opam-1.1.1/0000755000175000017500000000000012272210733010711 5ustar i33173i33173opam-1.1.1/Makefile0000644000175000017500000001401312272210733012350 0ustar i33173i33173-include Makefile.config LOCAL_OCPBUILD=./ocp-build/ocp-build -no-use-ocamlfind OCPBUILD ?= $(LOCAL_OCPBUILD) SRC_EXT=src_ext TARGETS = opam opam-admin opam-installer .PHONY: all all: $(LOCAL_OCPBUILD) META $(MAKE) clone $(MAKE) compile cold: ./shell/bootstrap-ocaml.sh env PATH=$$PATH:`pwd`/bootstrap/ocaml/bin ./configure env PATH=$$PATH:`pwd`/bootstrap/ocaml/bin $(MAKE) scan: $(LOCAL_OCPBUILD) $(OCPBUILD) -scan sanitize: $(LOCAL_OCPBUILD) $(OCPBUILD) byte: $(LOCAL_OCPBUILD) $(OCPBUILD) -byte opt: $(LOCAL_OCPBUILD) $(OCPBUILD) -asm OCAMLBUILD_FLAGS=\ -Is src/core,src/client,src/repositories,src/solver,src/scripts \ -use-ocamlfind -pkgs re.glob,re.pcre,re.str,re.perl,ocamlgraph,cmdliner,cudf,dose3 \ -classic-display with-ocamlbuild: autogen @for i in core repositories solver client; do\ echo Compiling opam-$$i;\ find src/$$i -type f \( -not -name opamMain.ml \) \ \( -name \*.ml -or -name \*.mly -or -name \*.mll \)\ | xargs -n 1 basename\ | awk -F. "{ print (toupper(substr(\$$1,0,1)) substr(\$$1,2)) }"\ > src/$$i/opam-$$i.mllib &&\ ocamlbuild $(OCAMLBUILD_FLAGS) opam-$$i.cma opam-$$i.cmxa;\ done;\ ocamlbuild $(OCAMLBUILD_FLAGS) opamMain.native opam_admin.native &&\ ln -sf _build/src/client/opamMain.native opam &&\ ln -sf _build/src/scripts/opam_admin.native opam-admin $(LOCAL_OCPBUILD): ocp-build/ocp-build.boot ocp-build/win32_c.c $(MAKE) -C ocp-build OCAMLFIND_DIR=$(shell ocamlfind printconf destdir) prepare: depends.ocp.in sed "s|%{lib}%|$(OCAMLFIND_DIR)|g" depends.ocp.in > depends.ocp autogen: src/core/opamGitVersion.ml src/core/opamScript.ml src/core/opamVersion.ml compile: $(LOCAL_OCPBUILD) autogen $(OCPBUILD) -init -scan $(TARGET) clone: src/core/opamVersion.ml $(MAKE) -C $(SRC_EXT) clean: rm -rf _obuild rm -f *.annot src/*.annot rm -f ocp-build.* rm -rf _build rm -rf config.log config.status META Makefile.config $(MAKE) -C $(SRC_EXT) clean $(MAKE) -C ocp-build clean rm -f $(OPAM_FULL_TARGZ) distclean: clean $(MAKE) -C $(SRC_EXT) distclean rm -f META Makefile.config config.log config.status rm -f src/core/opamVersion.ml src/core/opamGitVersion.ml src/core/opamScript.ml .PHONY: tests tests: $(MAKE) -C tests all tests-local: $(MAKE) -C tests local tests-git: $(MAKE) -C tests git %-install: @if [ -e _obuild/$*/$*.asm ]; then \ echo "install _obuild/$*/$*.asm" && \ cp _obuild/$*/$*.asm $(DESTDIR)$(prefix)/bin/$*; \ else \ echo "install _obuild/$*/$*.byte" && \ cp _obuild/$*/$*.byte $(DESTDIR)$(prefix)/bin/$*; \ fi %-install-with-ocamlbuild: @if [ -e $* ]; then\ echo "install $*" && cp $* $(DESTDIR)$(prefix)/bin/$*;\ fi META: META.in sed 's/@VERSION@/$(version)/g' < $< > $@ src/core/opamVersion.ml: @echo @echo " ERROR: you need to run ./configure." @echo @exit 1 .PHONY: src/core/opamGitVersion.ml src/core/opamGitVersion.ml: ocaml shell/get-git-id.ml $@ src/core/opamScript.ml: shell/ src/core/opamVersion.ml ocaml shell/crunch.ml "complete" < shell/opam_completion.sh > $@ ocaml shell/crunch.ml "complete_zsh" < shell/opam_completion_zsh.sh >> $@ ocaml shell/crunch.ml "switch_eval" < shell/opam_switch_eval.sh >> $@ .PHONY: uninstall install install-with-ocamlbuild install: mkdir -p $(DESTDIR)$(prefix)/bin $(MAKE) $(TARGETS:%=%-install) mkdir -p $(DESTDIR)$(mandir)/man1 && cp doc/man/* $(DESTDIR)$(mandir)/man1 install-with-ocamlbuild: mkdir -p $(DESTDIR)$(prefix)/bin $(MAKE) $(TARGETS:%=%-install-with-ocamlbuild) mkdir -p $(DESTDIR)$(mandir)/man1 && cp doc/man/* $(DESTDIR)$(mandir)/man1 uninstall: rm -f $(prefix)/bin/opam* rm -f $(mandir)/man1/opam* CORE_LIB = opam-core REPO_LIB = opam-repositories SOLVER_LIB = opam-solver CLIENT_LIB = opam-client CORE_NOMLI = opamGlobals.ml opamParser.ml opamLexer.ml opamLineLexer.ml CORE_MLI = $(foreach i, $(shell find src/core -name "*.mli"), $(notdir $i)) REPO_MLI = $(foreach i, $(shell find src/repositories -name "*.mli"), $(notdir $i)) SOLVER_MLI = $(foreach i, $(shell find src/solver -name "*.mli"), $(notdir $i)) CLIENT_MLI = $(foreach i, $(shell find src/client -name "*.mli"), $(notdir $i)) CORE_FILES = $(CORE_LIB:%=%.a) $(CORE_LIB:%=%.cma) $(CORE_LIB:%=%.cmxa)\ $(CORE_MLI:%.mli=%.cmi) $(CORE_NOMLI:%.ml=%.cmi) REPO_FILES = $(REPO_LIB:%=%.a) $(REPO_LIB:%=%.cma) $(REPO_LIB:%=%.cmxa)\ $(REPO_MLI:%.mli=%.cmi) SOLVER_FILES = $(SOLVER_LIB:%=%.a) $(SOLVER_LIB:%=%.cma) $(SOLVER_LIB:%=%.cmxa)\ $(SOLVER_MLI:%.mli=%.cmi) CLIENT_FILES = $(CLIENT_LIB:%=%.a) $(CLIENT_LIB:%=%.cma) $(CLIENT_LIB:%=%.cmxa)\ $(CLIENT_MLI:%.mli=%.cmi) FILES = $(CORE_FILES:%=_obuild/opam-core/%)\ $(REPO_FILES:%=_obuild/opam-repositories/%)\ $(SOLVER_FILES:%=_obuild/opam-solver/%)\ $(CLIENT_FILES:%=_obuild/opam-client/%) OCAMLBUILD_FILES =\ $(CORE_FILES:%=_build/src/core/%)\ $(REPO_FILES:%=_build/src/repositories/%)\ $(SOLVER_FILES:%=_build/src/solver/%)\ $(CLIENT_FILES:%=_build/src/client/%) .PHONY: libuninstall libinstall libinstall-with-ocamlbuild libinstall: META $(MAKE) libuninstall ocamlfind install opam META $(FILES) libinstall-with-ocamlbuild: META $(MAKE) libuninstall ocamlfind install opam META $(OCAMLBUILD_FILES) libuninstall: ocamlfind remove opam doc: compile $(MAKE) -C doc OPAM_FULL = opam-full-$(version) OPAM_FULL_TARGZ = $(OPAM_FULL).tar.gz OPAM_FILES = $(wildcard src_ext/*.tar.gz)\ $(wildcard src_ext/*.tbz)\ $(shell git ls-tree --name-only -r HEAD) prepare-archive: $(MAKE) -C src_ext distclean $(MAKE) clone rm -f $(OPAM_FULL) $(OPAM_FULL).tar.gz ln -s . $(OPAM_FULL) # we want OPAM_FILES to be up-to-date here complete-archive: tar cz $(addprefix $(OPAM_FULL)/,$(OPAM_FILES)) > $(OPAM_FULL).tar.gz rm -f $(OPAM_FULL) $(OPAM_FULL_TARGZ): $(MAKE) prepare-archive $(MAKE) complete-archive archive: $(OPAM_FULL_TARGZ) @ upload: $(OPAM_FULL_TARGZ) scp $(OPAM_FULL_TARGZ) webmaster@ocamlpro.com:pub/ configure: configure.ac m4/*.m4 aclocal -I m4 autoconf release: git tag -d latest || true git tag -a latest -m "Latest release" git tag -a $(version) -m "Release $(version)" $(MAKE) upload opam-1.1.1/doc/0000755000175000017500000000000012272210733011456 5ustar i33173i33173opam-1.1.1/doc/dev-manual/0000755000175000017500000000000012272210733013507 5ustar i33173i33173opam-1.1.1/doc/dev-manual/Makefile0000644000175000017500000000034012272210733015144 0ustar i33173i33173.PHONY: all all: dev-manual.pdf html: dev-manual.html %.pdf: %.tex pdflatex $* pdflatex $* %.html: %.tex hevea htmlmacros.hva $< %.txt: %.html links -dump $< > $@ clean: rm -f *~ *.log *.toc *.out *.bbl *.blg *.aux opam-1.1.1/doc/dev-manual/pdfswitch.sty0000644000175000017500000001103412272210733016242 0ustar i33173i33173%% %% This is file `pdfswitch.sty', %% generated with the docstrip utility. %% %% The original source files were: %% %% pdfswitch.dtx (with options: `package') %% %% IMPORTANT NOTICE: %% %% For the copyright see the source file. %% %% Any modified versions of this file must be renamed %% with new filenames distinct from pdfswitch.sty. %% %% For distribution of the original source see the terms %% for copying and modification in the file pdfswitch.dtx. %% %% This generated file may be distributed as long as the %% original source files, as listed above, are part of the %% same distribution. (The sources need not necessarily be %% in the same archive or directory.) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% \def\fileversion{0.0.2} \def\filedate{2003/07/12} \NeedsTeXFormat{LaTeX2e} \ProvidesPackage% {pdfswitch}% [\filedate\space Automatic switch between pdf and ps. v\fileversion] \RequirePackage{ae,aeguill} \RequirePackage{color} \RequirePackage{ifthen} \RequirePackage{ifpdf} \newboolean{nocolor@pdfswitch} \setboolean{nocolor@pdfswitch}{false} \DeclareOption{nocolor}{\setboolean{nocolor@pdfswitch}{true}} \newboolean{backref@pdfswitch} \setboolean{backref@pdfswitch}{false} \DeclareOption{backref}{\setboolean{backref@pdfswitch}{true}} \newboolean{pagebackref@pdfswitch} \setboolean{pagebackref@pdfswitch}{false} \DeclareOption{pagebackref}{\setboolean{pagebackref@pdfswitch}{true}} \newboolean{noborder@pdfswitch} \setboolean{noborder@pdfswitch}{false} \DeclareOption{noborder}{\setboolean{noborder@pdfswitch}{true}} \newboolean{plainpages@pdfswitch} \setboolean{plainpages@pdfswitch}{false} \DeclareOption{plainpages}{\setboolean{plainpages@pdfswitch}{true}} \ProcessOptions \definecolor{pdfurlcolor}{rgb}{0,0,0.6} \definecolor{pdfcitecolor}{rgb}{0,0.6,0} \definecolor{pdflinkcolor}{rgb}{0.6,0,0} %%%%%%%%%%%%%%%%%%%%%%%%% graphicx and thumbpdf %%%%%%%%%%%%%%%%%%%%%%%%%%%%% \ifpdf \usepackage[pdftex]{graphicx} %%% graphics for pdfLaTeX \DeclareGraphicsExtensions{.pdf} %%% standard extension for included graphics \usepackage[pdftex]{thumbpdf} %%% thumbnails for pdflatex \else \usepackage[dvips]{graphicx} %%% graphics for dvips \DeclareGraphicsExtensions{.ps,.eps} %%% standard extension for included graphics \fi %%%%%%%%%%%%%%%%%%%%%%%%% Basic options for hyperref %%%%%%%%%%%%%%%%%%%%%%%%% \ifpdf \edef\keys@pdfswitch{% pdftex, %%% hyper-references for pdflatex bookmarks=true,% %%% generate bookmarks ... bookmarksnumbered=true,% %%% ... with numbers hypertexnames=false,% %%% needed for correct links to figures !!! breaklinks=true% %%% break links if exceeding a single line } \else \edef\keys@pdfswitch{% ps2pdf, %%% hyper-references for ps2pdf bookmarks=true,% %%% generate bookmarks ... bookmarksnumbered=true,% %%% ... with numbers hypertexnames=false,% %%% needed for correct links to figures !!! breaklinks=true,% %%% breaks lines, but links are very small pdfborder={0 0 11.0} %%% border-width of frames will %%% be multiplied with 0.009 by ps2pdf } \fi \ifthenelse{\boolean{nocolor@pdfswitch}}{% \edef\keys@pdfswitch{\keys@pdfswitch,colorlinks=false}% }{ \edef\keys@pdfswitch{\keys@pdfswitch,colorlinks=true,% citecolor=pdfcitecolor, urlcolor=pdfurlcolor, linkcolor=pdflinkcolor, linkbordercolor={1 1 1}}% } \ifthenelse{\boolean{plainpages@pdfswitch}}{% }{ \edef\keys@pdfswitch{\keys@pdfswitch,plainpages=false}% } \ifthenelse{\boolean{noborder@pdfswitch}}{% \edef\keys@pdfswitch{\keys@pdfswitch,pdfborder={0 0 0}}% }{} \ifthenelse{\boolean{backref@pdfswitch}}{% \edef\keys@pdfswitch{\keys@pdfswitch,backref}% }{} \ifthenelse{\boolean{pagebackref@pdfswitch}}{% \edef\keys@pdfswitch{\keys@pdfswitch,pagebackref}% }{} \usepackage[\keys@pdfswitch]{hyperref} %%%%%%%%%%%%%%%%%%%%%%%%% HyperSetup %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \ifpdf \AtBeginDocument{ \hypersetup{ pdfauthor = {\@author}, pdftitle = {\@title}, pdfsubject = {\@ifundefined{@subject}{}{\@subject}}, pdfkeywords = {\@ifundefined{@keywords}{}{\@keywords}} } } %%% pdfcreator, pdfproducer, and Creation Date are automatically set by pdflatex !!! \pdfadjustspacing=1 %%% force LaTeX-like character spacing \else \AtBeginDocument{ } \fi \endinput %% %% End of file `pdfswitch.sty'. opam-1.1.1/doc/dev-manual/dev-manual.css0000644000175000017500000000261412272210733016255 0ustar i33173i33173/* ==== general presentation ==== */ body { padding: 0.4em 16% 3em 8%; } h1, h1 a, h2, h2 a, h3, h3 a { padding: 0 0 0 0.4em; } .titlemain, .titlerest { padding: 0.2em 3.8em; } pre { padding: 0.2em 0.4em; margin: 0.4em 0.6em; } p { padding: 0 0 0 0.8em; } dt { padding: 0 0 0 0.6em; } h1 { font-size: 1.6em; } h2 { font-size: 1.4em; } h3 { font-size: 1.2em; } h1 a { font-size: 1.0em; } h2 a { font-size: 1.0em; } h3 a { font-size: 1.0em; } a { text-decoration: none; } a:hover { text-decoration: underline; } /* ==== morning colors ==== */ body { color: #333; background-color: #F0F0F0; } pre { color: #224; background: #DDE; border: 1px solid #8AC; } h1, h1 a, h2, h2 a, h3, h3 a { color: #228; background: #CDF; } a { color: #08C; } a:hover { color: #06E; background: #DEF; } /* ==== evening colors ==== *\ body { color: #CCC; background-color: #226; } pre { color: #BDF; background: #447; border: 1px solid #46A; } h1, h1 a, h2, h2 a, h3, h3 a { color: #CCC; background: #359; } a { color: #6CF; } a:hover { color: #9EF; background: #448; } */ /* ==== sunny colors ==== *\ body { color: #333; background-color: #ffcd95; } pre { color: #422; background: #fdb50b; border: 1px solid #832809; } h1, h1 a, h2, h2 a, h3, h3 a { color: #672910; background: #ff9a0a; } a { color: #b94a48; } a:hover { color: #91310b; background: #fccb0d; } */ opam-1.1.1/doc/dev-manual/dev-manual.tex0000644000175000017500000014053712272210733016274 0ustar i33173i33173\documentclass[a4paper,10pt]{article} \usepackage{url} \usepackage{eurosym} %\usepackage[french]{babel} \usepackage[T1]{fontenc} \usepackage{pdfswitch} \usepackage{verbatim} \usepackage{fullpage} \usepackage{fancyvrb} \newenvironment{remark}[1][Remark]{\begin{trivlist} \item[\hskip \labelsep {\bfseries #1}]}{\end{trivlist}} \title{ OPAM: A Package Management System for OCaml\\ Developer Manual (version 1.1)\\ ~\ \\ ~\ \\} \author{Thomas GAZAGNAIRE\\ \url{thomas.gazagnaire@ocamlpro.com}\\ } \begin{document} \newcommand{\OPAM}{{\sc Opam}} \maketitle \vfill \tableofcontents \section*{Overview} \OPAM\ is a source-based package manager for OCaml. It supports multiple simultaneous compiler installations, flexible package constraints, and a Git-friendly development work-flow.\\ A package management system has typically two kinds of users: {\em end-users} who install and use packages for their own projects; and {\em packagers}, who create and upload packages. End-users want to install on their machine a consistent collection of {\em packages} -- a package being a collection of OCaml libraries and/or programs. Packagers want to take a collection of their own libraries and programs and make them available to other developpers.\\ This document describes the design of \OPAM\ to answer both of these needs. \subsection*{Conventions} In this document, \verb+$home+, \verb+$opam+, and \verb+$path+ are assumed to be defined as follows: \begin{itemize} \item {\tt \$home} refers to the end-user home path, typically {\tt /home/thomas/} on linux and {\tt /Users/thomas/} on OSX. % {\tt % C:\textbackslash Documents and Settings\textbackslash % thomas\textbackslash} on Windows. \item {\tt \$opam} refers to the filesystem subtree containing the client state. Default directory is {\tt \$home/.opam}. \item {\tt \$path} refers to a list of paths in the packager filesystem, where lives the collection of programs ({\tt ocamlc}, {\tt ocamldep}, {\tt ocamlopt}, {\tt ocamlbuild}, ...). \end{itemize} User variables are written in capital letters, prefixed by \verb+$+. For instance package names will be written \verb+$NAME+, package versions \verb+$VERSION+, and the version of the ocaml compiler currently installed \verb+$SWITCH+.\\ This document is organized as follows: Section~\ref{section:packages} describes the core of \OPAM, e.g. the management of packages. Section~\ref{section:repositories} describes how repositories are handled, Section~\ref{section:switches} focus on compiler switches and finally Section~\ref{section:config} explain how packages can define configuration variables (which can be later used by the build system). \section{Managing Packages} \label{section:packages} \subsection{State} The client state is stored on the filesystem, under {\tt \$opam}. All the configurations files, libraries and binaries related to a specific instance of the OCaml compiler in \verb+$opam/$SWITCH+, where \verb+$SWITCH+ is the name of that specific compiler instance. See Section~\ref{section:switches} for more details about compiler switches. \begin{itemize} \item {\tt \$opam/config} is the main configuration file. It defines the version of \OPAM, the repository addresses and the current compiler version. The file format is described in \S\ref{file:config}. \item \verb+$opam/packages/$NAME/$NAME.$VERSION/opam+ is the specification for the package \verb+$NAME+ with version \verb+$VERSION+ (which might not be installed). The format of {\tt opam} files is described in \S\ref{file:opam}. \item \verb+$opam/packages/$NAME/$NAME.$VERSION/descr+ contains the description for the version \verb+$VERSION+ of package \verb+$NAME+ (which might not be installed). The first line of this file is the package synopsis. \item \verb+$opam/packages/$NAME/$NAME.$VERSION/url+ contains the upstream location for version \verb+$VERSION+ of package \verb+$NAME+ (which might not be installed). The format of {\tt url} files is described in \S\ref{file:url}. \item \verb+$opam/packages/$NAME/$NAME.$VERSION/files/+ contains the eventual overlay files on top of the upstream sources, for version \verb+$VERSION+ of package \verb+$NAME+ (which might not be installed). This files are copied in the build directory before building and installing a package. \item \verb+$opam/archives/$NAME.$VERSION+opam.tar.gz+ contains the source archives for the version \verb+$VERSION+ of package \verb+$NAME+. This archive might be a bit different from the upstream library as it might have been repackaged by \OPAM\ to include the evenutal overlay files. \item \verb+$opam/packages.dev.+ contains cached information for development packages. \OPAM\ uses it on update to check which package needs to be upgraded. \end{itemize} \subsection{Files} \subsubsection{General Syntax of Structured Files} \label{file:general} Most of the files in the client and server states share the same syntax defined in this section. \begin{description} \item[Comments] Two kinds of comments are available: the usual \verb+(* ... *)+ OCaml comment blocks and also \verb+#+ which discard everything until the end of the current line. \item[Base types] The base types for values are: \begin{itemize} \item {\tt BOOL} is either {\tt true} or {\tt false} \item {\tt STRING} is a doubly-quoted OCaml string, for instance: {\tt "foo"}, {\tt "foo-bar"}, $\ldots$ \item {\tt SYMBOL} contains only non-letter and non-digit characters, for instance: {\tt =}, {\tt <=}, $\ldots$ Some symbols have a special meaning and thus are not valid {\tt SYMBOL}s: ``\verb+(+ \verb+)+ \verb+[+ \verb+]+ \verb+{+ \verb+}+ \verb+:+''. \item {\tt IDENT} starts with a letter and is followed by any number of letters, digit and symbols, for instance: {\tt foo}, {\tt foo-bar}, $\ldots$. \end{itemize} \item[Compound types] Types can be composed together to build more complex values: \begin{itemize} \item {\tt X Y } is a space-separated pair of value. \item {\tt X | Y } is a value of type either {\tt X} or {\tt Y}. \item {\tt ?X} is zero or one occurrence of a value of type {\tt X}. \item {\tt X+} is a space-separated list of values of at least one value of type {\tt X}. \item {\tt X*} is a space-separated list of values of values of type {\tt X} (it might contain no value). \end{itemize} \end{description} All structured files share the same syntax: {\small \begin{Verbatim}[frame=single] := * := IDENT : | ?IDENT: | IDENT STRING { + } := BOOL | INT | STRING | SYMBOL | IDENT | [ + ] | value { + } \end{Verbatim} } \subsubsection{Global Configuration File: {\tt config}} \label{file:config} \verb+$opam/config+ follows the syntax defined in \S\ref{file:general} with the following restrictions: {\small \begin{Verbatim}[frame=single] := opam-version: "1" repositories: [ STRING+ ] switch: STRING cores: INT \end{Verbatim} } The field {\tt opam-version} indicates the current \OPAM\ format. The field {\tt repositories} contains the list of \OPAM\ repositories. The field {\tt switch} corresponds to the current compiler instance. The field {\tt cores} is the number of parallel process that \OPAM\ will use when trying to build the packages. \subsubsection{Package Specification files: {\tt opam}} \label{file:opam} \verb+$opam/packages/$NAME/$NAME.$VERSION/opam+ follows the syntax defined in \S\ref{file:general} with the following restrictions: {\small \begin{Verbatim}[frame=single] := opam-version: "1" ?name: STRING ?version: STRING maintainer: STRING ?homepage: STRING ?authors: [ STRING+ ] ?doc: STRING ?license: STRING ?tags: [ STRING+ ] ?subst: [ STRING+ ] ?patches: [ (STRING ?{ } )+ ] ?build: commands ?build-doc: commands ?build-test: commands ?remove: commands ?depends: [ + ] ?depopts: [ + ] ?depexts: [ [[STRING+] [STRING+]]+ ] ?conflicts: [ + ] ?messages: [ (STRING ?{ } )+ ] ?post-messages: [ (STRING ?{ } )+ ] ?available: [ ] ?os: [ + ] ?ocaml-version: [ + ] ?libraries: [ STRING+ ] ?syntax: [ STRING+ ] := STRING | IDENT := [ ( ?{ })+ ] ?{ } := | [ + ] := | ! | | formula() := '&' | '|' | ( ) | := STRING | STRING { } := STRING := '=' | '<' | '>' | '>=' | '<=' | '!=' := | := | := STRING | '!' STRING \end{Verbatim} } \begin{itemize} \item The first line specifies the \OPAM\ version. \item The content of {\tt name} is \verb+$NAME+, the content of {\tt version} is \verb+$VERSION+. Both fields are optional are they can be inferred from the filename. \item The content of {\tt maintainer} is the contact address of the package maintainer. \item The {\tt license}, {\tt homepage} {\tt doc} and {\tt authors} fields are optional. {\tt doc} should be the address of the online documentation for the package. \item The {\tt tags} field is optional contains a list of tags to classify the package. \item The content of {\tt subst} is the list of files to substitute variable (see \S\ref{file:subst} for the file format and \S\ref{section:config} for the semantic of file substitution). \item The content of {\tt patches} is a list of patches to be applied. Substitutions happen before patch application, so patches can contain strings which will substituted. \item The content of {\tt build} is the list of commands to run in order to build the package libraries. The build script should build all the libraries and syntax extensions exported by the package and it should produce the platform-specific configuration and install files (e.g. \verb+$NAME.config+ and \verb+$NAME.install+, see \S\ref{file:config} and \S\ref{file:install}). Each command and command argument is substituted (see \S\ref{file:subst} and \S\ref{section:config}, with the identifier {\tt X} being equivalent to the string {\tt "\%\{X\}\%"}) and can be followed by an optional filter, whose evaluation will result in the command (or the command argument) being executed or not. Filter expressions are typed and must evaluate to a boolean and binary operations apply to version strings. A typical example is OS-related filters, where we can choose to execute commands depending on the current OS: \begin{Verbatim} build: [ ["mv" "Makefile.unix" "Makefile"] {os != "win32"} ["mv" "Makefile.win32" "Makefile"] {os = "win32"} [make] ] \end{Verbatim} \item {\tt build-doc} is optional and describes how the documentation is built. \item {\tt build-test} is optional and describes how the tests are built and run. \item The content of {\tt remove} is the command to run before deleting the installed file. \item The {\tt depends}, {\tt depopts} and {\tt conflicts} fields contain formulas over package names, optionally parametrized by version constraints. Some examples or package formula: \begin{itemize} \item A package name: {\tt "foo"}; \item A package name with version constraints: \verb+"foo" {>= "1.2" & <= "3.4"}+ \end{itemize} {\tt depends} is an {\em AND} formula, which means that top-level \verb+&+ are not mandatory. For instance, \verb+ "foo" {<= "1.2"} ("bar" | "gna" {= "3.14"})+ has the following semantic: ``{\em both any version of package {\tt "foo"} lesser or equal to $1.2$ and either any version of package {\tt "bar"} or the version $3.14$ of package {\tt "gna"}.}'' \\ The {\tt depopts} field contains a {\em OR} formula over package names, which means that top-level \verb+|+ are not mandatory. This field express optional dependencies that \OPAM\ will not try to install. However, when installing a new package it will check if it is an optional dependency of already installed packages. If it is the case, it will re-install the packages (and their transitive forward-dependency closure). \item The {\tt depexts} field is optional and contains tags describing the external dependencies. It contains pairs of lists of the form \verb+[ [predicates] [ext-packages] ]+. The predicates are tags that must be specified to {\tt opam install}'s {\tt --external} flag to get the corresponding external package set. Tags should normally be distribution or architecture names (e.g. \verb+"debian"+, \verb+"x86"+, in which case the \verb+ext-package+ list will correspond to {\tt apt-get} package names). \item The {\tt messages} field (since version $1.0.1$) is used to display an alternative message when prompting a solution implying the given package. The typical use-case is to tell the user that some functionality will not be available as some optional dependencies are not installed. \item The {\tt post-messages} field (since version $1.1.0$) allows to print specific messages to the user after the end of installation. The special boolean variable \verb+failure+ is defined in the scope of the filter, and can be used to print messages in case there was an error (typically, a hint on how it can be resolved, or a link to an open issue). \verb+success+ is also defined as syntactic sugar for \verb+!failure+. \item The {\tt available} field (since version $1.1.0$) can be used to add constraints on the OS and OCaml versions currently in use, using the built-in \verb+os+ and \verb+ocaml-version+ variables. In case the filter is not valid, the package is disabled. The {\tt os} and {\tt ocaml-version} fields are deprecated, please use {\tt available} instead in newly created packages. \item The {\tt libraries} and {\tt syntax} fields contain the libraries and syntax extensions defined by the package. See Section~\ref{section:config} for more details. \end{itemize} \subsubsection{URL files: {\tt url}} \label{file:url} The syntax of {\tt url} files follows the one described in \S\ref{file:general} with the following restrictions: { \begin{Verbatim}[frame=single] := ?src: STRING ?archive: STRING ?http: STRING ?local: STRING ?git: STRING ?darcs: STRING ?hg: STRING ?checksum: STRING \end{Verbatim} } {\tt src}, {\tt archive}, {\tt http}, {\tt local}, {\tt git}, {\tt hg}, {\tt darcs} are the location where the package upstream sources can be downloaded. It can be: \begin{itemize} \item A directory on the local file system (which will be copied to the build directory). Use {\tt local}. \item An archive file on the local file system (which will be unpacked into the build directory). Use {\tt local}. \item An archive file at a URL that is understood by either curl or wget (which will be fetched using either curl (if that available) or wget (if curl is not available) and unpacked into the build directory). Use {\tt http}. \item a version-controlled repository under git, darcs or hg, or a specific commit, tag or branch in that repository if the string ends by \verb+#+ or \verb+#+ or \verb+#+. Use {\tt git}, {\tt hg} or {\tt darcs}. \item \OPAM\ will try to guess the source kind if you use {\tt src} or {\tt archive}. \end{itemize} \subsection{Commands} \subsubsection{Creating a Fresh Client State} \label{opam-init} When an end-user starts \OPAM\ for the first time, he needs to initialize \verb+$opam/+ in a consistent state. In order to do so, he should run: \begin{verbatim} $ opam init [--kind $KIND] $REPO $ADDRESS [--comp $VERSION] \end{verbatim} Where: \begin{itemize} \item \verb+$KIND+ is the kind of \OPAM\ repository (default is {\tt http}); \item \verb+$REPO+ is the name of the repository (default is {\tt default}); and \item \verb+$ADDRESS+ is the repository address (default is \verb+http://opam.ocamlpro.com/pub+). \item \verb+$COMP+ is the compiler version to use (default is the version of the compiler installed on the system). \end{itemize} This command will: \begin{enumerate} \item Create the file \verb+$opam/config+ (as specified in \S\ref{file:config}) \item Create an empty \verb+$opam/$SWITCH/installed+ file, \verb+$SWITCH+ %being the result of ``{\tt ocamlc -version}''. is the version from the OCaml used to compile \verb+$opam+. In particular, we will not fail now if there is no \verb+ocamlc+ in \verb+$path+. \item Initialize \verb+$opam/repo/$REPO+ by running the appropriate operations (depending on the repository kind). \item Copy all \OPAM\ and description files (ie. copy every file in \verb+$opam/repo/$REPO/packages/+ to \verb+$opam/packages/+). \item Create \verb+$opam/repo/index+ and for each version \verb+$VERSION+ of package \verb+$NAME+ appearing in the repository, append the line \verb+'$REPO $NAME $VERSION'+ to the file. \item Create the empty directories \verb+$opam/archives+, \verb+$opam/$SWITCH/lib/+, \verb+$opam/$SWITCH/bin/+ and \verb+$opam/$SWITCH/doc/+. \end{enumerate} \subsubsection{Listing Packages} \label{opam-list} When an end-user wants to have information on all available packages, he should run: \begin{verbatim} $ opam list \end{verbatim} This command will parse \verb+$opam/$SWITCH/installed+ to know the installed packages, and \verb+$opam/packages/$NAME/$NAME.$VERSION/opam+ to get all the available packages. It will then build a summary of each packages. The description of each package will be read in \verb+$opam/packages/$NAME/$NAME.$VERSION/descr+ if it exists. For instance, if {\tt batteries} version {\tt 1.1.3} is installed, {\tt ounit} version {\tt 2.3+dev} is installed and {\tt camomille} is not installed, then running the previous command should display: \begin{verbatim} batteries 1.1.3 Batteries is a standard library replacement ounit 2.3+dev Test framework camomille -- Unicode support \end{verbatim} \subsubsection{Getting Package Info} In case the end-user wants a more details view of a specific package, he should run: \begin{verbatim} $ opam info $NAME \end{verbatim} This command will parse \verb+$opam/$SWITCH/installed+ to get the installed version of \verb+$NAME+, will process \verb+$opam/repo/index+ to get the repository where the package comes from and will look for \verb+$opam/packages/$NAME/$NAME.$VERSION/opam+ to get available versions of \verb+$NAME+. It can then display: \begin{verbatim} package: $NAME version: $VERSION versions: $VERSION1, $VERSION2, ... libraries: $LIB1, $LIB2, ... syntax: $SYNTAX1, $SYNTAX2, ... repository: $REPO description: $SYNOPSIS $LINE1 $LINE2 $LINE3 ... \end{verbatim} \subsubsection{Installing a Package} \label{opam-install} When an end-user wants to install a new package, he should run: \begin{verbatim} $ opam install $NAME \end{verbatim} This command will: \begin{enumerate} \item Compute the transitive closure of dependencies and conflicts of packages using the dependency solver (see \S\ref{deps}). If the dependency solver returns more than one answer, the tool will ask the user to pick one, otherwise it will proceed directly. The dependency solver should also mark the packages to recompile. \item The dependency solver sorts the collections of packages in topological order. Then, for each of them do: \begin{enumerate} \item Check whether the package is already installed by looking for the line \verb+$NAME $VERSION+ in \verb+$opam/$SWITCH/installed+. If not, then: \item Look into the archive cache to see whether it has already been downloaded. The cache location is: \verb+$opam/archives/$NAME.VERSION.tar.gz+ \item If not, process \verb+$opam/repo/index/+ (see \ref{section:repositories}) to get the repository \verb+$REPO+ where the archive is available and then ask the repository to download the archive if necessary. Once this is done, the archive might become available in \verb+$opam/repo/$REPO/archives/+. It it is, copy it in the global state (in \verb+$opam/archives+). If it is not, download it upstream by looking at \verb|$opam/packages/$NAME/$NAME.$VERSION/url| and add the eventual overlay files located in \verb|$opam/packages/$NAME/$NAME.$VERSION/files|. Note: this files can be overwritten by anything present in \verb|$opam/$SWITCH/overlay/$NAME.$VERSION/|. \item Decompress the archive into \verb+$opam/$SWITCH/build/$NAME.$VERSION/+. \item Substitute the required files. \item Run the list of commands to build the package with \verb+$opam/$SWITCH/bin+ in the path. \item Process \verb+$opam/$SWITCH/build/$NAME.$VERSION/$NAME.install+ to install the created files. The file format is described in \S\ref{file:install}. \item Install the installation file \verb+$opam/$SWITCH/build/$NAME.$VERSION/$NAME.install+ in \verb+$opam/$SWITCH/install/+ and the configuration file \verb+$opam/$SWITCH/build/$NAME.$VERSION/$NAME.config+ in \verb+$opam/$SWITCH/config/+. \end{enumerate} \end{enumerate} \subsubsection{Updating Index Files} \label{opam-update} When an end-user wants to know what are the latest packages available, he will write: \begin{verbatim} $ opam update \end{verbatim} This command will follow the following steps: \begin{itemize} \item Update each repositories in \verb+$opam/config+. \item For each repositories in \verb+$opam/config+, call the corresponding update scripts. Then, look at the difference between the digest of files in the global state and in each repositories, and fix the discrepancies (while notifying the user) if necessary. Here, the order in which the repositories are specified is important: the first repository containing a given version for a package will be the one providing it (this can be changed manually by editing \verb+$opam/repo/index+ later). \item For each installed pinned et development packages, look at what changed upstream and if something has changed, update \verb+$opam/$SWITCH/reinstall+ accordingly (for each compiler version \verb+$SWITCH+). \item Packages in \verb+$opam/$SWITCH/reinstall+ will be reinstalled (or upgraded if a new version is available) on the next {\tt opam upgrade} (see \S\ref{opam-upgrade}), with \verb+$SWITCH+ being the current compiler version when the upgrade command is run. \end{itemize} \subsubsection{Upgrading Installed Packages} \label{opam-upgrade} When an end-user wants to upgrade the packages installed on his host, he will write: \begin{verbatim} $ opam upgrade \end{verbatim} This command will: \begin{itemize} \item Call the dependency solver (see \S\ref{deps}) to find a consistent state where {\bf most} of the installed packages are upgraded to their latest version. Moreover, packages listed in \verb+$opam/$SWITCH/reinstall+ will be reinstalled (or upgraded if a new version is available). It will install each non-installed packages in topological order, similar to what it is done during the install step, See \S\ref{opam-install}. \item Once this is done the command will delete \verb+$opam/$SWITCH/reinstall+. \end{itemize} \subsubsection{Removing Packages} \label{opam-remove} When the user wants to remove a package, he should write: \begin{verbatim} $ opam remove $NAME \end{verbatim} This command will check whether the package \verb+$NAME+ is installed, and if yes, it will display to the user the list packages that will be uninstalled (ie. the transitive closure of all forward-dependencies). If the user accepts the list, all the packages should be uninstalled, and the client state should be let in a consistent state. \subsubsection{Dependency Solver} \label{deps} Dependency solving is a hard problem and we do not plan to start from scratch implementing a new SAT solver. Thus our plan to integrate (as a library) the Debian depency solver for CUDF files, which is written in OCaml. \begin{itemize} \item the dependency solver should run on the client; and \item the dependency solver should take as input a list of packages (with some optional version information) the user wants to install, upgrade and remove and it should return a consistent list of packages (with version numbers) to install, upgrade, recompile and remove. \end{itemize} \section{Managing Compiler Switches} \label{section:switches} \OPAM\ is able to manage concurrent compiler installations. \subsection{State} Compiler descriptions are stored in two files: \begin{itemize} \item \verb|$opam/compilers/$VERSION/$VERSION[+$TAG]/comp| contains the meta-data for a given compiler.\verb+$VERSION+ is the compiler version and \verb+$TAG+ an optional tag (such as \verb|4.01+fp|). The format of {\tt .comp} file is described in \ref{file:comp}. \item (optional) \verb|$opam/compilers/$VERSION/$VERSION[+$TAG]/descr| contains the description of that compiler. \verb+$VERSION+ is the compiler version and \verb+$TAG+ an optional tag (such as \verb|4.01+fp|). The first line of that line is used as synopsis and is displayed with {\tt opam repository list}. \end{itemize} Switch-related meta-data are stored under \verb+$opam/$SWITCH/+: \begin{itemize} \item \verb+$opam/$SWITCH/installed+ is the list of installed packages for the compiler instance \verb+$SWITCH+. The file format is described in \S\ref{file:installed}. \item \verb+$opam/$SWITCH/installed.root+ is the list of installed packages roots for the compiler instance \verb+$SWITCH+. The file format is described in \S\ref{file:installed}. A package root has been explicitely installed by the user. \item \verb+$opam/$SWITCH/config/$NAME.config+ is a platform-specific configuration file of for the installed package \verb+$NAME+ with the compiler instance \verb+$SWITCH+. The file format is described in \S\ref{file:config}. \item \verb+$opam/$SWITCH/install/$NAME.install+ is a platform-specific package installation file for the installed package \verb+$NAME+ with the compiler instance \verb+$SWITCH+. The file format is described in \S\ref{file:install}. \item \verb+$opam/$SWITCH/lib/$NAME/+ contains the libraries associated to the installed package \verb+$NAME+ with the compiler instance \verb+$SWITCH+. \item \verb+$opam/$SWITCH/doc/$NAME/+ contains the documentation associated to the installed package {\tt NAME} with the compiler instance \verb+$SWITCH+. \item \verb+$opam/$SWITCH/bin/+ contains the program files for all installed packages with the compiler instance \verb+$SWITCH+. \item \verb+$opam/$SWITCH/build/$NAME.$VERSION/+ is a tempory folder used to build package \verb+$NAME+ with version \verb+$VERSION+, with compiler instance \verb+$SWITCH+. \item \verb+$opam/$SWITCH/reinstall+ contains the list of packages which has been changed upstream since the last upgrade. This can happen for instance when a packager uploads a new archive or fix the {\tt opam} file for a specific package version. Every package appearing in this file will be reinstalled (or upgraded if a new version is available) during the next upgrade when the current instance of the compiler is \verb+$SWITCH+. The file format is similar to the one described in \S\ref{file:installed}. \item \verb+$opam/$SWITCH/pinned+ contains the list of pinned packages. The file format is described in \S\ref{file:pinned}. \item \verb+$opam/$SWITCH/overlay/$NAME.$VERSION/+ contains overlay files for the version \verb+$VERSION+ of package \verb+$NAME+, for the switch \verb+$SWITCH+. These possible overlay files are {\tt opam}, {\tt url}, {\tt descr} or the directory {\tt files/}. If one of this file (or directory) is present, the file (or directory) will be used instead of the global one. \item \verb+$opam/$SWITCH/packages.dev+ contains cached information for dev and pinned packages. \OPAM\ uses it on update to check which package needs to be upgraded. \end{itemize} \subsection{Files} \subsubsection{Package List: {\tt installed} and {\tt reinstall}} \label{file:installed} The following configuration files: \verb+$opam/$SWITCH/installed+, \verb+$opam/$SWITCH/reinstall+, and \verb+$opam/repo/$REPO/updated+ follow a very simple syntax. The file is a list of lines which contains a space-separated name and a version. Each line \verb+$NAME $VERSION+ means that the version \verb+$VERSION+ of package \verb+$NAME+ has been compiled with the compiler instance \verb+$SWITCH+ and has been installed on the system in \verb+$opam/$SWITCH/lib/$NAME+ and \verb+$opam/$SWITCH/bin/+. \\ For instance, if {\tt batteries} version {\tt 1.0+beta} and {\tt ocamlfind} version {\tt 1.2} are installed, then \verb+$opam/$SWITCH/installed+ will contain: {\small \begin{Verbatim}[frame=single] batteries 1.0+beta ocamlfind 1.2 \end{Verbatim} } \subsubsection{Compiler Description Files: {\tt comp}} \label{file:comp} The syntax of {\tt comp} files follows the one described in \S\ref{file:general} with the following restrictions: { \begin{Verbatim}[frame=single] := opam-version: "1" name: STRING ?src: STRING ?archive: STRING ?http: STRING ?local: STRING ?git: STRING ?darcs: STRING ?hg: STRING ?make: STRING+ ] ?build: [[STRING+]] ?patches: [ STRING+ ] ?configure: [ STRING+ ] ?bytecomp: [ STRING+ ] ?asmcomp: [ STRING+ ] ?bytelink: [ STRING+ ] ?asmlink: [ STRING+ ] ?packages: ?requires: [ STRING+ ] ?pp: [ + ] ?preinstalled: BOOL ?env: [ + ] := CAMLP4 { STRING+ } | STRING+ := IDENT STRING := '=' | '+=' | '=+' | ':=' | '=:' \end{Verbatim} } \begin{itemize} \item {\tt name} is the compiler name, it should be identical to the filename. \item {\tt src}, {\tt archive}, {\tt http}, {\tt local}, {\tt git}, {\tt hg}, {\tt darcs} are the location where the compiler sources can be downloaded. It can be: \begin{itemize} \item A directory on the local file system (which will be linked or, if file system doesn't support links, copied to the build directory). Use {\tt local}. \item An archive file on the local file system (which will be unpacked into the build directory). Use {\tt local}. \item An archive file at a URL that is understood by either curl or wget (which will be fetched using either curl (if that available) or wget (if curl is not available) and unpacked into the build directory). Use {\tt http}. \item a version-controlled repository under git, darcs or hg, or a specific commit, tag or branch in that repository if the string ends by \verb+#+ or \verb+#+ or \verb+#+. Use {\tt git}, {\tt hg} or {\tt darcs}. \item \OPAM\ will try to guess the source kind if you use {\tt src} or {\tt archive}. \end{itemize} \item {\tt patches} are optional patch addresses, available via {\tt http} or locally on the filesystem. \item {\tt configure} are the optional flags to pass to the configure script. The order is relevant: {\tt --prefix=\$opam/SWITCH/} will be automatically added at the end to these options. Remark that if these flags contain {\tt --bindir}, {\tt --libdir}, and {\tt --mandir}, then every {\tt --prefix} will be ignored by {\tt configure}. \item {\tt make} are the flags to pass to {\tt make}. It must at least contain some target like {\tt world} or {\tt world.opt}. If {\tt make} is not present, \OPAM\ will execute all the commands listed in {\tt build}. \item {\tt bytecomp}, {\tt asmcomp}, {\tt bytelink} and {\tt asmlink} are the compilation and linking flags to pass to the OCaml compiler. They will be taken into account by the \verb+opam config+ command (see \S\ref{opam-config}). \item {\tt packages} is the list of packages to install just after the compiler installation finished. These libraries will not consider what is in the {\tt requires} nor {\tt pp} (as {\tt requires} and {\tt pp} might want to use things already installed with {\tt packages}). \item {\tt requires} is a list of libraries and syntax extensions dependencies which will be added to every packages installed with this compiler. The libraries and syntax extensions should be present in packages defined in {\tt packages}, otherwise an error should be thrown. \item {\tt pp} is the command to use with the {\tt -pp} command-line argument. It is either a full command line or a {\tt camlp4} command, such as \verb+CAMLP4 [ "pp-trace" ]+: this will look for the compilation flags for the syntax extension \verb+"pp-trace"+ and expand the {\tt camlp4} command-line accordingly. All the syntax extensions used should be present in {\tt packages}. \item {\tt preinstall} is {\tt true} when the version of the compiler available in the path is the same as {\tt name}. \item {\tt env} is the list of environment variables to set in the given compiler switch: \begin{itemize} \item {\tt VAR = "value"} set the variable to the given value; \item {\tt VAR += "value"} prepend the given value to the variable; \item {\tt VAR =+ "value"} append the given value to the variable; \item {\tt VAR := "value"} prepend the given value to the variable, separated by a colon. If the variable was empty, add the colon anyway. \item {\tt VAR =: "value"} append the given value to the variable, separated by a colon. If the variable was empty, add the colon anyway. \end{itemize} \end{itemize} For instance the file, {\tt 3.12.1+memprof.comp} describes OCaml, version $3.12.1$ with the memory profiling patch enabled: \begin{verbatim} opam-version: "1" name: "3.12.1" src: "http://caml.inria.fr/pub/distrib/ocaml-3.12/ocaml-3.12.1.tar.gz" make: [ "world" "world.opt" ] patches: [ "http://bozman.cagdas.free.fr/documents/ocamlmemprof-3.12.0.patch" ] env: [ CAML_LD_LIBRARY_PATH = "%{lib}%/stublibs" ] \end{verbatim} And the file {\tt trunk-g-notk-byte.comp} describes OCaml from SVN trunk, with no {\em tk} support and only in bytecode, and all the libraries built with {\tt -g}: \begin{verbatim} opam-version: "1" name: "trunk-g-notk-byte" src: "http://caml.inria.fr/pub/distrib/ocaml-3.12/ocaml-3.12.1.tar.gz" configure: [ "-no-tk" ] make: [ "world" ] bytecomp: [ "-g" ] bytelink: [ "-g" ] env: [ CAML_LD_LIBRARY_PATH = "%{lib}%/stublibs" ] \end{verbatim} \subsubsection{Package installation files: {\tt *.install}} \label{file:install} \verb+$opam/$SWITCH/install/NAME.install+ follows the syntax defined in \S\ref{file:general} with the following restrictions: {\small \begin{Verbatim}[frame=single] := ?lib: [ + ] ?bin: [ + ] ?sbin: [ + ] ?toplevel: [ + ] ?share: [ + ] ?etc: [ + ] ?doc: [ + ] ?misc: [ + ] ?stublibs: [ + ] ?man: [ + ] := STRING | STRING { STRING } \end{Verbatim} } \begin{itemize} \item Files listed under {\tt lib} are copied into \verb+$opam/$SWITCH/lib/$NAME/+. \item Files listed under {\tt bin} are copied into \verb+$opam/$SWITCH/bin/+. \item Files listed under {\tt sbin} are copied into \verb+$opam/$SWITCH/sbin/+. \item Files listed under {\tt doc} are copied into \verb+$opam/$SWITCH/doc/$NAME/+. \item Files listed under {\tt share} are copied into \verb+$opam/$SWITCH/share/$NAME/+. \item Files listed under {\tt etc} are copied into \verb+$opam/$SWITCH/etc/$NAME/+. \item Files listed under {\tt toplevel} are copied into \verb+$opam/$SWITCH/toplevel+. \item Files lister under {\tt stublibs} are copied into \verb+$opam/$SWITCH/lib/stublibs/+ \item Files listed under {\tt man} are copied into \verb+$opam/$SWITCH/man/man3+. You can change the sub-directory by setting the right optional argument (for instance: \verb+man: [ "foo.1" {"man1"} ]+. \item Files listed under {\tt misc} are processed as follows: for each pair \verb+$SRC { $DST }+, the tool asks the user if he wants to install \verb+$SRC+ to the absolute path \verb+$DST+. \end{itemize} General remarks: \begin{itemize} \item You control where the files are copied under the given prefix by using the optional argument. For instance: \verb+doc: [ "_build/foo.html" {"foo/index.html"} ]+ will copy the given HTML page under \verb+$opam/$SWITCH/doc/$NAME/foo/index.html+. \item \OPAM\ will try to install all the files in sequence, and it will fail in case a source filename is not available. To tell \OPAM\ a source filename might not be generated (because of byte/native constraints or because of optional dependencies) the source filename should start with \verb+?+. \item It is much cleaner if the underlying build-system can generate the right \verb+$NAME.install+ files, containing the existing files only. \end{itemize} \subsubsection{Pinned Packages: {\tt pinned}} \label{file:pinned} \verb+$opam/$SWITCH/pinned+ contains a list of lines of the form: \begin{Verbatim} \end{Verbatim} \begin{itemize} \item \verb++ is the name of the pinned package \item \verb++ is the kind of pinning. This could be \verb+version+, \verb+local+, \verb+git+ or \verb+darcs+. \item \verb++ is either the version number (if kind is \verb+version+) or the path to synchronize with. \end{itemize} \subsection{Commands} \subsubsection{Switching Compiler Version} If the user wants to switch to another compiler version, he should run: \begin{verbatim} $ opam switch [-alias-of $COMPILER] $SWITCH \end{verbatim} This command will: \begin{itemize} \item If \verb+$COMPILER+ is not set, set it to \verb+$SWITCH+ \item Look for an existing \verb+$opam/$COMPILER+ directory. \begin{itemize} \item If it exists, then change the {\tt ocaml-version} content to \verb+$COMPILER+ in \verb+$opam/config+. \item If it does not exist, look for an existing \verb|$opam/compilers/$VERSION/$VERSON[+$TAG]/comp|, where \verb|$COMPILER = $VERSION[+TAG]| If the file does not exists, the command will fail with a well-defined error. \item If the file exist, then build the new compiler with the right options (and pass \verb+--prefix $opam/$SWITCH+ to \verb+./configure+) and initialize everything in \verb+$opam/+ in a consistent state as if ``\verb+opam init+'' has just been called. \item Update the file \verb+$opam/aliases+ with the line \verb+$SWITCH $COMPILER+ \end{itemize} \end{itemize} \section{Managing Repositories} \label{section:repositories} \subsection{State} \label{state-repo} Configuration files for the remote repository \verb+REPO+ are stored in \verb+$opam/repo/$REPO+. Repositories can be of different kinds (stored on the local filesystem, available via HTTP, stored under git, $\ldots$); they all share the same filesystem hierachy, which is updated by different operations, depending on the repository kind. \begin{itemize} \item \verb+$opam/repo/$REPO/version+ contains the minimum version of \OPAM\ which can read that repository meta-data. \item \verb+$opam/repo/$REPO/config+ contains the configuration of the repository \verb+$REPO+. % The format of repository config % files is described in \S\ref{file:repo-config}. \item \verb+$opam/repo/$REPO/packages/$PREFIX/$NAME.$VERSION/opam+ is the {\tt opam} file for the package \verb+$NAME+ with version \verb+$VERSION+ (which might not be installed) with any possible \verb+$PREFIX+. The format of {\tt opam} files is described in \S\ref{file:opam}. \item (optional) \verb+$opam/repo/$REPO/packages/$PREFIX/$NAME.$VERSION/descr+ contains the textual description for the version \verb+$VERSION+ of package \verb+$NAME+ (which might not be installed) with any possible \verb+$PREFIX+ -- it should be in the same loacation as the corresponding {\tt opam} file. The first line of this file is the package synopsis. \item (optional) \verb+$opam/repo/$REPO/packages/$PREFIX/$NAME.$VERSION/url+ contains the upstream location for the version \verb+$VERSION+ of package \verb+$NAME+ (which might not be installed) with any possible \verb+$PREFIX+ -- it should be in the same loacation as the corresponding {\tt opam} file. The format of {\tt url} files is described in \S\ref{file:url}. \item (optional) \verb+$opam/repo/$REPO/packages/$PREFIX/$NAME.$VERSION/files/+ contains the overlay files for the version \verb+$VERSION+ of package \verb+$NAME+ (which might not be installed) with any possible \verb+$PREFIX+ -- it should be in the same loacation as the corresponding {\tt opam} file. The overlay files are added to the build directory when a package is built and installed. \item (optional) \verb+$opam/repo/$REPO/archives/$NAME.$VERSION.tar.gz+ contains the source archives for the version \verb+$VERSION+ of package \verb+$NAME+. This folder is populated when a package needs to be downloaded and that the given repository expose such a file. If the file is not present, \OPAM\ will download the package from the upstream sources. \end{itemize} \subsection{Files} \subsubsection{Index of packages} \label{file:index} \verb+$opam/repo/index+ follows a very simple syntax: each line of the file contains a space separated list of words \verb|$NAME.$VERSION $REPO+| specifying that all the version \verb+$VERSION+ of package \verb+$NAME+ is available in the remote repositories \verb|$REPO+|. The file contains information on all available packages (e.g. not only on the installed one). \\ For instance, if {\tt batteries} version {\tt 1.0+beta} is available in the {\tt testing} repository and {\tt ocamlfind} version {\tt 1.2} is available in the {\tt default} and testing repositories (where {\tt default} is one being used), then \verb+$opam/repo/index+ will contain: {\small \begin{Verbatim}[frame=single] batteries.1.0+beta testing ocamlfind.1.2 default testing \end{Verbatim} } \subsection{Commands} \subsubsection{Managing Remote Repository} An user can manage remote repositories, by writing: \begin{verbatim} $ opam repository list # 'opam repository' works as well $ opam repository add [--kind $KIND] $REPO $ADRESS $ opam repository remove $REPO \end{verbatim} \begin{itemize} \item \verb+list+ lists the current repositories by looking at \verb+$opam/config+ \item \verb+add [--kind $KIND] $REPO $ADDRESS+ initializes \verb+$REPO+ as described in \S\ref{opam-init}. \item For distributed version controlled repository, the user can use \verb+url#hash+ or \verb+url#name+ where {\tt hash} is a given revision name and {\tt name} it the name of a tag or a branch. \item \verb+remove $REPO+ deletes \verb+$opam/repo/$REPO+ and removes \verb+$REPO+ from the {\tt repositories} list in \verb+$opam/config+. Then, for each package in \verb+$opam/repo/index+ it updates the link between packages and repositories (ie. it either deletes packages or symlink them to the new repository containing the package). \end{itemize} \section{Managing Configurations} \label{section:config} \subsection{State} \subsection{Files} \subsubsection{Substitution files: {\tt *.in}} \label{file:subst} Any file can be processed using generated using a special mode of {\tt opam} which can perform tests and substitutes variables (see \S\ref{section:config} for the exact command to run). Substitution files contains some templates which will be replaced with some contents. The syntax of templates is the following: \begin{itemize} \item templates such as \verb+%{$NAME:$VAR}%+ are replaced by the value of the variable \verb+$VAR+ defined at the root of the file \verb+$opam/$SWITCH/config/NAME.config+. \item templates such as \verb+%{$NAME.$LIB:$VAR}%+ are replaced by the value of the variable \verb+$VAR+ defined in the \verb+$LIB+ section in the file \verb+$opam/$SWITCH/config/$NAME.config+ \end{itemize} \subsubsection{Package configuration files: {\tt *.config}} \label{file:dotconfig} \verb+$opam/SWITCH/config/NAME.config+ follows the syntax defined in \S\ref{file:general}, with the following restrictions: {\small \begin{Verbatim}[frame=single] := * := |
:= STRING { ?asmcomp: [ STRING+ ] ?bytecomp: [ STRING+ ] ?asmlink : [ STRING+ ] ?bytelink: [ STRING+ ] ?requires: [ STRING+ ] * } := library | syntax := IDENT: BOOL | IDENT: STRING | IDENT: [ STRING+ ] \end{Verbatim} } \verb+$NAME.config+ contains platform-dependent information which can be useful for other libraries or syntax extensions that want to use libraries defined in the package \verb+$NAME+. \paragraph{Local and global variables} The definitions ``{\tt IDENT: BOOL}'', ``{\tt IDENT: STRING}'' and ``{\tt IDENT: [ STRING+ ]}'', are used to defined variables associated to this package, and are used to substitute variables in template files (see \S\ref{subst}): \begin{itemize} \item \verb+%{$NAME:$VAR}%+ will refer to the variable \verb+$VAR+ defined at the root of the configuration file \verb+$opam/$SWITCH/config/NAME.config+. \item \verb+%{$NAME.$LIB:$VAR}%+ will refer to the variable \verb+$VAR+ defined in the {\tt library} or {\tt syntax} section named \verb+$LIB+ in the configuration file \verb+$opam/$SWITCH/config/$NAME.config+. \end{itemize} \paragraph{Library and syntax sections} Each {\tt library} and {\tt syntax} section defines an OCaml library and the specific compilation flags to enable when using and linking with this library. The distinction between libraries and syntax extensions is only useful at compile time to know whether the options should be used as compilation or pre-processing arguments (ie. should they go on the compiler command line or should they be passed to the {\tt -pp} option). This is the responsibility of the build tool to do the right thing and the {\tt } of sections is only used for documentation purposes in \OPAM. \\ The available options are: \begin{itemize} \item {\tt asmcomp} are compilation options to give to the native compiler (when using the {\tt -c} option) \item {\tt bytecomp} are compilation options to give to the bytecode compiler (when using the {\tt -c} option) \item {\tt asmlink} are linking options to give to the native compiler \item {\tt bytlink} are linking options to give to the bytecode compiler \item {\tt requires} is the list of libraries and syntax extensions the current block is depending on. The full list of compilation and linking options is built by looking at the transitive closure of dependencies. The contents of {\tt dep}s is the list of libraries or syntax extension the current section depends on. Note that we do not refer here to any package name, as multiple packages can expose libraries with the same name and interface and thus we want the user to be able to switch between them easily. \end{itemize} \subsection{Commands} \subsubsection{Getting Package Configuration} \label{opam-config} \OPAM\ contains the minimal information to be able to use installed libraries. In order to do so, the end-user (or the packager) should run: \begin{verbatim} $ opam config list $ opam config var $NAME:$VAR $ opam config var $NAME.$LIB:$VAR $ opam config subst $FILENAME+ $ opam config [-R] include $NAME+ $ opam config [-R] bytecomp $NAME.$LIB+ $ opam config [-R] asmcomp $NAME.$LIB+ $ opam config [-R] bytelink $NAME.$LIB+ $ opam config [-R] asmlink $NAME.$LIB+ \end{verbatim} \begin{itemize} \item \verb+list+ will return the list of all variables defined in installed packages (see \S\ref{file:dotconfig}) \item \verb+var $var+ will return the value associated to the variable \verb+$var+ \item \label{subst}\verb+subst $FILENAME+ replace any occurrence of \verb+%{$NAME:$VAR}%+ and \verb+%{$NAME.$LIB:$VAR}%+ as specified in \S\ref{file:subst} in \verb+$FILENAME.in+ to create \verb+$FILENAME+. \item \verb+includes $NAME+ will return the list of paths to include when compiling a project using the package \verb+$NAME+ (\verb+-R+ gives a result taking into account the transitive closure of dependencies). \item \verb+bytecomp+, \verb+asmcomp+, \verb+bytelink+ and \verb+asmlink+ return the associated value for the section \verb+$LIB+ in the file \verb+$opam/$SWITCH/config/$NAME.config+ (\verb+-R+ gives a result taking into account the transitive closure of all dependencies). \end{itemize} \end{document} opam-1.1.1/doc/dev-manual/htmlmacros.hva0000644000175000017500000000003712272210733016360 0ustar i33173i33173\loadcssfile{./dev-manual.css} opam-1.1.1/doc/Makefile0000644000175000017500000000201312272210733013112 0ustar i33173i33173OPAM = ../_obuild/opam/opam.byte TOPICS = $(shell $(OPAM) help topics) OPAM_ADMIN = ../_obuild/opam-admin/opam-admin.byte TOPICS_ADMIN = check make HELPFMT = --help=groff .PHONY: man html dev-manual tutorials all: man tutorials dev html man: rm -f man/* $(OPAM) $(HELPFMT) > man/opam.1 for i in $(TOPICS); do\ $(OPAM) $$i $(HELPFMT) > man/opam-$$i.1;\ done $(OPAM_ADMIN) $(HELPFMT) > man/opam-admin.1 for i in $(TOPICS_ADMIN); do\ $(OPAM_ADMIN) $$i $(HELPFMT) > man/opam-admin-$$i.1;\ done for i in opam-check; do\ pandoc -s -t man man-ext/$$i.md -o man/$$i.1;\ done tutorials: $(MAKE) -C tutorials dev: $(MAKE) -C dev-manual html: mkdir -p html/ ocamldoc \ -I ../_obuild/opam-core -I ../_obuild/opam-solver \ -I ../_obuild/opam-repositories -I ../_obuild/opam-client \ -I ../_obuild/opam-lib -I ../_obuild/cudf -I ../_obuild/dose \ -I ../_obuild/re -I ../_obuild/unix -I ../_obuild/extlib \ -I ../_obuild/arg -I ../_obuild/graph -I ../_obuild/cmdliner \ ../src/**/*.mli -html -d html/ opam-1.1.1/doc/release/0000755000175000017500000000000012272210733013076 5ustar i33173i33173opam-1.1.1/doc/release/readme.md0000644000175000017500000000167212272210733014663 0ustar i33173i33173## Step to follow for each release * `export VERSION=... HOST=...` * Update version (and copyright year) in `configure.ac` * Run `make configure` to regenerate `./configure` * Run `make tests` * Run `opam-rt` (with and without aspcud) * Run `make doc` to re-generate the API documetation * Check that 'make with-ocamlbuild install-with-ocamlbuild' works * Check that 'make libinstall-with-ocamlbuild' work (try to compile `opam-rt` and `opam2web` with it) * Run `make release` to create the full archive and upload it * Run `ssh $HOST cd pub && ln -f opam-full-$VERSION.tar.gz opam-full-latest.tar.gz * On every arch * Run `sh shell/make_update_binary.sh $VERSION` to generate the binary * Run `scp opam-* $HOST:pub/` to upload the binary * Update `VERSION` in `$HOST:pub/opam_installer.sh` * Upload `opam-lib` version in OPAM * Fix `opam2web` constraints in OPAM and upload a new version * Send an email on the platform list (and on the caml-list) opam-1.1.1/doc/man-ext/0000755000175000017500000000000012272210733013027 5ustar i33173i33173opam-1.1.1/doc/man-ext/opam-check.md.in0000644000175000017500000000046312272210733015770 0ustar i33173i33173% OPAM(1) OPAM @PACKAGE_VERSION@ | OPAM Manual % OCamlPro % 20/02/2013 # NAME opam-check - a Tool check that OPAM repositories are consistent # DESCRIPTION See *opam-check --help* for more information. # SEE ALSO **opam**(1) # LINKS * **http://opam.ocamlpro.com** # OPAM Part of the opam(1) suite opam-1.1.1/doc/man/0000755000175000017500000000000012272210733012231 5ustar i33173i33173opam-1.1.1/doc/man/opam-uninstall.10000644000175000017500000001016612272210733015262 0ustar i33173i33173.\" Pipe this output to groff -man -Tutf8 | less .\" .TH "OPAM-UNINSTALL" 1 "" "Opam 1.1.1" "Opam Manual" .\" Disable hyphenantion and ragged-right .nh .ad l .SH NAME .P opam\-uninstall \- An alias for \fBremove\fR. .SH SYNOPSIS .P \fBopam uninstall\fR [\fIOPTION\fR]... [\fIPACKAGES\fR]... .SH DESCRIPTION .P \fBopam uninstall\fR is an alias for \fBopam remove\fR. .P See \fBopam remove \-\-help\fR for details. .SH ARGUMENTS .TP 4 \fIPACKAGES\fR List of package names. .SH COMMON OPTIONS .TP 4 \fB\-\-color\fR=\fIWHEN\fR (absent=auto) Colorize the output. \fIWHEN\fR must be `always', `never' or `auto'. .TP 4 \fB\-\-compat\-mode\-1.0\fR Compatibility mode with OPAM 1.0 .TP 4 \fB\-\-debug\fR Print debug message on stdout. This is equivalent to setting \fB$OPAMDEBUG\fR to a non\-empty value. .TP 4 \fB\-\-git\-version\fR Print the git version if it exists and exit. .TP 4 \fB\-\-no\-aspcud\fR Do not use the external aspcud solver, even if available. .TP 4 \fB\-\-no\-base\-packages\fR Do not install base packages (useful for testing purposes). This is equivalent to setting \fB$OPAMNOBASEPACKAGES\fR to a non\-empty string. .TP 4 \fB\-q\fR, \fB\-\-quiet\fR Be quiet when installing a new compiler. .TP 4 \fB\-r\fR \fIROOT\fR, \fB\-\-root\fR=\fIROOT\fR (absent=~/.opam) Use \fIROOT\fR as the current root path. This is equivalent to setting \fB$OPAMROOT\fR to \fIROOT\fR. .TP 4 \fB\-\-strict\fR Fail whenever an error is found in a package definition or a configuration file. The default is to continue silently if possible. .TP 4 \fB\-\-switch\fR=\fISWITCH\fR Use \fISWITCH\fR as the current compiler switch. This is equivalent to setting \fB$OPAMSWITCH\fR to \fISWITCH\fR. .TP 4 \fB\-v\fR, \fB\-\-verbose\fR Be more verbose. This is equivalent to setting \fB$OPAMVERBOSE\fR to a non\-empty value. .TP 4 \fB\-y\fR, \fB\-\-yes\fR Disable interactive mode and answer yes to all questions that would otherwise be asked to the user. This is equivalent to setting \fB$OPAMYES\fR to a non\-empty string. .SH OPTIONS .TP 4 \fB\-a\fR, \fB\-\-auto\-remove\fR Remove all the packages which have not been explicitly installed and which are not necessary anymore. It is possible to prevent the removal of an already\-installed package by running \fBopam install \fR. This flag can also be set using the \fB$OPAMAUTOREMOVE\fR configuration variable. .TP 4 \fB\-b\fR, \fB\-\-keep\-build\-dir\fR Keep the build directory. This is equivalent to setting \fB$OPAMKEEPBUILDIR\fR to a non\-empty string. .TP 4 \fB\-\-cudf\fR=\fIFILENAME\fR Save the CUDF request sent to the solver to \fIFILENAME\fR\-.cudf. .TP 4 \fB\-d\fR, \fB\-\-build\-doc\fR Build the package documentation. This is equivalent to setting \fB$OPAMBUILDDOC\fR to a non\-empty string. .TP 4 \fB\-\-dry\-run\fR Simply call the solver without actually performing any build/install operations. .TP 4 \fB\-e\fR \fITAGS\fR, \fB\-\-external\fR=\fITAGS\fR Display the external packages associated to the given tags. .TP 4 \fB\-\-fake\fR WARNING: This option is for testing purposes only! Using this option without care is the best way to corrupt your current compiler environment. When using this option OPAM will run a dry\-run of the solver and then fake the build and install commands. .TP 4 \fB\-\-force\fR Execute the remove commands of given packages directly, even if they are not considered installed by OPAM. .TP 4 \fB\-\-help\fR[=\fIFMT\fR] (default=pager) Show this help in format \fIFMT\fR (pager, plain or groff). .TP 4 \fB\-j\fR \fIJOBS\fR, \fB\-\-jobs\fR=\fIJOBS\fR Set the maximal number of concurrent jobs to use. You can also set it using the OPAMJOBS environment variable. .TP 4 \fB\-\-json\fR=\fIFILENAME\fR Save the result output of an OPAM run in a computer\-readable file .TP 4 \fB\-m\fR \fIMAKE\fR, \fB\-\-make\fR=\fIMAKE\fR Use \fIMAKE\fR as the default 'make' command. .TP 4 \fB\-\-no\-checksums\fR Do not verify the checksum of downloaded archives.This is equivalent to setting \fB$OPAMNOCHECKSUMS\fR to a non\-empty string. .TP 4 \fB\-t\fR, \fB\-\-build\-test\fR Build and \fBrun\fR the package unit\-tests. This is equivalent to setting \fB$OPAMBUILDTEST\fR to a non\-empty string. .TP 4 \fB\-\-version\fR Show version information.opam-1.1.1/doc/man/opam-check.10000644000175000017500000000055112272210733014323 0ustar i33173i33173.TH "OPAM" "1" "20/02/2013" "OPAM 1.1.1" "OPAM Manual" .SH NAME .PP opam\-check \- a Tool check that OPAM repositories are consistent .SH DESCRIPTION .PP See \f[I]opam\-check \-\-help\f[] for more information. .SH SEE ALSO .PP \f[B]opam\f[](1) .SH LINKS .IP \[bu] 2 \f[B]http://opam.ocamlpro.com\f[] .SH OPAM .PP Part of the opam(1) suite .SH AUTHORS OCamlPro. opam-1.1.1/doc/man/opam-reinstall.10000644000175000017500000001077212272210733015251 0ustar i33173i33173.\" Pipe this output to groff -man -Tutf8 | less .\" .TH "OPAM-REINSTALL" 1 "" "Opam 1.1.1" "Opam Manual" .\" Disable hyphenantion and ragged-right .nh .ad l .SH NAME .P opam\-reinstall \- Reinstall a list of packages. .SH SYNOPSIS .P \fBopam reinstall\fR [\fIOPTION\fR]... [\fIPACKAGES\fR]... .SH DESCRIPTION .P This command removes the given packages, reinstalls them and recompiles the right package dependencies. .SH ARGUMENTS .TP 4 \fIPACKAGES\fR List of package names. .SH OPTIONS .TP 4 \fB\-b\fR, \fB\-\-keep\-build\-dir\fR Keep the build directory. This is equivalent to setting \fB$OPAMKEEPBUILDIR\fR to a non\-empty string. .TP 4 \fB\-\-cudf\fR=\fIFILENAME\fR Save the CUDF request sent to the solver to \fIFILENAME\fR\-.cudf. .TP 4 \fB\-d\fR, \fB\-\-build\-doc\fR Build the package documentation. This is equivalent to setting \fB$OPAMBUILDDOC\fR to a non\-empty string. .TP 4 \fB\-\-dry\-run\fR Simply call the solver without actually performing any build/install operations. .TP 4 \fB\-e\fR \fITAGS\fR, \fB\-\-external\fR=\fITAGS\fR Display the external packages associated to the given tags. .TP 4 \fB\-\-fake\fR WARNING: This option is for testing purposes only! Using this option without care is the best way to corrupt your current compiler environment. When using this option OPAM will run a dry\-run of the solver and then fake the build and install commands. .TP 4 \fB\-j\fR \fIJOBS\fR, \fB\-\-jobs\fR=\fIJOBS\fR Set the maximal number of concurrent jobs to use. You can also set it using the OPAMJOBS environment variable. .TP 4 \fB\-\-json\fR=\fIFILENAME\fR Save the result output of an OPAM run in a computer\-readable file .TP 4 \fB\-m\fR \fIMAKE\fR, \fB\-\-make\fR=\fIMAKE\fR Use \fIMAKE\fR as the default 'make' command. .TP 4 \fB\-\-no\-checksums\fR Do not verify the checksum of downloaded archives.This is equivalent to setting \fB$OPAMNOCHECKSUMS\fR to a non\-empty string. .TP 4 \fB\-t\fR, \fB\-\-build\-test\fR Build and \fBrun\fR the package unit\-tests. This is equivalent to setting \fB$OPAMBUILDTEST\fR to a non\-empty string. .SH COMMON OPTIONS .P These options are common to all commands. .TP 4 \fB\-\-color\fR=\fIWHEN\fR (absent=auto) Colorize the output. \fIWHEN\fR must be `always', `never' or `auto'. .TP 4 \fB\-\-compat\-mode\-1.0\fR Compatibility mode with OPAM 1.0 .TP 4 \fB\-\-debug\fR Print debug message on stdout. This is equivalent to setting \fB$OPAMDEBUG\fR to a non\-empty value. .TP 4 \fB\-\-git\-version\fR Print the git version if it exists and exit. .TP 4 \fB\-\-help\fR[=\fIFMT\fR] (default=pager) Show this help in format \fIFMT\fR (pager, plain or groff). .TP 4 \fB\-\-no\-aspcud\fR Do not use the external aspcud solver, even if available. .TP 4 \fB\-\-no\-base\-packages\fR Do not install base packages (useful for testing purposes). This is equivalent to setting \fB$OPAMNOBASEPACKAGES\fR to a non\-empty string. .TP 4 \fB\-q\fR, \fB\-\-quiet\fR Be quiet when installing a new compiler. .TP 4 \fB\-r\fR \fIROOT\fR, \fB\-\-root\fR=\fIROOT\fR (absent=~/.opam) Use \fIROOT\fR as the current root path. This is equivalent to setting \fB$OPAMROOT\fR to \fIROOT\fR. .TP 4 \fB\-\-strict\fR Fail whenever an error is found in a package definition or a configuration file. The default is to continue silently if possible. .TP 4 \fB\-\-switch\fR=\fISWITCH\fR Use \fISWITCH\fR as the current compiler switch. This is equivalent to setting \fB$OPAMSWITCH\fR to \fISWITCH\fR. .TP 4 \fB\-v\fR, \fB\-\-verbose\fR Be more verbose. This is equivalent to setting \fB$OPAMVERBOSE\fR to a non\-empty value. .TP 4 \fB\-\-version\fR Show version information. .TP 4 \fB\-y\fR, \fB\-\-yes\fR Disable interactive mode and answer yes to all questions that would otherwise be asked to the user. This is equivalent to setting \fB$OPAMYES\fR to a non\-empty string. .SH ENVIRONMENT VARIABLES .P opam makes use of environment variables listed here. .P \fIOPAMCOLOR\fR, when set to \fIalways\fR or \fInever\fR, sets a default value for the \-\-color option .P \fIOPAMCURL\fR can be used to define an alternative for the 'curl' command\-line utility to download files .SH FURTHER DOCUMENTATION .P See https://opam.ocaml.org. .SH AUTHORS .P Thomas Gazagnaire .sp -1 .P Anil Madhavapeddy .sp -1 .P Fabrice Le Fessant .sp -1 .P Frederic Tuong .sp -1 .P Louis Gesbert .sp -1 .P Vincent Bernardoff .sp -1 .P Guillem Rieu .SH BUGS .P Check bug reports at https://github.com/OCamlPro/opam/issues.opam-1.1.1/doc/man/opam-info.10000644000175000017500000000437512272210733014211 0ustar i33173i33173.\" Pipe this output to groff -man -Tutf8 | less .\" .TH "OPAM-INFO" 1 "" "Opam 1.1.1" "Opam Manual" .\" Disable hyphenantion and ragged-right .nh .ad l .SH NAME .P opam\-info \- An alias for \fBshow\fR. .SH SYNOPSIS .P \fBopam info\fR [\fIOPTION\fR]... [\fIPATTERNS\fR]... .SH DESCRIPTION .P \fBopam info\fR is an alias for \fBopam show\fR. .P See \fBopam show \-\-help\fR for details. .SH ARGUMENTS .TP 4 \fIPATTERNS\fR List of package patterns. .SH COMMON OPTIONS .TP 4 \fB\-\-color\fR=\fIWHEN\fR (absent=auto) Colorize the output. \fIWHEN\fR must be `always', `never' or `auto'. .TP 4 \fB\-\-compat\-mode\-1.0\fR Compatibility mode with OPAM 1.0 .TP 4 \fB\-\-debug\fR Print debug message on stdout. This is equivalent to setting \fB$OPAMDEBUG\fR to a non\-empty value. .TP 4 \fB\-\-git\-version\fR Print the git version if it exists and exit. .TP 4 \fB\-\-no\-aspcud\fR Do not use the external aspcud solver, even if available. .TP 4 \fB\-\-no\-base\-packages\fR Do not install base packages (useful for testing purposes). This is equivalent to setting \fB$OPAMNOBASEPACKAGES\fR to a non\-empty string. .TP 4 \fB\-q\fR, \fB\-\-quiet\fR Be quiet when installing a new compiler. .TP 4 \fB\-r\fR \fIROOT\fR, \fB\-\-root\fR=\fIROOT\fR (absent=~/.opam) Use \fIROOT\fR as the current root path. This is equivalent to setting \fB$OPAMROOT\fR to \fIROOT\fR. .TP 4 \fB\-\-strict\fR Fail whenever an error is found in a package definition or a configuration file. The default is to continue silently if possible. .TP 4 \fB\-\-switch\fR=\fISWITCH\fR Use \fISWITCH\fR as the current compiler switch. This is equivalent to setting \fB$OPAMSWITCH\fR to \fISWITCH\fR. .TP 4 \fB\-v\fR, \fB\-\-verbose\fR Be more verbose. This is equivalent to setting \fB$OPAMVERBOSE\fR to a non\-empty value. .TP 4 \fB\-y\fR, \fB\-\-yes\fR Disable interactive mode and answer yes to all questions that would otherwise be asked to the user. This is equivalent to setting \fB$OPAMYES\fR to a non\-empty string. .SH OPTIONS .TP 4 \fB\-f\fR \fIFIELDS\fR, \fB\-\-field\fR=\fIFIELDS\fR Only display these fields. You can specify multiple fields by separating them with commas. .TP 4 \fB\-\-help\fR[=\fIFMT\fR] (default=pager) Show this help in format \fIFMT\fR (pager, plain or groff). .TP 4 \fB\-\-version\fR Show version information.opam-1.1.1/doc/man/opam-repository.10000644000175000017500000001021312272210733015461 0ustar i33173i33173.\" Pipe this output to groff -man -Tutf8 | less .\" .TH "OPAM-REPOSITORY" 1 "" "Opam 1.1.1" "Opam Manual" .\" Disable hyphenantion and ragged-right .nh .ad l .SH NAME .P opam\-repository \- Manage OPAM repositories. .SH SYNOPSIS .P \fBopam repository\fR [\fIOPTION\fR]... [\fICOMMAND\fR] [\fIARG\fR]... .SH DESCRIPTION .P This command is used to manage OPAM repositories. To synchronize OPAM with the last versions of the packages available in remote repositories, \fBopam update\fR should be used. .SH ARGUMENTS .TP 4 \fICOMMAND\fR Name of the sub\-command. See the \fBCOMMANDS\fR section for more info. .SH OPTIONS .TP 4 \fB\-k\fR \fIKIND\fR, \fB\-\-kind\fR=\fIKIND\fR Specify the kind of the repository to be set (the main ones are 'http', 'local', 'git', 'darcs' or 'hg'). .TP 4 \fB\-p\fR \fIINT\fR, \fB\-\-priority\fR=\fIINT\fR Set the repository priority (bigger is better) .TP 4 \fB\-s\fR, \fB\-\-short\fR Output the names separated by one whitespace instead of using the usual formatting. .SH COMMANDS .TP 4 \fBadd\fR Add the repository \fBname\fR available at address \fBaddress\fR to the list of repositories used by OPAM, with priority \fBpriority\fR. The repository priority can be optionally specified with \fB\-\-priority\fR, otherwise the new repository has a higher priority then any other existing repositories. The kind of the repository can be specified with the \fB\-\-kind\fR option, otherwise it will be determined automatically. .TP 4 \fBremove\fR Remove the repository named \fBname\fR from the list of repositories used by OPAM. .TP 4 \fBlist\fR List all repositories used by OPAM. .TP 4 \fBpriority\fR Change the priority of repository named \fBname\fR to \fBpriority\fR. .SH COMMON OPTIONS .P These options are common to all commands. .TP 4 \fB\-\-color\fR=\fIWHEN\fR (absent=auto) Colorize the output. \fIWHEN\fR must be `always', `never' or `auto'. .TP 4 \fB\-\-compat\-mode\-1.0\fR Compatibility mode with OPAM 1.0 .TP 4 \fB\-\-debug\fR Print debug message on stdout. This is equivalent to setting \fB$OPAMDEBUG\fR to a non\-empty value. .TP 4 \fB\-\-git\-version\fR Print the git version if it exists and exit. .TP 4 \fB\-\-help\fR[=\fIFMT\fR] (default=pager) Show this help in format \fIFMT\fR (pager, plain or groff). .TP 4 \fB\-\-no\-aspcud\fR Do not use the external aspcud solver, even if available. .TP 4 \fB\-\-no\-base\-packages\fR Do not install base packages (useful for testing purposes). This is equivalent to setting \fB$OPAMNOBASEPACKAGES\fR to a non\-empty string. .TP 4 \fB\-q\fR, \fB\-\-quiet\fR Be quiet when installing a new compiler. .TP 4 \fB\-r\fR \fIROOT\fR, \fB\-\-root\fR=\fIROOT\fR (absent=~/.opam) Use \fIROOT\fR as the current root path. This is equivalent to setting \fB$OPAMROOT\fR to \fIROOT\fR. .TP 4 \fB\-\-strict\fR Fail whenever an error is found in a package definition or a configuration file. The default is to continue silently if possible. .TP 4 \fB\-\-switch\fR=\fISWITCH\fR Use \fISWITCH\fR as the current compiler switch. This is equivalent to setting \fB$OPAMSWITCH\fR to \fISWITCH\fR. .TP 4 \fB\-v\fR, \fB\-\-verbose\fR Be more verbose. This is equivalent to setting \fB$OPAMVERBOSE\fR to a non\-empty value. .TP 4 \fB\-\-version\fR Show version information. .TP 4 \fB\-y\fR, \fB\-\-yes\fR Disable interactive mode and answer yes to all questions that would otherwise be asked to the user. This is equivalent to setting \fB$OPAMYES\fR to a non\-empty string. .SH ENVIRONMENT VARIABLES .P opam makes use of environment variables listed here. .P \fIOPAMCOLOR\fR, when set to \fIalways\fR or \fInever\fR, sets a default value for the \-\-color option .P \fIOPAMCURL\fR can be used to define an alternative for the 'curl' command\-line utility to download files .SH FURTHER DOCUMENTATION .P See https://opam.ocaml.org. .SH AUTHORS .P Thomas Gazagnaire .sp -1 .P Anil Madhavapeddy .sp -1 .P Fabrice Le Fessant .sp -1 .P Frederic Tuong .sp -1 .P Louis Gesbert .sp -1 .P Vincent Bernardoff .sp -1 .P Guillem Rieu .SH BUGS .P Check bug reports at https://github.com/OCamlPro/opam/issues.opam-1.1.1/doc/man/opam-config.10000644000175000017500000001651112272210733014516 0ustar i33173i33173.\" Pipe this output to groff -man -Tutf8 | less .\" .TH "OPAM-CONFIG" 1 "" "Opam 1.1.1" "Opam Manual" .\" Disable hyphenantion and ragged-right .nh .ad l .SH NAME .P opam\-config \- Display configuration options for packages. .SH SYNOPSIS .P \fBopam config\fR [\fIOPTION\fR]... [\fIDOMAIN\fR] [\fIARG\fR]... .SH DESCRIPTION .P This command uses OPAM state to output information on how to use installed libraries, update the \fBPATH\fR, and substitute variables used in OPAM packages. .P Apart from \fBopam config env\fR, most of these commands are used by OPAM internally, and are of limited interest for the casual user. .SH ARGUMENTS .TP 4 \fIDOMAIN\fR Name of the sub\-command. See the \fBDOMAINS\fR section for more info. .SH OPTIONS .TP 4 \fB\-a\fR, \fB\-\-all\fR Enable all the global and user configuration options. .TP 4 \fB\-\-csh\fR Use csh\-compatible mode for configuring OPAM. .TP 4 \fB\-\-dot\-profile\fR=\fIFILENAME\fR Name of the configuration file to update instead of \fI~/.profile\fR or \fI~/.zshrc\fR based on shell detection. .TP 4 \fB\-e\fR \fIVAL\fR Backward\-compatible option, equivalent to \fBopam config env\fR. .TP 4 \fB\-\-fish\fR Use fish\-compatible mode for configuring OPAM. .TP 4 \fB\-g\fR, \fB\-\-global\fR Enable all the global configuration options. .TP 4 \fB\-l\fR, \fB\-\-list\fR List the current configuration. .TP 4 \fB\-\-no\-complete\fR Do not load the auto\-completion scripts in the environment. .TP 4 \fB\-\-no\-switch\-eval\fR Do not install `opam\-switch\-eval` to switch & eval using a single command. .TP 4 \fB\-\-ocamlinit\fR Modify ~/.ocamlinit to make `#use "topfind"` works in the toplevel. .TP 4 \fB\-\-profile\fR Modify ~/.profile (or ~/.zshrc if running zsh) to setup an OPAM\-friendly environment when starting a new shell. .TP 4 \fB\-R\fR, \fB\-\-rec\fR Recursive query. .TP 4 \fB\-\-sexp\fR Display environment variables as an s\-expression .TP 4 \fB\-\-sh\fR Use sh\-compatible mode for configuring OPAM. .TP 4 \fB\-u\fR, \fB\-\-user\fR Enable all the user configuration options. .TP 4 \fB\-\-zsh\fR Use zsh\-compatible mode for configuring OPAM. .SH DOMAINS .TP 4 \fBenv\fR Return the environment variables PATH, MANPATH, OCAML_TOPLEVEL_PATH and CAML_LD_LIBRARY_PATH according to the currently selected compiler. The output of this command is meant to be evaluated by a shell, for example by doing \fBeval `opam config env`\fR. .TP 4 \fBsetup\fR Configure global and user parameters for OPAM. Use \fB opam config setup\fR to display more options. Use \fB\-\-list\fR to display the current configuration options. You can use this command to automatically update: (i) user\-configuration files such as ~/.profile and ~/.ocamlinit; and (ii) global\-configaration files controlling which shell scripts are loaded on startup, such as auto\-completion. These configuration options can be updated using: \fBopam config setup \-\-global\fR to setup the global configuration files stored in \fB~/.opam/opam\-init/\fR and \fBopam config setup \-\-user\fR to setup the user ones. To modify both the global and user configuration, use \fBopam config setup \-\-all\fR. .TP 4 \fBexec\fR Execute the shell script given in parameter with the correct environment variables. This option can be used to cross\-compile between switches using \fBopam config exec "CMD ARG1 ... ARGn" \-\-switch=SWITCH\fR .TP 4 \fBvar\fR Return the value associated with the given variable. If the variable contains a colon such as \fIpkg:var\fR, then the left element will be understood as the package in which the variable is defined. The variable resolution is done as follows: first, OPAM will check whether \fB$var\fR exists; for package variables, it will look for \fB$pkg_var\fR. If the variable is not found, OPAM will then check whether the variable is implicit. There are two global implicit variables: \fIocaml\-version\fR and \fIpreinstalled\fR and two implicit variables per package: \fIpkg:installed\fR which is either \fB"true"\fR or \fB"false"\fR, and \fIpkg:enable\fR which is either \fB"enable"\fR or \fB"disable"\fR. Finally, OPAM will look into its global and package config files to find whether these variables exist. .TP 4 \fBlist\fR Return the list of all variables defined in the listed packages. It is possible to filter the list of variables by giving package names (use \fBglobals\fR to get the list of global variables). No parameter means displaying all the variables. .TP 4 \fBsubst\fR Substitute variables in the given files. The strings \fI%{var}%\fR are replaced by the value of the variable \fIvar\fR (see the documentation associated to \fBopam config var\fR). .TP 4 \fBincludes\fR returns include options. .TP 4 \fBbytecomp\fR returns bytecode compile options. .TP 4 \fBasmcomp\fR returns assembly compile options. .TP 4 \fBbytelink\fR returns bytecode linking options. .TP 4 \fBasmlink\fR returns assembly compile options. .TP 4 \fBreport\fR Prints a summary of your setup, useful for bug\-reports. .SH COMMON OPTIONS .P These options are common to all commands. .TP 4 \fB\-\-color\fR=\fIWHEN\fR (absent=auto) Colorize the output. \fIWHEN\fR must be `always', `never' or `auto'. .TP 4 \fB\-\-compat\-mode\-1.0\fR Compatibility mode with OPAM 1.0 .TP 4 \fB\-\-debug\fR Print debug message on stdout. This is equivalent to setting \fB$OPAMDEBUG\fR to a non\-empty value. .TP 4 \fB\-\-git\-version\fR Print the git version if it exists and exit. .TP 4 \fB\-\-help\fR[=\fIFMT\fR] (default=pager) Show this help in format \fIFMT\fR (pager, plain or groff). .TP 4 \fB\-\-no\-aspcud\fR Do not use the external aspcud solver, even if available. .TP 4 \fB\-\-no\-base\-packages\fR Do not install base packages (useful for testing purposes). This is equivalent to setting \fB$OPAMNOBASEPACKAGES\fR to a non\-empty string. .TP 4 \fB\-q\fR, \fB\-\-quiet\fR Be quiet when installing a new compiler. .TP 4 \fB\-r\fR \fIROOT\fR, \fB\-\-root\fR=\fIROOT\fR (absent=~/.opam) Use \fIROOT\fR as the current root path. This is equivalent to setting \fB$OPAMROOT\fR to \fIROOT\fR. .TP 4 \fB\-\-strict\fR Fail whenever an error is found in a package definition or a configuration file. The default is to continue silently if possible. .TP 4 \fB\-\-switch\fR=\fISWITCH\fR Use \fISWITCH\fR as the current compiler switch. This is equivalent to setting \fB$OPAMSWITCH\fR to \fISWITCH\fR. .TP 4 \fB\-v\fR, \fB\-\-verbose\fR Be more verbose. This is equivalent to setting \fB$OPAMVERBOSE\fR to a non\-empty value. .TP 4 \fB\-\-version\fR Show version information. .TP 4 \fB\-y\fR, \fB\-\-yes\fR Disable interactive mode and answer yes to all questions that would otherwise be asked to the user. This is equivalent to setting \fB$OPAMYES\fR to a non\-empty string. .SH ENVIRONMENT VARIABLES .P opam makes use of environment variables listed here. .P \fIOPAMCOLOR\fR, when set to \fIalways\fR or \fInever\fR, sets a default value for the \-\-color option .P \fIOPAMCURL\fR can be used to define an alternative for the 'curl' command\-line utility to download files .SH FURTHER DOCUMENTATION .P See https://opam.ocaml.org. .SH AUTHORS .P Thomas Gazagnaire .sp -1 .P Anil Madhavapeddy .sp -1 .P Fabrice Le Fessant .sp -1 .P Frederic Tuong .sp -1 .P Louis Gesbert .sp -1 .P Vincent Bernardoff .sp -1 .P Guillem Rieu .SH BUGS .P Check bug reports at https://github.com/OCamlPro/opam/issues.opam-1.1.1/doc/man/opam-switch.10000644000175000017500000001640012272210733014547 0ustar i33173i33173.\" Pipe this output to groff -man -Tutf8 | less .\" .TH "OPAM-SWITCH" 1 "" "Opam 1.1.1" "Opam Manual" .\" Disable hyphenantion and ragged-right .nh .ad l .SH NAME .P opam\-switch \- Manage multiple installation of compilers. .SH SYNOPSIS .P \fBopam switch\fR [\fIOPTION\fR]... [\fICOMMAND\fR] [\fIARG\fR]... .SH DESCRIPTION .P This command allows one to switch between different compiler versions, installing the compiler if \fBopam switch\fR is used to switch to that compiler for the first time. The different compiler versions are totally independent from each other, meaning that OPAM maintains a separate state (e.g. list of installed packages...) for each. .P See the documentation of \fBopam switch list\fR to see the compilers which are available, and how to switch or to install a new one. .SH ARGUMENTS .TP 4 \fICOMMAND\fR Name of the sub\-command. See the \fBCOMMANDS\fR section for more info. If a compiler switch is given instead of an usual command, this command will switch to the given compiler. You will then need to run \fBeval `opam config env`\fR to update your environment variables. .SH OPTIONS .TP 4 \fB\-A\fR \fICOMP\fR, \fB\-\-alias\-of\fR=\fICOMP\fR The name of the compiler description which will be aliased. .TP 4 \fB\-a\fR, \fB\-\-all\fR List all the compilers which can be installed on the system. .TP 4 \fB\-b\fR, \fB\-\-keep\-build\-dir\fR Keep the build directory. This is equivalent to setting \fB$OPAMKEEPBUILDIR\fR to a non\-empty string. .TP 4 \fB\-\-cudf\fR=\fIFILENAME\fR Save the CUDF request sent to the solver to \fIFILENAME\fR\-.cudf. .TP 4 \fB\-d\fR, \fB\-\-build\-doc\fR Build the package documentation. This is equivalent to setting \fB$OPAMBUILDDOC\fR to a non\-empty string. .TP 4 \fB\-\-dry\-run\fR Simply call the solver without actually performing any build/install operations. .TP 4 \fB\-e\fR \fITAGS\fR, \fB\-\-external\fR=\fITAGS\fR Display the external packages associated to the given tags. .TP 4 \fB\-f\fR \fIFILENAME\fR, \fB\-\-filename\fR=\fIFILENAME\fR The name of the file to export to/import from. .TP 4 \fB\-\-fake\fR WARNING: This option is for testing purposes only! Using this option without care is the best way to corrupt your current compiler environment. When using this option OPAM will run a dry\-run of the solver and then fake the build and install commands. .TP 4 \fB\-i\fR, \fB\-\-installed\fR List installed compiler switches only. .TP 4 \fB\-j\fR \fIJOBS\fR, \fB\-\-jobs\fR=\fIJOBS\fR Set the maximal number of concurrent jobs to use. You can also set it using the OPAMJOBS environment variable. .TP 4 \fB\-\-json\fR=\fIFILENAME\fR Save the result output of an OPAM run in a computer\-readable file .TP 4 \fB\-m\fR \fIMAKE\fR, \fB\-\-make\fR=\fIMAKE\fR Use \fIMAKE\fR as the default 'make' command. .TP 4 \fB\-\-no\-checksums\fR Do not verify the checksum of downloaded archives.This is equivalent to setting \fB$OPAMNOCHECKSUMS\fR to a non\-empty string. .TP 4 \fB\-\-no\-switch\fR Only install the compiler switch, without switching to it. If the compiler switch is already installed, then do nothing. .TP 4 \fB\-\-no\-warning\fR Do not display any warning related to environment variables. .TP 4 \fB\-s\fR, \fB\-\-short\fR Output the names separated by one whitespace instead of using the usual formatting. .TP 4 \fB\-t\fR, \fB\-\-build\-test\fR Build and \fBrun\fR the package unit\-tests. This is equivalent to setting \fB$OPAMBUILDTEST\fR to a non\-empty string. .SH COMMANDS .TP 4 \fBinstall\fR Install the given compiler. The commands fails if the package is already installed (e.g. it will not transparently switch to the installed compiler switch, as \fBopam switch \fR does). .TP 4 \fBremove\fR Remove the given compiler. .TP 4 \fBexport\fR Export the list installed package to a file. .TP 4 \fBimport\fR Install the packages from a file. .TP 4 \fBreinstall\fR Reinstall the given compiler switch. This will also try reinstall the installed packages. .TP 4 \fBlist\fR List compilers. By default, lists installed and `standard' compilers. Use `\-\-all' to get the list of all installable compilers. The first column displays the switch name (if any), the second one the switch state (C = current, I = installed, \-\- = not installed), the third one the compiler name and the last one the compiler description. To switch to an already installed compiler alias (with state = I), use \fBopam switch \fR. If you want to use a new compiler , use \fBopam switch \fR: this will download, compile and create a fresh and independent environment where new packages can be installed. If you want to create a new compiler alias (for instance because you already have this compiler version installed), use \fBopam switch \-\-alias\-of \fR. In case and are the same, this is equivalent to \fBopam switch \fR. .TP 4 \fBshow\fR Show the current compiler. .SH COMMON OPTIONS .P These options are common to all commands. .TP 4 \fB\-\-color\fR=\fIWHEN\fR (absent=auto) Colorize the output. \fIWHEN\fR must be `always', `never' or `auto'. .TP 4 \fB\-\-compat\-mode\-1.0\fR Compatibility mode with OPAM 1.0 .TP 4 \fB\-\-debug\fR Print debug message on stdout. This is equivalent to setting \fB$OPAMDEBUG\fR to a non\-empty value. .TP 4 \fB\-\-git\-version\fR Print the git version if it exists and exit. .TP 4 \fB\-\-help\fR[=\fIFMT\fR] (default=pager) Show this help in format \fIFMT\fR (pager, plain or groff). .TP 4 \fB\-\-no\-aspcud\fR Do not use the external aspcud solver, even if available. .TP 4 \fB\-\-no\-base\-packages\fR Do not install base packages (useful for testing purposes). This is equivalent to setting \fB$OPAMNOBASEPACKAGES\fR to a non\-empty string. .TP 4 \fB\-q\fR, \fB\-\-quiet\fR Be quiet when installing a new compiler. .TP 4 \fB\-r\fR \fIROOT\fR, \fB\-\-root\fR=\fIROOT\fR (absent=~/.opam) Use \fIROOT\fR as the current root path. This is equivalent to setting \fB$OPAMROOT\fR to \fIROOT\fR. .TP 4 \fB\-\-strict\fR Fail whenever an error is found in a package definition or a configuration file. The default is to continue silently if possible. .TP 4 \fB\-\-switch\fR=\fISWITCH\fR Use \fISWITCH\fR as the current compiler switch. This is equivalent to setting \fB$OPAMSWITCH\fR to \fISWITCH\fR. .TP 4 \fB\-v\fR, \fB\-\-verbose\fR Be more verbose. This is equivalent to setting \fB$OPAMVERBOSE\fR to a non\-empty value. .TP 4 \fB\-\-version\fR Show version information. .TP 4 \fB\-y\fR, \fB\-\-yes\fR Disable interactive mode and answer yes to all questions that would otherwise be asked to the user. This is equivalent to setting \fB$OPAMYES\fR to a non\-empty string. .SH ENVIRONMENT VARIABLES .P opam makes use of environment variables listed here. .P \fIOPAMCOLOR\fR, when set to \fIalways\fR or \fInever\fR, sets a default value for the \-\-color option .P \fIOPAMCURL\fR can be used to define an alternative for the 'curl' command\-line utility to download files .SH FURTHER DOCUMENTATION .P See https://opam.ocaml.org. .SH AUTHORS .P Thomas Gazagnaire .sp -1 .P Anil Madhavapeddy .sp -1 .P Fabrice Le Fessant .sp -1 .P Frederic Tuong .sp -1 .P Louis Gesbert .sp -1 .P Vincent Bernardoff .sp -1 .P Guillem Rieu .SH BUGS .P Check bug reports at https://github.com/OCamlPro/opam/issues.opam-1.1.1/doc/man/opam-admin-make.10000644000175000017500000000217412272210733015254 0ustar i33173i33173.\" Pipe this output to groff -man -Tutf8 | less .\" .TH "OPAM-ADMIN-MAKE" 1 "" "Opam-admin 1.1.1" "Opam-admin Manual" .\" Disable hyphenantion and ragged-right .nh .ad l .SH NAME .P opam\-admin\-make \- Initialize a repo for serving files. .SH SYNOPSIS .P \fBopam\-admin make\fR [\fIOPTION\fR]... [\fIPKG\fR]... .SH ARGUMENTS .TP 4 \fIPKG\fR Names of the packages to include in the repo. .SH OPTIONS .TP 4 \fB\-d\fR, \fB\-\-dryrun\fR Simply display the possible actions instead of executing them. .TP 4 \fB\-\-debug\fR Display debug messages. .TP 4 \fB\-g\fR, \fB\-\-generate\-checksums\fR Automatically correct the wrong archive checksums. .TP 4 \fB\-\-help\fR[=\fIFMT\fR] (default=pager) Show this help in format \fIFMT\fR (pager, plain or groff). .TP 4 \fB\-i\fR, \fB\-\-index\fR Only build indexes, not package archives. .TP 4 \fB\-r\fR, \fB\-\-recursive\fR Recurse among the transitive dependencies. .TP 4 \fB\-\-resolve\fR A more advanced version of `\-\-recursive': will attempt to resolve your installation with all dependencies in the best way possible and build the archives accordingly. .TP 4 \fB\-\-version\fR Show version information.opam-1.1.1/doc/man/opam-init.10000644000175000017500000001434312272210733014215 0ustar i33173i33173.\" Pipe this output to groff -man -Tutf8 | less .\" .TH "OPAM-INIT" 1 "" "Opam 1.1.1" "Opam Manual" .\" Disable hyphenantion and ragged-right .nh .ad l .SH NAME .P opam\-init \- Initialize OPAM state. .SH SYNOPSIS .P \fBopam init\fR [\fIOPTION\fR]... [\fINAME\fR] [\fIADDRESS\fR] .SH DESCRIPTION .P The \fBinit\fR command creates a fresh client state. This initializes OPAM configuration in \fI~/.opam\fR and configures a default package repository. .P Once the fresh client has been created, OPAM will ask the user if he wants \fI~/.profile\fR (or i,~/.zshrc, depending on his shell) and \fI~/.ocamlinit\fR to be updated. If \fB\-\-auto\-setup\fR is used, OPAM will modify the configuration files automatically, without asking the user. If \fB\-\-no\-setup\fR is used, OPAM will *NOT* modify anything outside of \fI~/.opam\fR. .P Additional repositories can be added later by using the \fBopam repository\fR command. .P The state of repositories can be synchronized by using \fBopam update\fR. .P The user and global configuration files can be setup later by using \fBopam config setup\fR. .SH ARGUMENTS .TP 4 \fIADDRESS\fR (absent=https://opam.ocaml.org) Address of the repository. .TP 4 \fINAME\fR (absent=default) Name of the repository. .SH OPTIONS .TP 4 \fB\-a\fR, \fB\-\-auto\-setup\fR Automatically setup all the global and user configuration options for OPAM. .TP 4 \fB\-b\fR, \fB\-\-keep\-build\-dir\fR Keep the build directory. This is equivalent to setting \fB$OPAMKEEPBUILDIR\fR to a non\-empty string. .TP 4 \fB\-\-comp\fR=\fIVERSION\fR (absent=system) Which compiler version to use. .TP 4 \fB\-\-csh\fR Use csh\-compatible mode for configuring OPAM. .TP 4 \fB\-\-cudf\fR=\fIFILENAME\fR Save the CUDF request sent to the solver to \fIFILENAME\fR\-.cudf. .TP 4 \fB\-d\fR, \fB\-\-build\-doc\fR Build the package documentation. This is equivalent to setting \fB$OPAMBUILDDOC\fR to a non\-empty string. .TP 4 \fB\-\-dot\-profile\fR=\fIFILENAME\fR Name of the configuration file to update instead of \fI~/.profile\fR or \fI~/.zshrc\fR based on shell detection. .TP 4 \fB\-\-dry\-run\fR Simply call the solver without actually performing any build/install operations. .TP 4 \fB\-e\fR \fITAGS\fR, \fB\-\-external\fR=\fITAGS\fR Display the external packages associated to the given tags. .TP 4 \fB\-\-fake\fR WARNING: This option is for testing purposes only! Using this option without care is the best way to corrupt your current compiler environment. When using this option OPAM will run a dry\-run of the solver and then fake the build and install commands. .TP 4 \fB\-\-fish\fR Use fish\-compatible mode for configuring OPAM. .TP 4 \fB\-j\fR \fIJOBS\fR, \fB\-\-jobs\fR=\fIJOBS\fR Set the maximal number of concurrent jobs to use. You can also set it using the OPAMJOBS environment variable. .TP 4 \fB\-j\fR \fIJOBS\fR, \fB\-\-jobs\fR=\fIJOBS\fR (absent=1) Number of jobs to use when building packages. .TP 4 \fB\-\-json\fR=\fIFILENAME\fR Save the result output of an OPAM run in a computer\-readable file .TP 4 \fB\-k\fR \fIKIND\fR, \fB\-\-kind\fR=\fIKIND\fR Specify the kind of the repository to be set (the main ones are 'http', 'local', 'git', 'darcs' or 'hg'). .TP 4 \fB\-m\fR \fIMAKE\fR, \fB\-\-make\fR=\fIMAKE\fR Use \fIMAKE\fR as the default 'make' command. .TP 4 \fB\-n\fR, \fB\-\-no\-setup\fR Do not update the global and user configuration options to setup OPAM. .TP 4 \fB\-\-no\-checksums\fR Do not verify the checksum of downloaded archives.This is equivalent to setting \fB$OPAMNOCHECKSUMS\fR to a non\-empty string. .TP 4 \fB\-\-sh\fR Use sh\-compatible mode for configuring OPAM. .TP 4 \fB\-t\fR, \fB\-\-build\-test\fR Build and \fBrun\fR the package unit\-tests. This is equivalent to setting \fB$OPAMBUILDTEST\fR to a non\-empty string. .TP 4 \fB\-\-zsh\fR Use zsh\-compatible mode for configuring OPAM. .SH COMMON OPTIONS .P These options are common to all commands. .TP 4 \fB\-\-color\fR=\fIWHEN\fR (absent=auto) Colorize the output. \fIWHEN\fR must be `always', `never' or `auto'. .TP 4 \fB\-\-compat\-mode\-1.0\fR Compatibility mode with OPAM 1.0 .TP 4 \fB\-\-debug\fR Print debug message on stdout. This is equivalent to setting \fB$OPAMDEBUG\fR to a non\-empty value. .TP 4 \fB\-\-git\-version\fR Print the git version if it exists and exit. .TP 4 \fB\-\-help\fR[=\fIFMT\fR] (default=pager) Show this help in format \fIFMT\fR (pager, plain or groff). .TP 4 \fB\-\-no\-aspcud\fR Do not use the external aspcud solver, even if available. .TP 4 \fB\-\-no\-base\-packages\fR Do not install base packages (useful for testing purposes). This is equivalent to setting \fB$OPAMNOBASEPACKAGES\fR to a non\-empty string. .TP 4 \fB\-q\fR, \fB\-\-quiet\fR Be quiet when installing a new compiler. .TP 4 \fB\-r\fR \fIROOT\fR, \fB\-\-root\fR=\fIROOT\fR (absent=~/.opam) Use \fIROOT\fR as the current root path. This is equivalent to setting \fB$OPAMROOT\fR to \fIROOT\fR. .TP 4 \fB\-\-strict\fR Fail whenever an error is found in a package definition or a configuration file. The default is to continue silently if possible. .TP 4 \fB\-\-switch\fR=\fISWITCH\fR Use \fISWITCH\fR as the current compiler switch. This is equivalent to setting \fB$OPAMSWITCH\fR to \fISWITCH\fR. .TP 4 \fB\-v\fR, \fB\-\-verbose\fR Be more verbose. This is equivalent to setting \fB$OPAMVERBOSE\fR to a non\-empty value. .TP 4 \fB\-\-version\fR Show version information. .TP 4 \fB\-y\fR, \fB\-\-yes\fR Disable interactive mode and answer yes to all questions that would otherwise be asked to the user. This is equivalent to setting \fB$OPAMYES\fR to a non\-empty string. .SH ENVIRONMENT VARIABLES .P opam makes use of environment variables listed here. .P \fIOPAMCOLOR\fR, when set to \fIalways\fR or \fInever\fR, sets a default value for the \-\-color option .P \fIOPAMCURL\fR can be used to define an alternative for the 'curl' command\-line utility to download files .SH FURTHER DOCUMENTATION .P See https://opam.ocaml.org. .SH AUTHORS .P Thomas Gazagnaire .sp -1 .P Anil Madhavapeddy .sp -1 .P Fabrice Le Fessant .sp -1 .P Frederic Tuong .sp -1 .P Louis Gesbert .sp -1 .P Vincent Bernardoff .sp -1 .P Guillem Rieu .SH BUGS .P Check bug reports at https://github.com/OCamlPro/opam/issues.opam-1.1.1/doc/man/opam.10000644000175000017500000001035412272210733013252 0ustar i33173i33173.\" Pipe this output to groff -man -Tutf8 | less .\" .TH "OPAM" 1 "" "Opam 1.1.1" "Opam Manual" .\" Disable hyphenantion and ragged-right .nh .ad l .SH NAME .P opam \- source\-based OCaml package management .SH SYNOPSIS .P \fBopam\fR \fICOMMAND\fR ... .SH DESCRIPTION .P OPAM is a package manager for OCaml. It uses the powerful mancoosi tools to handle dependencies, including support for version constraints, optional dependencies, and conflict management. .P It has support for different remote repositories such as HTTP, rsync, git, darcs and mercurial. It handles multiple OCaml versions concurrently, and is flexible enough to allow you to use your own repositories and packages in addition to the central ones it provides. .P Use either \fBopam \-\-help\fR or \fBopam help \fR for more information on a specific command. .SH COMMANDS .TP 4 \fBconfig\fR Display configuration options for packages. .TP 4 \fBhelp\fR Display help about OPAM and OPAM commands. .TP 4 \fBinit\fR Initialize OPAM state. .TP 4 \fBinstall\fR Install a list of packages. .TP 4 \fBlist\fR Display the list of available packages. .TP 4 \fBpin\fR Pin a given package to a specific version. .TP 4 \fBreinstall\fR Reinstall a list of packages. .TP 4 \fBremove\fR Remove a list of packages. .TP 4 \fBrepository\fR Manage OPAM repositories. .TP 4 \fBsearch\fR Search into the package list. .TP 4 \fBshow\fR Display information about specific packages. .TP 4 \fBswitch\fR Manage multiple installation of compilers. .TP 4 \fBupdate\fR Update the list of available packages. .TP 4 \fBupgrade\fR Upgrade the installed package to latest version. .SH COMMANDS ALIASES .TP 4 \fBinfo\fR An alias for \fBshow\fR. .TP 4 \fBremote\fR An alias for \fBrepository\fR. .TP 4 \fBuninstall\fR An alias for \fBremove\fR. .SH COMMON OPTIONS .P These options are common to all commands. .TP 4 \fB\-\-color\fR=\fIWHEN\fR (absent=auto) Colorize the output. \fIWHEN\fR must be `always', `never' or `auto'. .TP 4 \fB\-\-compat\-mode\-1.0\fR Compatibility mode with OPAM 1.0 .TP 4 \fB\-\-debug\fR Print debug message on stdout. This is equivalent to setting \fB$OPAMDEBUG\fR to a non\-empty value. .TP 4 \fB\-\-git\-version\fR Print the git version if it exists and exit. .TP 4 \fB\-\-help\fR[=\fIFMT\fR] (default=pager) Show this help in format \fIFMT\fR (pager, plain or groff). .TP 4 \fB\-\-no\-aspcud\fR Do not use the external aspcud solver, even if available. .TP 4 \fB\-\-no\-base\-packages\fR Do not install base packages (useful for testing purposes). This is equivalent to setting \fB$OPAMNOBASEPACKAGES\fR to a non\-empty string. .TP 4 \fB\-q\fR, \fB\-\-quiet\fR Be quiet when installing a new compiler. .TP 4 \fB\-r\fR \fIROOT\fR, \fB\-\-root\fR=\fIROOT\fR (absent=~/.opam) Use \fIROOT\fR as the current root path. This is equivalent to setting \fB$OPAMROOT\fR to \fIROOT\fR. .TP 4 \fB\-\-strict\fR Fail whenever an error is found in a package definition or a configuration file. The default is to continue silently if possible. .TP 4 \fB\-\-switch\fR=\fISWITCH\fR Use \fISWITCH\fR as the current compiler switch. This is equivalent to setting \fB$OPAMSWITCH\fR to \fISWITCH\fR. .TP 4 \fB\-v\fR, \fB\-\-verbose\fR Be more verbose. This is equivalent to setting \fB$OPAMVERBOSE\fR to a non\-empty value. .TP 4 \fB\-\-version\fR Show version information. .TP 4 \fB\-y\fR, \fB\-\-yes\fR Disable interactive mode and answer yes to all questions that would otherwise be asked to the user. This is equivalent to setting \fB$OPAMYES\fR to a non\-empty string. .SH ENVIRONMENT VARIABLES .P opam makes use of environment variables listed here. .P \fIOPAMCOLOR\fR, when set to \fIalways\fR or \fInever\fR, sets a default value for the \-\-color option .P \fIOPAMCURL\fR can be used to define an alternative for the 'curl' command\-line utility to download files .SH FURTHER DOCUMENTATION .P See https://opam.ocaml.org. .SH AUTHORS .P Thomas Gazagnaire .sp -1 .P Anil Madhavapeddy .sp -1 .P Fabrice Le Fessant .sp -1 .P Frederic Tuong .sp -1 .P Louis Gesbert .sp -1 .P Vincent Bernardoff .sp -1 .P Guillem Rieu .SH BUGS .P Check bug reports at https://github.com/OCamlPro/opam/issues.opam-1.1.1/doc/man/opam-remove.10000644000175000017500000001221312272210733014541 0ustar i33173i33173.\" Pipe this output to groff -man -Tutf8 | less .\" .TH "OPAM-REMOVE" 1 "" "Opam 1.1.1" "Opam Manual" .\" Disable hyphenantion and ragged-right .nh .ad l .SH NAME .P opam\-remove \- Remove a list of packages. .SH SYNOPSIS .P \fBopam remove\fR [\fIOPTION\fR]... [\fIPACKAGES\fR]... .SH DESCRIPTION .P This command removes (i.e. uninstalls) one or more packages currently installed in the currently selected compiler switch. To remove packages installed in another compiler, you need to switch compilers using \fBopam switch\fR or use the \fB\-\-switch\fR flag. This command is the inverse of \fBopam\-install\fR. .SH ARGUMENTS .TP 4 \fIPACKAGES\fR List of package names. .SH OPTIONS .TP 4 \fB\-a\fR, \fB\-\-auto\-remove\fR Remove all the packages which have not been explicitly installed and which are not necessary anymore. It is possible to prevent the removal of an already\-installed package by running \fBopam install \fR. This flag can also be set using the \fB$OPAMAUTOREMOVE\fR configuration variable. .TP 4 \fB\-b\fR, \fB\-\-keep\-build\-dir\fR Keep the build directory. This is equivalent to setting \fB$OPAMKEEPBUILDIR\fR to a non\-empty string. .TP 4 \fB\-\-cudf\fR=\fIFILENAME\fR Save the CUDF request sent to the solver to \fIFILENAME\fR\-.cudf. .TP 4 \fB\-d\fR, \fB\-\-build\-doc\fR Build the package documentation. This is equivalent to setting \fB$OPAMBUILDDOC\fR to a non\-empty string. .TP 4 \fB\-\-dry\-run\fR Simply call the solver without actually performing any build/install operations. .TP 4 \fB\-e\fR \fITAGS\fR, \fB\-\-external\fR=\fITAGS\fR Display the external packages associated to the given tags. .TP 4 \fB\-\-fake\fR WARNING: This option is for testing purposes only! Using this option without care is the best way to corrupt your current compiler environment. When using this option OPAM will run a dry\-run of the solver and then fake the build and install commands. .TP 4 \fB\-\-force\fR Execute the remove commands of given packages directly, even if they are not considered installed by OPAM. .TP 4 \fB\-j\fR \fIJOBS\fR, \fB\-\-jobs\fR=\fIJOBS\fR Set the maximal number of concurrent jobs to use. You can also set it using the OPAMJOBS environment variable. .TP 4 \fB\-\-json\fR=\fIFILENAME\fR Save the result output of an OPAM run in a computer\-readable file .TP 4 \fB\-m\fR \fIMAKE\fR, \fB\-\-make\fR=\fIMAKE\fR Use \fIMAKE\fR as the default 'make' command. .TP 4 \fB\-\-no\-checksums\fR Do not verify the checksum of downloaded archives.This is equivalent to setting \fB$OPAMNOCHECKSUMS\fR to a non\-empty string. .TP 4 \fB\-t\fR, \fB\-\-build\-test\fR Build and \fBrun\fR the package unit\-tests. This is equivalent to setting \fB$OPAMBUILDTEST\fR to a non\-empty string. .SH COMMON OPTIONS .P These options are common to all commands. .TP 4 \fB\-\-color\fR=\fIWHEN\fR (absent=auto) Colorize the output. \fIWHEN\fR must be `always', `never' or `auto'. .TP 4 \fB\-\-compat\-mode\-1.0\fR Compatibility mode with OPAM 1.0 .TP 4 \fB\-\-debug\fR Print debug message on stdout. This is equivalent to setting \fB$OPAMDEBUG\fR to a non\-empty value. .TP 4 \fB\-\-git\-version\fR Print the git version if it exists and exit. .TP 4 \fB\-\-help\fR[=\fIFMT\fR] (default=pager) Show this help in format \fIFMT\fR (pager, plain or groff). .TP 4 \fB\-\-no\-aspcud\fR Do not use the external aspcud solver, even if available. .TP 4 \fB\-\-no\-base\-packages\fR Do not install base packages (useful for testing purposes). This is equivalent to setting \fB$OPAMNOBASEPACKAGES\fR to a non\-empty string. .TP 4 \fB\-q\fR, \fB\-\-quiet\fR Be quiet when installing a new compiler. .TP 4 \fB\-r\fR \fIROOT\fR, \fB\-\-root\fR=\fIROOT\fR (absent=~/.opam) Use \fIROOT\fR as the current root path. This is equivalent to setting \fB$OPAMROOT\fR to \fIROOT\fR. .TP 4 \fB\-\-strict\fR Fail whenever an error is found in a package definition or a configuration file. The default is to continue silently if possible. .TP 4 \fB\-\-switch\fR=\fISWITCH\fR Use \fISWITCH\fR as the current compiler switch. This is equivalent to setting \fB$OPAMSWITCH\fR to \fISWITCH\fR. .TP 4 \fB\-v\fR, \fB\-\-verbose\fR Be more verbose. This is equivalent to setting \fB$OPAMVERBOSE\fR to a non\-empty value. .TP 4 \fB\-\-version\fR Show version information. .TP 4 \fB\-y\fR, \fB\-\-yes\fR Disable interactive mode and answer yes to all questions that would otherwise be asked to the user. This is equivalent to setting \fB$OPAMYES\fR to a non\-empty string. .SH ENVIRONMENT VARIABLES .P opam makes use of environment variables listed here. .P \fIOPAMCOLOR\fR, when set to \fIalways\fR or \fInever\fR, sets a default value for the \-\-color option .P \fIOPAMCURL\fR can be used to define an alternative for the 'curl' command\-line utility to download files .SH FURTHER DOCUMENTATION .P See https://opam.ocaml.org. .SH AUTHORS .P Thomas Gazagnaire .sp -1 .P Anil Madhavapeddy .sp -1 .P Fabrice Le Fessant .sp -1 .P Frederic Tuong .sp -1 .P Louis Gesbert .sp -1 .P Vincent Bernardoff .sp -1 .P Guillem Rieu .SH BUGS .P Check bug reports at https://github.com/OCamlPro/opam/issues.opam-1.1.1/doc/man/opam-list.10000644000175000017500000000752312272210733014227 0ustar i33173i33173.\" Pipe this output to groff -man -Tutf8 | less .\" .TH "OPAM-LIST" 1 "" "Opam 1.1.1" "Opam Manual" .\" Disable hyphenantion and ragged-right .nh .ad l .SH NAME .P opam\-list \- Display the list of available packages. .SH SYNOPSIS .P \fBopam list\fR [\fIOPTION\fR]... [\fIPATTERNS\fR]... .SH DESCRIPTION .P This command displays the list of installed packages, or the list of all the available packages if the \fB\-\-all\fR flag is used. .P Unless the \fB\-\-short\fR switch is used, the output format displays one package per line, and each line contains the name of the package, the installed version or \-\- if the package is not installed, and a short description. In color mode, root packages (eg. manually installed) are underlined. .P The full description can be obtained by doing \fBopam info \fR. You can search through the package descriptions using the \fBopam search\fR command. .SH ARGUMENTS .TP 4 \fIPATTERNS\fR List of package patterns. .SH OPTIONS .TP 4 \fB\-a\fR, \fB\-\-all\fR List all the packages which can be installed on the system. .TP 4 \fB\-i\fR, \fB\-\-installed\fR List installed packages only. .TP 4 \fB\-\-installed\-roots\fR Display only the installed roots. .TP 4 \fB\-s\fR, \fB\-\-short\fR Output the names separated by one whitespace instead of using the usual formatting. .TP 4 \fB\-S\fR, \fB\-\-sort\fR Sort the packages in dependency order. .SH COMMON OPTIONS .P These options are common to all commands. .TP 4 \fB\-\-color\fR=\fIWHEN\fR (absent=auto) Colorize the output. \fIWHEN\fR must be `always', `never' or `auto'. .TP 4 \fB\-\-compat\-mode\-1.0\fR Compatibility mode with OPAM 1.0 .TP 4 \fB\-\-debug\fR Print debug message on stdout. This is equivalent to setting \fB$OPAMDEBUG\fR to a non\-empty value. .TP 4 \fB\-\-git\-version\fR Print the git version if it exists and exit. .TP 4 \fB\-\-help\fR[=\fIFMT\fR] (default=pager) Show this help in format \fIFMT\fR (pager, plain or groff). .TP 4 \fB\-\-no\-aspcud\fR Do not use the external aspcud solver, even if available. .TP 4 \fB\-\-no\-base\-packages\fR Do not install base packages (useful for testing purposes). This is equivalent to setting \fB$OPAMNOBASEPACKAGES\fR to a non\-empty string. .TP 4 \fB\-q\fR, \fB\-\-quiet\fR Be quiet when installing a new compiler. .TP 4 \fB\-r\fR \fIROOT\fR, \fB\-\-root\fR=\fIROOT\fR (absent=~/.opam) Use \fIROOT\fR as the current root path. This is equivalent to setting \fB$OPAMROOT\fR to \fIROOT\fR. .TP 4 \fB\-\-strict\fR Fail whenever an error is found in a package definition or a configuration file. The default is to continue silently if possible. .TP 4 \fB\-\-switch\fR=\fISWITCH\fR Use \fISWITCH\fR as the current compiler switch. This is equivalent to setting \fB$OPAMSWITCH\fR to \fISWITCH\fR. .TP 4 \fB\-v\fR, \fB\-\-verbose\fR Be more verbose. This is equivalent to setting \fB$OPAMVERBOSE\fR to a non\-empty value. .TP 4 \fB\-\-version\fR Show version information. .TP 4 \fB\-y\fR, \fB\-\-yes\fR Disable interactive mode and answer yes to all questions that would otherwise be asked to the user. This is equivalent to setting \fB$OPAMYES\fR to a non\-empty string. .SH ENVIRONMENT VARIABLES .P opam makes use of environment variables listed here. .P \fIOPAMCOLOR\fR, when set to \fIalways\fR or \fInever\fR, sets a default value for the \-\-color option .P \fIOPAMCURL\fR can be used to define an alternative for the 'curl' command\-line utility to download files .SH FURTHER DOCUMENTATION .P See https://opam.ocaml.org. .SH AUTHORS .P Thomas Gazagnaire .sp -1 .P Anil Madhavapeddy .sp -1 .P Fabrice Le Fessant .sp -1 .P Frederic Tuong .sp -1 .P Louis Gesbert .sp -1 .P Vincent Bernardoff .sp -1 .P Guillem Rieu .SH BUGS .P Check bug reports at https://github.com/OCamlPro/opam/issues.opam-1.1.1/doc/man/opam-upgrade.10000644000175000017500000001122612272210733014676 0ustar i33173i33173.\" Pipe this output to groff -man -Tutf8 | less .\" .TH "OPAM-UPGRADE" 1 "" "Opam 1.1.1" "Opam Manual" .\" Disable hyphenantion and ragged-right .nh .ad l .SH NAME .P opam\-upgrade \- Upgrade the installed package to latest version. .SH SYNOPSIS .P \fBopam upgrade\fR [\fIOPTION\fR]... [\fIPACKAGES\fR]... .SH DESCRIPTION .P This command upgrades the installed packages to their latest available versions. More precisely, this command calls the dependency solver to find a consistent state where \fImost\fR of the installed packages are upgraded to their latest versions. .SH ARGUMENTS .TP 4 \fIPACKAGES\fR List of package names. .SH OPTIONS .TP 4 \fB\-b\fR, \fB\-\-keep\-build\-dir\fR Keep the build directory. This is equivalent to setting \fB$OPAMKEEPBUILDIR\fR to a non\-empty string. .TP 4 \fB\-\-cudf\fR=\fIFILENAME\fR Save the CUDF request sent to the solver to \fIFILENAME\fR\-.cudf. .TP 4 \fB\-d\fR, \fB\-\-build\-doc\fR Build the package documentation. This is equivalent to setting \fB$OPAMBUILDDOC\fR to a non\-empty string. .TP 4 \fB\-\-dry\-run\fR Simply call the solver without actually performing any build/install operations. .TP 4 \fB\-e\fR \fITAGS\fR, \fB\-\-external\fR=\fITAGS\fR Display the external packages associated to the given tags. .TP 4 \fB\-\-fake\fR WARNING: This option is for testing purposes only! Using this option without care is the best way to corrupt your current compiler environment. When using this option OPAM will run a dry\-run of the solver and then fake the build and install commands. .TP 4 \fB\-j\fR \fIJOBS\fR, \fB\-\-jobs\fR=\fIJOBS\fR Set the maximal number of concurrent jobs to use. You can also set it using the OPAMJOBS environment variable. .TP 4 \fB\-\-json\fR=\fIFILENAME\fR Save the result output of an OPAM run in a computer\-readable file .TP 4 \fB\-m\fR \fIMAKE\fR, \fB\-\-make\fR=\fIMAKE\fR Use \fIMAKE\fR as the default 'make' command. .TP 4 \fB\-\-no\-checksums\fR Do not verify the checksum of downloaded archives.This is equivalent to setting \fB$OPAMNOCHECKSUMS\fR to a non\-empty string. .TP 4 \fB\-t\fR, \fB\-\-build\-test\fR Build and \fBrun\fR the package unit\-tests. This is equivalent to setting \fB$OPAMBUILDTEST\fR to a non\-empty string. .SH COMMON OPTIONS .P These options are common to all commands. .TP 4 \fB\-\-color\fR=\fIWHEN\fR (absent=auto) Colorize the output. \fIWHEN\fR must be `always', `never' or `auto'. .TP 4 \fB\-\-compat\-mode\-1.0\fR Compatibility mode with OPAM 1.0 .TP 4 \fB\-\-debug\fR Print debug message on stdout. This is equivalent to setting \fB$OPAMDEBUG\fR to a non\-empty value. .TP 4 \fB\-\-git\-version\fR Print the git version if it exists and exit. .TP 4 \fB\-\-help\fR[=\fIFMT\fR] (default=pager) Show this help in format \fIFMT\fR (pager, plain or groff). .TP 4 \fB\-\-no\-aspcud\fR Do not use the external aspcud solver, even if available. .TP 4 \fB\-\-no\-base\-packages\fR Do not install base packages (useful for testing purposes). This is equivalent to setting \fB$OPAMNOBASEPACKAGES\fR to a non\-empty string. .TP 4 \fB\-q\fR, \fB\-\-quiet\fR Be quiet when installing a new compiler. .TP 4 \fB\-r\fR \fIROOT\fR, \fB\-\-root\fR=\fIROOT\fR (absent=~/.opam) Use \fIROOT\fR as the current root path. This is equivalent to setting \fB$OPAMROOT\fR to \fIROOT\fR. .TP 4 \fB\-\-strict\fR Fail whenever an error is found in a package definition or a configuration file. The default is to continue silently if possible. .TP 4 \fB\-\-switch\fR=\fISWITCH\fR Use \fISWITCH\fR as the current compiler switch. This is equivalent to setting \fB$OPAMSWITCH\fR to \fISWITCH\fR. .TP 4 \fB\-v\fR, \fB\-\-verbose\fR Be more verbose. This is equivalent to setting \fB$OPAMVERBOSE\fR to a non\-empty value. .TP 4 \fB\-\-version\fR Show version information. .TP 4 \fB\-y\fR, \fB\-\-yes\fR Disable interactive mode and answer yes to all questions that would otherwise be asked to the user. This is equivalent to setting \fB$OPAMYES\fR to a non\-empty string. .SH ENVIRONMENT VARIABLES .P opam makes use of environment variables listed here. .P \fIOPAMCOLOR\fR, when set to \fIalways\fR or \fInever\fR, sets a default value for the \-\-color option .P \fIOPAMCURL\fR can be used to define an alternative for the 'curl' command\-line utility to download files .SH FURTHER DOCUMENTATION .P See https://opam.ocaml.org. .SH AUTHORS .P Thomas Gazagnaire .sp -1 .P Anil Madhavapeddy .sp -1 .P Fabrice Le Fessant .sp -1 .P Frederic Tuong .sp -1 .P Louis Gesbert .sp -1 .P Vincent Bernardoff .sp -1 .P Guillem Rieu .SH BUGS .P Check bug reports at https://github.com/OCamlPro/opam/issues.opam-1.1.1/doc/man/opam-search.10000644000175000017500000000720412272210733014515 0ustar i33173i33173.\" Pipe this output to groff -man -Tutf8 | less .\" .TH "OPAM-SEARCH" 1 "" "Opam 1.1.1" "Opam Manual" .\" Disable hyphenantion and ragged-right .nh .ad l .SH NAME .P opam\-search \- Search into the package list. .SH SYNOPSIS .P \fBopam search\fR [\fIOPTION\fR]... [\fIPATTERNS\fR]... .SH DESCRIPTION .P This command displays the list of available packages that match one of the package patterns specified as arguments. .P Unless the \fB\-\-short\fR flag is used, the output format is the same as the \fBopam list\fR command. It displays one package per line, and each line contains the name of the package, the installed version or \-\- if the package is not installed, and a short description. .P The full description can be obtained by doing \fBopam info \fR. .SH ARGUMENTS .TP 4 \fIPATTERNS\fR List of package patterns. .SH OPTIONS .TP 4 \fB\-c\fR, \fB\-\-case\-sensitive\fR Force the search in case sensitive mode. .TP 4 \fB\-i\fR, \fB\-\-installed\fR List installed packages only. .TP 4 \fB\-\-installed\-roots\fR Display only the installed roots. .TP 4 \fB\-s\fR, \fB\-\-short\fR Output the names separated by one whitespace instead of using the usual formatting. .SH COMMON OPTIONS .P These options are common to all commands. .TP 4 \fB\-\-color\fR=\fIWHEN\fR (absent=auto) Colorize the output. \fIWHEN\fR must be `always', `never' or `auto'. .TP 4 \fB\-\-compat\-mode\-1.0\fR Compatibility mode with OPAM 1.0 .TP 4 \fB\-\-debug\fR Print debug message on stdout. This is equivalent to setting \fB$OPAMDEBUG\fR to a non\-empty value. .TP 4 \fB\-\-git\-version\fR Print the git version if it exists and exit. .TP 4 \fB\-\-help\fR[=\fIFMT\fR] (default=pager) Show this help in format \fIFMT\fR (pager, plain or groff). .TP 4 \fB\-\-no\-aspcud\fR Do not use the external aspcud solver, even if available. .TP 4 \fB\-\-no\-base\-packages\fR Do not install base packages (useful for testing purposes). This is equivalent to setting \fB$OPAMNOBASEPACKAGES\fR to a non\-empty string. .TP 4 \fB\-q\fR, \fB\-\-quiet\fR Be quiet when installing a new compiler. .TP 4 \fB\-r\fR \fIROOT\fR, \fB\-\-root\fR=\fIROOT\fR (absent=~/.opam) Use \fIROOT\fR as the current root path. This is equivalent to setting \fB$OPAMROOT\fR to \fIROOT\fR. .TP 4 \fB\-\-strict\fR Fail whenever an error is found in a package definition or a configuration file. The default is to continue silently if possible. .TP 4 \fB\-\-switch\fR=\fISWITCH\fR Use \fISWITCH\fR as the current compiler switch. This is equivalent to setting \fB$OPAMSWITCH\fR to \fISWITCH\fR. .TP 4 \fB\-v\fR, \fB\-\-verbose\fR Be more verbose. This is equivalent to setting \fB$OPAMVERBOSE\fR to a non\-empty value. .TP 4 \fB\-\-version\fR Show version information. .TP 4 \fB\-y\fR, \fB\-\-yes\fR Disable interactive mode and answer yes to all questions that would otherwise be asked to the user. This is equivalent to setting \fB$OPAMYES\fR to a non\-empty string. .SH ENVIRONMENT VARIABLES .P opam makes use of environment variables listed here. .P \fIOPAMCOLOR\fR, when set to \fIalways\fR or \fInever\fR, sets a default value for the \-\-color option .P \fIOPAMCURL\fR can be used to define an alternative for the 'curl' command\-line utility to download files .SH FURTHER DOCUMENTATION .P See https://opam.ocaml.org. .SH AUTHORS .P Thomas Gazagnaire .sp -1 .P Anil Madhavapeddy .sp -1 .P Fabrice Le Fessant .sp -1 .P Frederic Tuong .sp -1 .P Louis Gesbert .sp -1 .P Vincent Bernardoff .sp -1 .P Guillem Rieu .SH BUGS .P Check bug reports at https://github.com/OCamlPro/opam/issues.opam-1.1.1/doc/man/opam-install.10000644000175000017500000001256712272210733014726 0ustar i33173i33173.\" Pipe this output to groff -man -Tutf8 | less .\" .TH "OPAM-INSTALL" 1 "" "Opam 1.1.1" "Opam Manual" .\" Disable hyphenantion and ragged-right .nh .ad l .SH NAME .P opam\-install \- Install a list of packages. .SH SYNOPSIS .P \fBopam install\fR [\fIOPTION\fR]... [\fIPACKAGES\fR]... .SH DESCRIPTION .P This command installs one or more packages to the currently selected compiler. To install packages for another compiler, you need to switch compilers using \fBopam switch\fR. You can remove installed packages with \fBopam remove\fR, and list installed packages with \fBopam list \-i\fR. See \fBopam pin\fR as well to understand how to manage package versions. .P This command makes OPAM use the dependency solver to compute the transitive closure of dependencies to be installed, and will also handle conflicts. If the dependency solver returns more than one solution, OPAM will arbitrarily select the first one. If dependencies are to be installed, OPAM will confirm if the installation should proceed. .SH ARGUMENTS .TP 4 \fIPACKAGES\fR List of package names. .SH OPTIONS .TP 4 \fB\-b\fR, \fB\-\-keep\-build\-dir\fR Keep the build directory. This is equivalent to setting \fB$OPAMKEEPBUILDIR\fR to a non\-empty string. .TP 4 \fB\-\-cudf\fR=\fIFILENAME\fR Save the CUDF request sent to the solver to \fIFILENAME\fR\-.cudf. .TP 4 \fB\-d\fR, \fB\-\-build\-doc\fR Build the package documentation. This is equivalent to setting \fB$OPAMBUILDDOC\fR to a non\-empty string. .TP 4 \fB\-\-deps\-only\fR Install all its dependencies, but don't actually install the package. .TP 4 \fB\-\-dry\-run\fR Simply call the solver without actually performing any build/install operations. .TP 4 \fB\-e\fR \fITAGS\fR, \fB\-\-external\fR=\fITAGS\fR Display the external packages associated to the given tags. .TP 4 \fB\-\-fake\fR WARNING: This option is for testing purposes only! Using this option without care is the best way to corrupt your current compiler environment. When using this option OPAM will run a dry\-run of the solver and then fake the build and install commands. .TP 4 \fB\-j\fR \fIJOBS\fR, \fB\-\-jobs\fR=\fIJOBS\fR Set the maximal number of concurrent jobs to use. You can also set it using the OPAMJOBS environment variable. .TP 4 \fB\-\-json\fR=\fIFILENAME\fR Save the result output of an OPAM run in a computer\-readable file .TP 4 \fB\-m\fR \fIMAKE\fR, \fB\-\-make\fR=\fIMAKE\fR Use \fIMAKE\fR as the default 'make' command. .TP 4 \fB\-\-no\-checksums\fR Do not verify the checksum of downloaded archives.This is equivalent to setting \fB$OPAMNOCHECKSUMS\fR to a non\-empty string. .TP 4 \fB\-\-set\-root\fR Mark given packages as installed roots. This is the default for newly manually\-installed packages. .TP 4 \fB\-t\fR, \fB\-\-build\-test\fR Build and \fBrun\fR the package unit\-tests. This is equivalent to setting \fB$OPAMBUILDTEST\fR to a non\-empty string. .TP 4 \fB\-\-unset\-root\fR Mark given packages as "installed automatically". .SH COMMON OPTIONS .P These options are common to all commands. .TP 4 \fB\-\-color\fR=\fIWHEN\fR (absent=auto) Colorize the output. \fIWHEN\fR must be `always', `never' or `auto'. .TP 4 \fB\-\-compat\-mode\-1.0\fR Compatibility mode with OPAM 1.0 .TP 4 \fB\-\-debug\fR Print debug message on stdout. This is equivalent to setting \fB$OPAMDEBUG\fR to a non\-empty value. .TP 4 \fB\-\-git\-version\fR Print the git version if it exists and exit. .TP 4 \fB\-\-help\fR[=\fIFMT\fR] (default=pager) Show this help in format \fIFMT\fR (pager, plain or groff). .TP 4 \fB\-\-no\-aspcud\fR Do not use the external aspcud solver, even if available. .TP 4 \fB\-\-no\-base\-packages\fR Do not install base packages (useful for testing purposes). This is equivalent to setting \fB$OPAMNOBASEPACKAGES\fR to a non\-empty string. .TP 4 \fB\-q\fR, \fB\-\-quiet\fR Be quiet when installing a new compiler. .TP 4 \fB\-r\fR \fIROOT\fR, \fB\-\-root\fR=\fIROOT\fR (absent=~/.opam) Use \fIROOT\fR as the current root path. This is equivalent to setting \fB$OPAMROOT\fR to \fIROOT\fR. .TP 4 \fB\-\-strict\fR Fail whenever an error is found in a package definition or a configuration file. The default is to continue silently if possible. .TP 4 \fB\-\-switch\fR=\fISWITCH\fR Use \fISWITCH\fR as the current compiler switch. This is equivalent to setting \fB$OPAMSWITCH\fR to \fISWITCH\fR. .TP 4 \fB\-v\fR, \fB\-\-verbose\fR Be more verbose. This is equivalent to setting \fB$OPAMVERBOSE\fR to a non\-empty value. .TP 4 \fB\-\-version\fR Show version information. .TP 4 \fB\-y\fR, \fB\-\-yes\fR Disable interactive mode and answer yes to all questions that would otherwise be asked to the user. This is equivalent to setting \fB$OPAMYES\fR to a non\-empty string. .SH ENVIRONMENT VARIABLES .P opam makes use of environment variables listed here. .P \fIOPAMCOLOR\fR, when set to \fIalways\fR or \fInever\fR, sets a default value for the \-\-color option .P \fIOPAMCURL\fR can be used to define an alternative for the 'curl' command\-line utility to download files .SH FURTHER DOCUMENTATION .P See https://opam.ocaml.org. .SH AUTHORS .P Thomas Gazagnaire .sp -1 .P Anil Madhavapeddy .sp -1 .P Fabrice Le Fessant .sp -1 .P Frederic Tuong .sp -1 .P Louis Gesbert .sp -1 .P Vincent Bernardoff .sp -1 .P Guillem Rieu .SH BUGS .P Check bug reports at https://github.com/OCamlPro/opam/issues.opam-1.1.1/doc/man/opam-remote.10000644000175000017500000000506512272210733014546 0ustar i33173i33173.\" Pipe this output to groff -man -Tutf8 | less .\" .TH "OPAM-REMOTE" 1 "" "Opam 1.1.1" "Opam Manual" .\" Disable hyphenantion and ragged-right .nh .ad l .SH NAME .P opam\-remote \- An alias for \fBrepository\fR. .SH SYNOPSIS .P \fBopam remote\fR [\fIOPTION\fR]... [\fICOMMAND\fR] [\fIARG\fR]... .SH DESCRIPTION .P \fBopam remote\fR is an alias for \fBopam repository\fR. .P See \fBopam repository \-\-help\fR for details. .SH ARGUMENTS .TP 4 \fICOMMAND\fR Name of the sub\-command. See the \fBCOMMANDS\fR section for more info. .SH COMMON OPTIONS .TP 4 \fB\-\-color\fR=\fIWHEN\fR (absent=auto) Colorize the output. \fIWHEN\fR must be `always', `never' or `auto'. .TP 4 \fB\-\-compat\-mode\-1.0\fR Compatibility mode with OPAM 1.0 .TP 4 \fB\-\-debug\fR Print debug message on stdout. This is equivalent to setting \fB$OPAMDEBUG\fR to a non\-empty value. .TP 4 \fB\-\-git\-version\fR Print the git version if it exists and exit. .TP 4 \fB\-\-no\-aspcud\fR Do not use the external aspcud solver, even if available. .TP 4 \fB\-\-no\-base\-packages\fR Do not install base packages (useful for testing purposes). This is equivalent to setting \fB$OPAMNOBASEPACKAGES\fR to a non\-empty string. .TP 4 \fB\-q\fR, \fB\-\-quiet\fR Be quiet when installing a new compiler. .TP 4 \fB\-r\fR \fIROOT\fR, \fB\-\-root\fR=\fIROOT\fR (absent=~/.opam) Use \fIROOT\fR as the current root path. This is equivalent to setting \fB$OPAMROOT\fR to \fIROOT\fR. .TP 4 \fB\-\-strict\fR Fail whenever an error is found in a package definition or a configuration file. The default is to continue silently if possible. .TP 4 \fB\-\-switch\fR=\fISWITCH\fR Use \fISWITCH\fR as the current compiler switch. This is equivalent to setting \fB$OPAMSWITCH\fR to \fISWITCH\fR. .TP 4 \fB\-v\fR, \fB\-\-verbose\fR Be more verbose. This is equivalent to setting \fB$OPAMVERBOSE\fR to a non\-empty value. .TP 4 \fB\-y\fR, \fB\-\-yes\fR Disable interactive mode and answer yes to all questions that would otherwise be asked to the user. This is equivalent to setting \fB$OPAMYES\fR to a non\-empty string. .SH OPTIONS .TP 4 \fB\-\-help\fR[=\fIFMT\fR] (default=pager) Show this help in format \fIFMT\fR (pager, plain or groff). .TP 4 \fB\-k\fR \fIKIND\fR, \fB\-\-kind\fR=\fIKIND\fR Specify the kind of the repository to be set (the main ones are 'http', 'local', 'git', 'darcs' or 'hg'). .TP 4 \fB\-p\fR \fIINT\fR, \fB\-\-priority\fR=\fIINT\fR Set the repository priority (bigger is better) .TP 4 \fB\-s\fR, \fB\-\-short\fR Output the names separated by one whitespace instead of using the usual formatting. .TP 4 \fB\-\-version\fR Show version information.opam-1.1.1/doc/man/opam-pin.10000644000175000017500000000763512272210733014046 0ustar i33173i33173.\" Pipe this output to groff -man -Tutf8 | less .\" .TH "OPAM-PIN" 1 "" "Opam 1.1.1" "Opam Manual" .\" Disable hyphenantion and ragged-right .nh .ad l .SH NAME .P opam\-pin \- Pin a given package to a specific version. .SH SYNOPSIS .P \fBopam pin\fR [\fIOPTION\fR]... [\fIPACKAGE\fR] [\fIPIN\fR] .SH DESCRIPTION .P This command will 'pin' a package to a specific version, or use a specific source path for installing and upgrading the package. Using \fBopam pin none\fR will undo the 'pinned' status of . .P It is possible to pin a package to a specific git commit/tag/branch with \fBopam pin #\fR. .P By default, local directories will be pinned as `local` backends. You can change that default choice by forcing a given backend kind using the \fB\-\-kind\fR option. .P To list all the currently pinned packages, call the \fBopam pin\fR without arguments or use \fB\-\-list\fR. .SH ARGUMENTS .TP 4 \fIPACKAGE\fR Package name. .TP 4 \fIPIN\fR Specific version, local path, git or darcs url to pin the package to, or 'none' to unpin the package. .SH OPTIONS .TP 4 \fB\-e\fR, \fB\-\-edit\fR Edit the OPAM file associated to the given package. .TP 4 \fB\-f\fR, \fB\-\-force\fR Disable consistency checks. .TP 4 \fB\-k\fR \fIKIND\fR, \fB\-\-kind\fR=\fIKIND\fR Force the kind of pinning. .TP 4 \fB\-l\fR, \fB\-\-list\fR List the currently pinned packages. .TP 4 \fB\-u\fR, \fB\-\-unpin\fR Unpin the given package. .SH COMMON OPTIONS .P These options are common to all commands. .TP 4 \fB\-\-color\fR=\fIWHEN\fR (absent=auto) Colorize the output. \fIWHEN\fR must be `always', `never' or `auto'. .TP 4 \fB\-\-compat\-mode\-1.0\fR Compatibility mode with OPAM 1.0 .TP 4 \fB\-\-debug\fR Print debug message on stdout. This is equivalent to setting \fB$OPAMDEBUG\fR to a non\-empty value. .TP 4 \fB\-\-git\-version\fR Print the git version if it exists and exit. .TP 4 \fB\-\-help\fR[=\fIFMT\fR] (default=pager) Show this help in format \fIFMT\fR (pager, plain or groff). .TP 4 \fB\-\-no\-aspcud\fR Do not use the external aspcud solver, even if available. .TP 4 \fB\-\-no\-base\-packages\fR Do not install base packages (useful for testing purposes). This is equivalent to setting \fB$OPAMNOBASEPACKAGES\fR to a non\-empty string. .TP 4 \fB\-q\fR, \fB\-\-quiet\fR Be quiet when installing a new compiler. .TP 4 \fB\-r\fR \fIROOT\fR, \fB\-\-root\fR=\fIROOT\fR (absent=~/.opam) Use \fIROOT\fR as the current root path. This is equivalent to setting \fB$OPAMROOT\fR to \fIROOT\fR. .TP 4 \fB\-\-strict\fR Fail whenever an error is found in a package definition or a configuration file. The default is to continue silently if possible. .TP 4 \fB\-\-switch\fR=\fISWITCH\fR Use \fISWITCH\fR as the current compiler switch. This is equivalent to setting \fB$OPAMSWITCH\fR to \fISWITCH\fR. .TP 4 \fB\-v\fR, \fB\-\-verbose\fR Be more verbose. This is equivalent to setting \fB$OPAMVERBOSE\fR to a non\-empty value. .TP 4 \fB\-\-version\fR Show version information. .TP 4 \fB\-y\fR, \fB\-\-yes\fR Disable interactive mode and answer yes to all questions that would otherwise be asked to the user. This is equivalent to setting \fB$OPAMYES\fR to a non\-empty string. .SH ENVIRONMENT VARIABLES .P opam makes use of environment variables listed here. .P \fIOPAMCOLOR\fR, when set to \fIalways\fR or \fInever\fR, sets a default value for the \-\-color option .P \fIOPAMCURL\fR can be used to define an alternative for the 'curl' command\-line utility to download files .SH FURTHER DOCUMENTATION .P See https://opam.ocaml.org. .SH AUTHORS .P Thomas Gazagnaire .sp -1 .P Anil Madhavapeddy .sp -1 .P Fabrice Le Fessant .sp -1 .P Frederic Tuong .sp -1 .P Louis Gesbert .sp -1 .P Vincent Bernardoff .sp -1 .P Guillem Rieu .SH BUGS .P Check bug reports at https://github.com/OCamlPro/opam/issues.opam-1.1.1/doc/man/opam-admin-check.10000644000175000017500000000403312272210733015410 0ustar i33173i33173.\" Pipe this output to groff -man -Tutf8 | less .\" .TH "OPAM-ADMIN-CHECK" 1 "" "Opam-admin 1.1.1" "Opam-admin Manual" .\" Disable hyphenantion and ragged-right .nh .ad l .SH NAME .P opam\-admin\-check \- Check a local repo for errors. .SH SYNOPSIS .P \fBopam\-admin check\fR [\fIOPTION\fR]... .SH COMMON OPTIONS .TP 4 \fB\-\-color\fR=\fIWHEN\fR (absent=auto) Colorize the output. \fIWHEN\fR must be `always', `never' or `auto'. .TP 4 \fB\-\-compat\-mode\-1.0\fR Compatibility mode with OPAM 1.0 .TP 4 \fB\-\-debug\fR Print debug message on stdout. This is equivalent to setting \fB$OPAMDEBUG\fR to a non\-empty value. .TP 4 \fB\-\-git\-version\fR Print the git version if it exists and exit. .TP 4 \fB\-\-no\-aspcud\fR Do not use the external aspcud solver, even if available. .TP 4 \fB\-\-no\-base\-packages\fR Do not install base packages (useful for testing purposes). This is equivalent to setting \fB$OPAMNOBASEPACKAGES\fR to a non\-empty string. .TP 4 \fB\-q\fR, \fB\-\-quiet\fR Be quiet when installing a new compiler. .TP 4 \fB\-r\fR \fIROOT\fR, \fB\-\-root\fR=\fIROOT\fR (absent=~/.opam) Use \fIROOT\fR as the current root path. This is equivalent to setting \fB$OPAMROOT\fR to \fIROOT\fR. .TP 4 \fB\-\-strict\fR Fail whenever an error is found in a package definition or a configuration file. The default is to continue silently if possible. .TP 4 \fB\-\-switch\fR=\fISWITCH\fR Use \fISWITCH\fR as the current compiler switch. This is equivalent to setting \fB$OPAMSWITCH\fR to \fISWITCH\fR. .TP 4 \fB\-v\fR, \fB\-\-verbose\fR Be more verbose. This is equivalent to setting \fB$OPAMVERBOSE\fR to a non\-empty value. .TP 4 \fB\-y\fR, \fB\-\-yes\fR Disable interactive mode and answer yes to all questions that would otherwise be asked to the user. This is equivalent to setting \fB$OPAMYES\fR to a non\-empty string. .SH OPTIONS .TP 4 \fB\-\-help\fR[=\fIFMT\fR] (default=pager) Show this help in format \fIFMT\fR (pager, plain or groff). .TP 4 \fB\-n\fR, \fB\-\-normalize\fR Normalize all files in the repository. .TP 4 \fB\-\-version\fR Show version information.opam-1.1.1/doc/man/opam-update.10000644000175000017500000000745112272210733014536 0ustar i33173i33173.\" Pipe this output to groff -man -Tutf8 | less .\" .TH "OPAM-UPDATE" 1 "" "Opam 1.1.1" "Opam Manual" .\" Disable hyphenantion and ragged-right .nh .ad l .SH NAME .P opam\-update \- Update the list of available packages. .SH SYNOPSIS .P \fBopam update\fR [\fIOPTION\fR]... [\fIREPOSITORIES\fR]... .SH DESCRIPTION .P This command updates each repository that has been previously set up by the \fBopam init\fR or \fBopam repository\fR commands. The list of packages that can be upgraded will be printed out, and the user can use \fBopam upgrade\fR to upgrade them. .SH ARGUMENTS .TP 4 \fIREPOSITORIES\fR List of repository names. .SH OPTIONS .TP 4 \fB\-j\fR \fIJOBS\fR, \fB\-\-jobs\fR=\fIJOBS\fR Set the maximal number of concurrent jobs to use. You can also set it using the OPAMJOBS environment variable. .TP 4 \fB\-\-json\fR=\fIFILENAME\fR Save the result output of an OPAM run in a computer\-readable file .TP 4 \fB\-R\fR, \fB\-\-repositories\fR Only update repositories, not development packages. .TP 4 \fB\-\-sync\-archives\fR Always sync the remote archives files. This is not a good idea to enable this, unless your really know what your are doing: this flag will make OPAM try to download the archive files for ALL the available packages. .TP 4 \fB\-u\fR, \fB\-\-upgrade\fR Automatically run \fBopam upgrade \-\-yes\fR after the update. .SH COMMON OPTIONS .P These options are common to all commands. .TP 4 \fB\-\-color\fR=\fIWHEN\fR (absent=auto) Colorize the output. \fIWHEN\fR must be `always', `never' or `auto'. .TP 4 \fB\-\-compat\-mode\-1.0\fR Compatibility mode with OPAM 1.0 .TP 4 \fB\-\-debug\fR Print debug message on stdout. This is equivalent to setting \fB$OPAMDEBUG\fR to a non\-empty value. .TP 4 \fB\-\-git\-version\fR Print the git version if it exists and exit. .TP 4 \fB\-\-help\fR[=\fIFMT\fR] (default=pager) Show this help in format \fIFMT\fR (pager, plain or groff). .TP 4 \fB\-\-no\-aspcud\fR Do not use the external aspcud solver, even if available. .TP 4 \fB\-\-no\-base\-packages\fR Do not install base packages (useful for testing purposes). This is equivalent to setting \fB$OPAMNOBASEPACKAGES\fR to a non\-empty string. .TP 4 \fB\-q\fR, \fB\-\-quiet\fR Be quiet when installing a new compiler. .TP 4 \fB\-r\fR \fIROOT\fR, \fB\-\-root\fR=\fIROOT\fR (absent=~/.opam) Use \fIROOT\fR as the current root path. This is equivalent to setting \fB$OPAMROOT\fR to \fIROOT\fR. .TP 4 \fB\-\-strict\fR Fail whenever an error is found in a package definition or a configuration file. The default is to continue silently if possible. .TP 4 \fB\-\-switch\fR=\fISWITCH\fR Use \fISWITCH\fR as the current compiler switch. This is equivalent to setting \fB$OPAMSWITCH\fR to \fISWITCH\fR. .TP 4 \fB\-v\fR, \fB\-\-verbose\fR Be more verbose. This is equivalent to setting \fB$OPAMVERBOSE\fR to a non\-empty value. .TP 4 \fB\-\-version\fR Show version information. .TP 4 \fB\-y\fR, \fB\-\-yes\fR Disable interactive mode and answer yes to all questions that would otherwise be asked to the user. This is equivalent to setting \fB$OPAMYES\fR to a non\-empty string. .SH ENVIRONMENT VARIABLES .P opam makes use of environment variables listed here. .P \fIOPAMCOLOR\fR, when set to \fIalways\fR or \fInever\fR, sets a default value for the \-\-color option .P \fIOPAMCURL\fR can be used to define an alternative for the 'curl' command\-line utility to download files .SH FURTHER DOCUMENTATION .P See https://opam.ocaml.org. .SH AUTHORS .P Thomas Gazagnaire .sp -1 .P Anil Madhavapeddy .sp -1 .P Fabrice Le Fessant .sp -1 .P Frederic Tuong .sp -1 .P Louis Gesbert .sp -1 .P Vincent Bernardoff .sp -1 .P Guillem Rieu .SH BUGS .P Check bug reports at https://github.com/OCamlPro/opam/issues.opam-1.1.1/doc/man/opam-help.10000644000175000017500000000134312272210733014176 0ustar i33173i33173.\" Pipe this output to groff -man -Tutf8 | less .\" .TH "OPAM-HELP" 1 "" "Opam 1.1.1" "Opam Manual" .\" Disable hyphenantion and ragged-right .nh .ad l .SH NAME .P opam\-help \- Display help about OPAM and OPAM commands. .SH SYNOPSIS .P \fBopam help\fR [\fIOPTION\fR]... [\fITOPIC\fR] .SH DESCRIPTION .P Prints help about OPAM commands. .P Use `opam help topics' to get the full list of help topics. .SH ARGUMENTS .TP 4 \fITOPIC\fR The topic to get help on. .SH OPTIONS .TP 4 \fB\-\-help\fR[=\fIFMT\fR] (default=pager) Show this help in format \fIFMT\fR (pager, plain or groff). .TP 4 \fB\-\-man\-format\fR=\fIFMT\fR (absent=pager) Show output in format \fIFMT\fR (pager, plain or groff). .TP 4 \fB\-\-version\fR Show version information.opam-1.1.1/doc/man/opam-show.10000644000175000017500000000663212272210733014234 0ustar i33173i33173.\" Pipe this output to groff -man -Tutf8 | less .\" .TH "OPAM-SHOW" 1 "" "Opam 1.1.1" "Opam Manual" .\" Disable hyphenantion and ragged-right .nh .ad l .SH NAME .P opam\-show \- Display information about specific packages. .SH SYNOPSIS .P \fBopam show\fR [\fIOPTION\fR]... [\fIPATTERNS\fR]... .SH DESCRIPTION .P This command displays the information block for the selected package(s). .P The information block consists in the name of the package, the installed version if this package is installed in the currently selected compiler, the list of available (installable) versions, and a complete description. .P \fBopam list\fR can be used to display the list of available packages as well as a short description for each. .SH ARGUMENTS .TP 4 \fIPATTERNS\fR List of package patterns. .SH OPTIONS .TP 4 \fB\-f\fR \fIFIELDS\fR, \fB\-\-field\fR=\fIFIELDS\fR Only display these fields. You can specify multiple fields by separating them with commas. .SH COMMON OPTIONS .P These options are common to all commands. .TP 4 \fB\-\-color\fR=\fIWHEN\fR (absent=auto) Colorize the output. \fIWHEN\fR must be `always', `never' or `auto'. .TP 4 \fB\-\-compat\-mode\-1.0\fR Compatibility mode with OPAM 1.0 .TP 4 \fB\-\-debug\fR Print debug message on stdout. This is equivalent to setting \fB$OPAMDEBUG\fR to a non\-empty value. .TP 4 \fB\-\-git\-version\fR Print the git version if it exists and exit. .TP 4 \fB\-\-help\fR[=\fIFMT\fR] (default=pager) Show this help in format \fIFMT\fR (pager, plain or groff). .TP 4 \fB\-\-no\-aspcud\fR Do not use the external aspcud solver, even if available. .TP 4 \fB\-\-no\-base\-packages\fR Do not install base packages (useful for testing purposes). This is equivalent to setting \fB$OPAMNOBASEPACKAGES\fR to a non\-empty string. .TP 4 \fB\-q\fR, \fB\-\-quiet\fR Be quiet when installing a new compiler. .TP 4 \fB\-r\fR \fIROOT\fR, \fB\-\-root\fR=\fIROOT\fR (absent=~/.opam) Use \fIROOT\fR as the current root path. This is equivalent to setting \fB$OPAMROOT\fR to \fIROOT\fR. .TP 4 \fB\-\-strict\fR Fail whenever an error is found in a package definition or a configuration file. The default is to continue silently if possible. .TP 4 \fB\-\-switch\fR=\fISWITCH\fR Use \fISWITCH\fR as the current compiler switch. This is equivalent to setting \fB$OPAMSWITCH\fR to \fISWITCH\fR. .TP 4 \fB\-v\fR, \fB\-\-verbose\fR Be more verbose. This is equivalent to setting \fB$OPAMVERBOSE\fR to a non\-empty value. .TP 4 \fB\-\-version\fR Show version information. .TP 4 \fB\-y\fR, \fB\-\-yes\fR Disable interactive mode and answer yes to all questions that would otherwise be asked to the user. This is equivalent to setting \fB$OPAMYES\fR to a non\-empty string. .SH ENVIRONMENT VARIABLES .P opam makes use of environment variables listed here. .P \fIOPAMCOLOR\fR, when set to \fIalways\fR or \fInever\fR, sets a default value for the \-\-color option .P \fIOPAMCURL\fR can be used to define an alternative for the 'curl' command\-line utility to download files .SH FURTHER DOCUMENTATION .P See https://opam.ocaml.org. .SH AUTHORS .P Thomas Gazagnaire .sp -1 .P Anil Madhavapeddy .sp -1 .P Fabrice Le Fessant .sp -1 .P Frederic Tuong .sp -1 .P Louis Gesbert .sp -1 .P Vincent Bernardoff .sp -1 .P Guillem Rieu .SH BUGS .P Check bug reports at https://github.com/OCamlPro/opam/issues.opam-1.1.1/doc/man/opam-admin.10000644000175000017500000000122412272210733014334 0ustar i33173i33173.\" Pipe this output to groff -man -Tutf8 | less .\" .TH "OPAM-ADMIN" 1 "" "Opam-admin 1.1.1" "Opam-admin Manual" .\" Disable hyphenantion and ragged-right .nh .ad l .SH NAME .P opam\-admin \- Administration tool for local repositories. .SH SYNOPSIS .P \fBopam\-admin\fR \fICOMMAND\fR ... .SH COMMANDS .TP 4 \fBcheck\fR Check a local repo for errors. .TP 4 \fBdepexts\fR Add external dependencies. .TP 4 \fBmake\fR Initialize a repo for serving files. .TP 4 \fBstats\fR Compute statistics. .SH OPTIONS .TP 4 \fB\-\-help\fR[=\fIFMT\fR] (default=pager) Show this help in format \fIFMT\fR (pager, plain or groff). .TP 4 \fB\-\-version\fR Show version information.opam-1.1.1/src/0000755000175000017500000000000012272210733011500 5ustar i33173i33173opam-1.1.1/src/core/0000755000175000017500000000000012272210733012430 5ustar i33173i33173opam-1.1.1/src/core/opamFilename.ml0000644000175000017500000002772212272210733015371 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) module Base = OpamMisc.Base let log fmt = OpamGlobals.log "FILENAME" fmt module Dir = struct include OpamMisc.Base let of_string dirname = if (String.length dirname >= 1 && dirname.[0] = '~') then let home = OpamMisc.getenv "HOME" in match dirname with | "~" -> home | _ -> let prefix = Filename.concat "~" "" in let suffix = OpamMisc.remove_prefix ~prefix dirname in Filename.concat home suffix else if Filename.is_relative dirname then OpamSystem.real_path dirname else dirname let to_string dirname = OpamSystem.real_path dirname end let raw_dir s = s let with_tmp_dir fn = OpamSystem.with_tmp_dir (fun dir -> fn (Dir.of_string dir)) let rmdir dirname = log "rmdir %s" (Dir.to_string dirname); OpamSystem.remove (Dir.to_string dirname) let cwd () = Dir.of_string (Unix.getcwd ()) let mkdir dirname = OpamSystem.mkdir (Dir.to_string dirname) let cleandir dirname = log "cleandir %s" (Dir.to_string dirname); OpamSystem.remove (Dir.to_string dirname); mkdir dirname let rec_dirs d = let fs = OpamSystem.rec_dirs (Dir.to_string d) in List.rev (List.rev_map Dir.of_string fs) let dirs d = let fs = OpamSystem.dirs (Dir.to_string d) in List.rev (List.rev_map Dir.of_string fs) let in_dir dirname fn = if Sys.file_exists dirname then OpamSystem.in_dir dirname fn else OpamSystem.internal_error "Cannot CD to %s: the directory does not exist!" dirname let exec dirname ?env ?name ?metadata ?keep_going cmds = let env = match env with | None -> None | Some l -> Some (Array.of_list (List.rev_map (fun (k,v) -> k^"="^v) l)) in in_dir dirname (fun () -> OpamSystem.commands ?env ?name ?metadata ?keep_going cmds) let move_dir ~src ~dst = OpamSystem.command [ "mv"; Dir.to_string src; Dir.to_string dst ] let exists_dir dirname = let f = Dir.to_string dirname in Sys.file_exists f && Sys.is_directory f let copy_dir ~src ~dst = if exists_dir dst then OpamSystem.internal_error "Cannot create %s as the directory already exists." (Dir.to_string dst); OpamSystem.command [ "cp"; "-pPR"; Dir.to_string src; Dir.to_string dst ] let link_dir ~src ~dst = if exists_dir dst then OpamSystem.internal_error "Cannot link: %s already exists." (Dir.to_string dst) else ( mkdir (Filename.dirname dst); OpamSystem.link (Dir.to_string src) (Dir.to_string dst) ) let basename_dir dirname = Base.of_string (Filename.basename (Dir.to_string dirname)) let dirname_dir dirname = Dir.to_string (Filename.dirname (Dir.of_string dirname)) let to_list_dir dir = let base d = Dir.of_string (Filename.basename (Dir.to_string d)) in let rec aux acc dir = let d = dirname_dir dir in if d <> dir then aux (base dir :: acc) d else base dir :: acc in aux [] dir let (/) d1 s2 = let s1 = Dir.to_string d1 in raw_dir (Filename.concat s1 s2) type t = { dirname: Dir.t; basename: Base.t; } let create dirname basename = let b1 = Filename.dirname (Base.to_string basename) in let b2 = Base.of_string (Filename.basename (Base.to_string basename)) in if basename = b2 then { dirname; basename } else { dirname = dirname / b1; basename = b2 } let of_basename basename = let dirname = Dir.of_string "." in { dirname; basename } let raw str = let dirname = raw_dir (Filename.dirname str) in let basename = Base.of_string (Filename.basename str) in create dirname basename let to_string t = Filename.concat (Dir.to_string t.dirname) (Base.to_string t.basename) let digest t = Digest.to_hex (Digest.file (to_string t)) let touch t = OpamSystem.write (to_string t) "" let chmod t p = Unix.chmod (to_string t) p let of_string s = let dirname = Filename.dirname s in let basename = Filename.basename s in { dirname = Dir.of_string dirname; basename = Base.of_string basename; } let dirname t = t.dirname let basename t = t.basename let read filename = OpamSystem.read (to_string filename) let open_in filename = open_in (to_string filename) let write filename raw = OpamSystem.write (to_string filename) raw let remove filename = OpamSystem.remove_file (to_string filename) let exists filename = let f = to_string filename in Sys.file_exists f && not (Sys.is_directory f) let with_contents fn filename = fn (read filename) let check_suffix filename s = Filename.check_suffix (to_string filename) s let add_extension filename suffix = of_string ((to_string filename) ^ "." ^ suffix) let chop_extension filename = of_string (Filename.chop_extension (to_string filename)) let rec_files d = let fs = OpamSystem.rec_files (Dir.to_string d) in List.rev_map of_string fs let files d = let fs = OpamSystem.files (Dir.to_string d) in List.rev_map of_string fs let copy ~src ~dst = if src <> dst then OpamSystem.copy (to_string src) (to_string dst) let move ~src ~dst = if src <> dst then OpamSystem.command [ "mv"; to_string src; to_string dst ] let link ~src ~dst = if src <> dst then OpamSystem.link (to_string src) (to_string dst) let readlink src = if exists src then try of_string (Unix.readlink (to_string src)) with _ -> src else OpamSystem.internal_error "%s does not exist." (to_string src) let is_symlink src = try let s = Unix.lstat (to_string src) in s.Unix.st_kind = Unix.S_LNK with _ -> OpamSystem.internal_error "%s does not exist." (to_string src) let starts_with dirname filename = OpamMisc.starts_with ~prefix:(Dir.to_string dirname) (to_string filename) let remove_prefix prefix filename = let prefix = let str = Dir.to_string prefix in if str = "" then "" else Filename.concat str "" in let filename = to_string filename in OpamMisc.remove_prefix ~prefix filename let process_in ?root fn src dst = let basename = match root with | None -> basename src | Some r -> if starts_with r src then remove_prefix r src else OpamSystem.internal_error "%s is not a prefix of %s" (Dir.to_string r) (to_string src) in let dst = Filename.concat (Dir.to_string dst) basename in fn ~src ~dst:(of_string dst) let copy_in ?root = process_in ?root copy let link_in = process_in link let extract filename dirname = OpamSystem.extract (to_string filename) (Dir.to_string dirname) let extract_in filename dirname = OpamSystem.extract_in (to_string filename) (Dir.to_string dirname) type generic_file = | D of Dir.t | F of t let extract_generic_file filename dirname = match filename with | F f -> log "extracting %s to %s" (to_string f) (Dir.to_string dirname); extract f dirname | D d -> if d <> dirname then ( log "copying %s to %s" (Dir.to_string d) (Dir.to_string dirname); copy_dir ~src:d ~dst:dirname ) let ends_with suffix filename = OpamMisc.ends_with ~suffix (to_string filename) let remove_suffix suffix filename = let suffix = Base.to_string suffix in let filename = to_string filename in OpamMisc.remove_suffix ~suffix filename let download ~overwrite filename dirname = mkdir dirname; let dst = to_string (create dirname (basename filename)) in let file = OpamSystem.download ~overwrite ~filename:(to_string filename) ~dst in of_string file let download_as ~overwrite filename dest = mkdir (dirname dest); let file = OpamSystem.download ~overwrite ~filename:(to_string filename) ~dst:(to_string dest) in assert (file = to_string dest); () let download_iter ~overwrite filenames dirname = let rec aux = function | [] -> let filenames = List.map to_string filenames in OpamSystem.internal_error "Cannot download %s." (OpamMisc.pretty_list filenames) | h::t -> try download ~overwrite h dirname with _ -> aux t in aux filenames let patch filename dirname = in_dir dirname (fun () -> OpamSystem.patch (to_string filename)) let with_flock file f x = OpamSystem.flock (to_string file); try let r = f x in OpamSystem.funlock (to_string file); r with e -> OpamSystem.funlock (to_string file); raise e let checksum f = if exists f then [digest f] else [] let checksum_dir d = if exists_dir d then List.map digest (rec_files d) else [] let prettify_dir d = OpamMisc.prettify_path (Dir.to_string d) let prettify s = OpamMisc.prettify_path (to_string s) let to_json x = `String (to_string x) module O = struct type tmp = t type t = tmp let compare x y = compare (to_string x) (to_string y) let to_string = to_string let to_json = to_json end module Map = OpamMisc.Map.Make(O) module Set = OpamMisc.Set.Make(O) let copy_files ~src ~dst = let files = rec_files src in List.iter (fun file -> if not !OpamGlobals.do_not_copy_files then let base = remove_prefix src file in let dst_file = create dst (Base.of_string base) in if exists dst_file then OpamGlobals.warning "%s is replaced by the packager's overlay files. \ Set OPAMDONOTCOPYFILES to a non-empty value to no \ copy the overlay files." (to_string dst_file); OpamGlobals.msg "Copying %s to %s/\n" (prettify file) (prettify_dir dst); copy ~src:file ~dst:dst_file ) files module OP = struct let (/) = (/) let (//) d1 s2 = let d = Filename.dirname s2 in let b = Filename.basename s2 in if d <> "." then create (d1 / d) (Base.of_string b) else create d1 (Base.of_string s2) end module Attribute = struct type t = { base: Base.t; md5 : string; perm: int option; } let base t = t.base let md5 t = t.md5 let perm t = t.perm let create base md5 perm = { base; md5; perm=Some perm } let to_string t = let perm = match t.perm with | None -> "" | Some p -> Printf.sprintf " 0o%o" p in Printf.sprintf "%s %s%s" (Base.to_string t.base) t.md5 perm let of_string s = match OpamMisc.split s ' ' with | [base; md5] -> { base=Base.of_string base; md5; perm=None } | [base;md5; perm] -> { base=Base.of_string base; md5; perm=Some (int_of_string perm) } | k -> OpamSystem.internal_error "remote_file: '%s' is not a valid line." (String.concat " " k) let to_json x = `O ([ ("base" , Base.to_json x.base); ("md5" , `String x.md5)] @ match x. perm with | None -> [] | Some p -> ["perm", `String (string_of_int p)]) module O = struct type tmp = t type t = tmp let to_string = to_string let compare = compare let to_json = to_json end module Set = OpamMisc.Set.Make(O) module Map = OpamMisc.Map.Make(O) end let to_attribute root file = let basename = Base.of_string (remove_prefix root file) in let perm = let s = Unix.stat (to_string file) in s.Unix.st_perm in let digest = digest file in Attribute.create basename digest perm opam-1.1.1/src/core/opamVersion.ml.in0000644000175000017500000000456012272210733015676 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) type t = string let to_string x = x let of_string x = x let to_json x = `String x let compare v w = (* Ignore -xxx suffixes for version comparisons *) let cut s = match OpamMisc.cut_at s '-' with | Some (s,_) -> s | None -> s in Debian.Version.compare (cut v) (cut w) module O = struct type t = string let to_string = to_string let to_json = to_json let compare = compare end module Set = OpamMisc.Set.Make(O) module Map = OpamMisc.Map.Make(O) let current_raw = "@PACKAGE_VERSION@" let current = of_string current_raw let message () = Printf.printf "\n\ %s version %s\n\ \n\ Copyright (C) 2012 OCamlPro - INRIA\n\ \n\ This is free software; see the source for copying conditions. There is NO\n\ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n" Sys.argv.(0) current_raw; exit 0 let git = match OpamGitVersion.version with | None -> None | Some v -> Some (of_string v) let full = let git_version = match git with | None -> "" | Some v -> Printf.sprintf " (%s)" (to_string v) in Printf.sprintf "%s%s" (to_string current) git_version let magic = let hash = Hashtbl.hash full in Printf.sprintf "%08X" (hash mod (Int32.to_int Int32.max_int)) opam-1.1.1/src/core/opamJson.ml0000644000175000017500000017237712272210733014571 0ustar i33173i33173module Uutf = struct (*--------------------------------------------------------------------------- Copyright (c) 2012 Daniel C. Bünzli. All rights reserved. Distributed under the BSD3 license, see license at the end of the file. uutf release 0.9.2 ---------------------------------------------------------------------------*) let io_buffer_size = 65536 (* IO_BUFFER_SIZE 4.0.0 *) let pp = Format.fprintf let invalid_encode () = invalid_arg "expected `Await encode" let invalid_bounds j l = invalid_arg (Printf.sprintf "invalid bounds (index %d, length %d)" j l) (* Unsafe string byte manipulations. If you don't believe the author's invariants, replacing with safe versions makes everything safe in the module. He won't be upset. *) let unsafe_chr = Char.unsafe_chr let unsafe_blit = String.unsafe_blit let unsafe_array_get = Array.unsafe_get let unsafe_byte s j = Char.code (String.unsafe_get s j) let unsafe_set_byte s j byte = String.unsafe_set s j (Char.unsafe_chr byte) (* Unicode characters *) type uchar = int let u_bom = 0xFEFF (* BOM. *) let u_rep = 0xFFFD (* replacement character. *) let is_uchar cp = (0x0000 <= cp && cp <= 0xD7FF) || (0xE000 <= cp && cp <= 0x10FFFF) let pp_cp ppf cp = if cp < 0 || cp > 0x10FFFF then pp ppf "U+Invalid(%X)" cp else if cp <= 0xFFFF then pp ppf "U+%04X" cp else pp ppf "U+%X" cp let cp_to_string cp = (* NOT thread safe. *) pp Format.str_formatter "%a" pp_cp cp; Format.flush_str_formatter () (* Unicode encoding schemes *) type encoding = [ `UTF_8 | `UTF_16 | `UTF_16BE | `UTF_16LE ] type decoder_encoding = [ encoding | `US_ASCII | `ISO_8859_1 ] let encoding_of_string s = match String.uppercase s with (* IANA names. *) | "UTF-8" -> Some `UTF_8 | "UTF-16" -> Some `UTF_16 | "UTF-16LE" -> Some `UTF_16LE | "UTF-16BE" -> Some `UTF_16BE | "ANSI_X3.4-1968" | "ISO-IR-6" | "ANSI_X3.4-1986" | "ISO_646.IRV:1991" | "ASCII" | "ISO646-US" | "US-ASCII" | "US" | "IBM367" | "CP367" | "CSASCII" -> Some `US_ASCII | "ISO_8859-1:1987" | "ISO-IR-100" | "ISO_8859-1" | "ISO-8859-1" | "LATIN1" | "L1" | "IBM819" | "CP819" | "CSISOLATIN1" -> Some `ISO_8859_1 | _ -> None let encoding_to_string = function | `UTF_8 -> "UTF-8" | `UTF_16 -> "UTF-16" | `UTF_16BE -> "UTF-16BE" | `UTF_16LE -> "UTF-16LE" | `US_ASCII -> "US-ASCII" | `ISO_8859_1 -> "ISO-8859-1" (* Base character decoders. They assume enough data. *) let malformed s j l = `Malformed (String.sub s j l) let malformed_pair be hi s j l = (* missing or half low surrogate at eoi. *) let bs1 = String.sub s j l in let bs0 = String.create 2 in let j0, j1 = if be then (0, 1) else (1, 0) in unsafe_set_byte bs0 j0 (hi lsr 8); unsafe_set_byte bs0 j1 (hi land 0xFF); `Malformed (bs0 ^ bs1) let r_us_ascii s j = (* assert (0 <= j && j < String.length s); *) let b0 = unsafe_byte s j in if b0 <= 127 then `Uchar b0 else malformed s j 1 let r_iso_8859_1 s j = (* assert (0 <= j && j < String.length s); *) `Uchar (unsafe_byte s j) let utf_8_len = [| (* uchar byte length according to first UTF-8 byte. *) 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 2; 2; 2; 2; 2; 2; 2; 2; 2; 2; 2; 2; 2; 2; 2; 2; 2; 2; 2; 2; 2; 2; 2; 2; 2; 2; 2; 2; 2; 2; 3; 3; 3; 3; 3; 3; 3; 3; 3; 3; 3; 3; 3; 3; 3; 3; 4; 4; 4; 4; 4; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0; 0 |] let r_utf_8 s j l = (* assert (0 <= j && 0 <= l && j + l <= String.length s); *) match l with | 1 -> `Uchar (unsafe_byte s j) | 2 -> let b0 = unsafe_byte s j in let b1 = unsafe_byte s (j + 1) in if b1 lsr 6 != 0b10 then malformed s j l else `Uchar (((b0 land 0x1F) lsl 6) lor (b1 land 0x3F)) | 3 -> let b0 = unsafe_byte s j in let b1 = unsafe_byte s (j + 1) in let b2 = unsafe_byte s (j + 2) in let c = `Uchar (((b0 land 0x0F) lsl 12) lor ((b1 land 0x3F) lsl 6) lor (b2 land 0x3F)) in if b2 lsr 6 != 0b10 then malformed s j l else begin match b0 with | 0xE0 -> if b1 < 0xA0 || 0xBF < b1 then malformed s j l else c | 0xED -> if b1 < 0x80 || 0x9F < b1 then malformed s j l else c | _ -> if b1 lsr 6 != 0b10 then malformed s j l else c end | 4 -> let b0 = unsafe_byte s j in let b1 = unsafe_byte s (j + 1) in let b2 = unsafe_byte s (j + 2) in let b3 = unsafe_byte s (j + 3) in let c = `Uchar (((b0 land 0x07) lsl 18) lor ((b1 land 0x3F) lsl 12) lor ((b2 land 0x3F) lsl 6) lor (b3 land 0x3F)) in if b3 lsr 6 != 0b10 || b2 lsr 6 != 0b10 then malformed s j l else begin match b0 with | 0xF0 -> if b1 < 0x90 || 0xBF < b1 then malformed s j l else c | 0xF4 -> if b1 < 0x80 || 0x8F < b1 then malformed s j l else c | _ -> if b1 lsr 6 != 0b10 then malformed s j l else c end | _ -> assert false let r_utf_16 s j0 j1 = (* May return a high surrogate. *) (* assert (0 <= j0 && 0 <= j1 && max j0 j1 < String.length s); *) let b0 = unsafe_byte s j0 in let b1 = unsafe_byte s j1 in let u = (b0 lsl 8) lor b1 in if u < 0xD800 || u > 0xDFFF then `Uchar u else if u > 0xDBFF then malformed s (min j0 j1) 2 else `Hi u let r_utf_16_lo hi s j0 j1 = (* Combines [hi] with a low surrogate. *) (* assert (0 <= j0 && 0 <= j1 && max j0 j1 < String.length s); *) let b0 = unsafe_byte s j0 in let b1 = unsafe_byte s j1 in let lo = (b0 lsl 8) lor b1 in if lo < 0xDC00 || lo > 0xDFFF then malformed_pair (j0 < j1 (* true => be *)) hi s (min j0 j1) 2 else `Uchar ((((hi land 0x3FF) lsl 10) lor (lo land 0x3FF)) + 0x10000) let r_encoding s j l = (* guess encoding with max. 3 bytes. *) (* assert (0 <= j && 0 <= l && j + l <= String.length s) *) let some i = if i < l then Some (unsafe_byte s (j + i)) else None in match (some 0), (some 1), (some 2) with | Some 0xEF, Some 0xBB, Some 0xBF -> `UTF_8 `BOM | Some 0xFE, Some 0xFF, _ -> `UTF_16BE `BOM | Some 0xFF, Some 0xFE, _ -> `UTF_16LE `BOM | Some 0x00, Some p, _ when p > 0 -> `UTF_16BE (`ASCII p) | Some p, Some 0x00, _ when p > 0 -> `UTF_16LE (`ASCII p) | Some u, _, _ when utf_8_len.(u) <> 0 -> `UTF_8 `Decode | Some _, Some _, _ -> `UTF_16BE `Decode | Some _, None , None -> `UTF_8 `Decode | None , None , None -> `UTF_8 `End | None , Some _, _ -> assert false | Some _, None , Some _ -> assert false | None , None , Some _ -> assert false (* Decode *) type src = [ `Channel of in_channel | `String of string | `Manual ] type nln = [ `ASCII of uchar | `NLF of uchar | `Readline of uchar ] type decode = [ `Await | `End | `Malformed of string | `Uchar of uchar] let pp_decode ppf = function | `Uchar u -> pp ppf "@[`Uchar %a@]" pp_cp u | `End -> pp ppf "`End" | `Await -> pp ppf "`Await" | `Malformed bs -> let l = String.length bs in pp ppf "@[`Malformed @[("; if l > 0 then pp ppf "%02X" (Char.code (bs.[0])); for i = 1 to l - 1 do pp ppf " %02X" (Char.code (bs.[i])) done; pp ppf ")@]@]" type decoder = { src : src; (* input source. *) mutable encoding : decoder_encoding; (* decoded encoding. *) nln : nln option; (* newline normalization (if any). *) nl : int; (* newline normalization character. *) mutable i : string; (* current input chunk. *) mutable i_pos : int; (* input current position. *) mutable i_max : int; (* input maximal position. *) t : string; (* four bytes temporary buffer for overlapping reads. *) mutable t_len : int; (* current byte length of [t]. *) mutable t_need : int; (* number of bytes needed in [t]. *) mutable removed_bom : bool; (* [true] if an initial BOM was removed. *) mutable last_cr : bool; (* [true] if last char was CR. *) mutable line : int; (* line number. *) mutable col : int; (* column number. *) mutable count : int; (* char count. *) mutable pp : (* decoder post-processor for BOM, position and nln. *) decoder -> [ `Malformed of string | `Uchar of uchar ] -> decode; mutable k : decoder -> decode } (* decoder continuation. *) (* On decodes that overlap two (or more) [d.i] buffers, we use [t_fill] to copy the input data to [d.t] and decode from there. If the [d.i] buffers are not too small this is faster than continuation based byte per byte writes. End of input (eoi) is signalled by [d.i_pos = 0] and [d.i_max = min_int] which implies that [i_rem d < 0] is [true]. *) let i_rem d = d.i_max - d.i_pos + 1 (* remaining bytes to read in [d.i]. *) let eoi d = d.i <- ""; d.i_pos <- 0; d.i_max <- min_int (* set eoi in [d]. *) let src d s j l = (* set [d.i] with [s]. *) if (j < 0 || l < 0 || j + l > String.length s) then invalid_bounds j l else if (l = 0) then eoi d else (d.i <- s; d.i_pos <- j; d.i_max <- j + l - 1) let refill k d = match d.src with (* get new input in [d.i] and [k]ontinue. *) | `Manual -> d.k <- k; `Await | `String _ -> eoi d; k d | `Channel ic -> let rc = input ic d.i 0 (String.length d.i) in (src d d.i 0 rc; k d) let t_need d need = d.t_len <- 0; d.t_need <- need let rec t_fill k d = (* get [d.t_need] bytes (or less if eoi) in [i.t]. *) let blit d l = unsafe_blit d.i d.i_pos d.t d.t_len (* write pos. *) l; d.i_pos <- d.i_pos + l; d.t_len <- d.t_len + l; in let rem = i_rem d in if rem < 0 (* eoi *) then k d else let need = d.t_need - d.t_len in if rem < need then (blit d rem; refill (t_fill k) d) else (blit d need; k d) let ret k v d = d.k <- k; d.pp d v (* return post-processed [v]. *) (* Decoders. *) let rec decode_us_ascii d = let rem = i_rem d in if rem <= 0 then (if rem < 0 then `End else refill decode_us_ascii d) else let j = d.i_pos in d.i_pos <- d.i_pos + 1; ret decode_us_ascii (r_us_ascii d.i j) d let rec decode_iso_8859_1 d = let rem = i_rem d in if rem <= 0 then (if rem < 0 then `End else refill decode_iso_8859_1 d) else let j = d.i_pos in d.i_pos <- d.i_pos + 1; ret decode_iso_8859_1 (r_iso_8859_1 d.i j) d (* UTF-8 decoder *) let rec t_decode_utf_8 d = (* decode from [d.t]. *) if d.t_len < d.t_need then ret decode_utf_8 (malformed d.t 0 d.t_len) d else ret decode_utf_8 (r_utf_8 d.t 0 d.t_len) d and decode_utf_8 d = let rem = i_rem d in if rem <= 0 then (if rem < 0 then `End else refill decode_utf_8 d) else let need = unsafe_array_get utf_8_len (unsafe_byte d.i d.i_pos) in if rem < need then (t_need d need; t_fill t_decode_utf_8 d) else let j = d.i_pos in if need = 0 then (d.i_pos <- d.i_pos + 1; ret decode_utf_8 (malformed d.i j 1) d) else (d.i_pos <- d.i_pos + need; ret decode_utf_8 (r_utf_8 d.i j need) d) (* UTF-16BE decoder *) let rec t_decode_utf_16be_lo hi d = (* decode from [d.t]. *) if d.t_len < d.t_need then ret decode_utf_16be (malformed_pair true hi d.t 0 d.t_len) d else ret decode_utf_16be (r_utf_16_lo hi d.t 0 1) d and t_decode_utf_16be d = (* decode from [d.t]. *) if d.t_len < d.t_need then ret decode_utf_16be (malformed d.t 0 d.t_len) d else decode_utf_16be_lo (r_utf_16 d.t 0 1) d and decode_utf_16be_lo v d = match v with | `Uchar _ | `Malformed _ as v -> ret decode_utf_16be v d | `Hi hi -> let rem = i_rem d in if rem < 2 then (t_need d 2; t_fill (t_decode_utf_16be_lo hi) d) else let j = d.i_pos in d.i_pos <- d.i_pos + 2; ret decode_utf_16be (r_utf_16_lo hi d.i j (j + 1)) d and decode_utf_16be d = let rem = i_rem d in if rem <= 0 then (if rem < 0 then `End else refill decode_utf_16be d) else if rem < 2 then (t_need d 2; t_fill t_decode_utf_16be d) else let j = d.i_pos in d.i_pos <- d.i_pos + 2; decode_utf_16be_lo (r_utf_16 d.i j (j + 1)) d (* UTF-16LE decoder, same as UTF-16BE with byte swapped. *) let rec t_decode_utf_16le_lo hi d = (* decode from [d.t]. *) if d.t_len < d.t_need then ret decode_utf_16le (malformed_pair false hi d.t 0 d.t_len) d else ret decode_utf_16le (r_utf_16_lo hi d.t 1 0) d and t_decode_utf_16le d = (* decode from [d.t]. *) if d.t_len < d.t_need then ret decode_utf_16le (malformed d.t 0 d.t_len) d else decode_utf_16le_lo (r_utf_16 d.t 1 0) d and decode_utf_16le_lo v d = match v with | `Uchar _ | `Malformed _ as v -> ret decode_utf_16le v d | `Hi hi -> let rem = i_rem d in if rem < 2 then (t_need d 2; t_fill (t_decode_utf_16le_lo hi) d) else let j = d.i_pos in d.i_pos <- d.i_pos + 2; ret decode_utf_16le (r_utf_16_lo hi d.i (j + 1) j) d and decode_utf_16le d = let rem = i_rem d in if rem <= 0 then (if rem < 0 then `End else refill decode_utf_16le d) else if rem < 2 then (t_need d 2; t_fill t_decode_utf_16le d) else let j = d.i_pos in d.i_pos <- d.i_pos + 2; decode_utf_16le_lo (r_utf_16 d.i (j + 1) j) d (* Encoding guessing. The guess is simple but starting the decoder after is tedious, uutf's decoders are not designed to put bytes back in the stream. *) let guessed_utf_8 d = (* start decoder after `UTF_8 guess. *) let b3 d = (* handles the third read byte. *) let b3 = unsafe_byte d.t 2 in match utf_8_len.(b3) with | 0 -> ret decode_utf_8 (malformed d.t 2 1) d | n -> d.t_need <- n; d.t_len <- 1; unsafe_set_byte d.t 0 b3; t_fill t_decode_utf_8 d in let b2 d = (* handle second read byte. *) let b2 = unsafe_byte d.t 1 in let b3 = if d.t_len > 2 then b3 else decode_utf_8 (* decodes `End *) in match utf_8_len.(b2) with | 0 -> ret b3 (malformed d.t 1 1) d | 1 -> ret b3 (r_utf_8 d.t 1 1) d | n -> (* copy d.t.(1-2) to d.t.(0-1) and decode *) d.t_need <- n; unsafe_set_byte d.t 0 b2; if (d.t_len < 3) then d.t_len <- 1 else (d.t_len <- 2; unsafe_set_byte d.t 1 (unsafe_byte d.t 2); ); t_fill t_decode_utf_8 d in let b1 = unsafe_byte d.t 0 in (* handle first read byte. *) let b2 = if d.t_len > 1 then b2 else decode_utf_8 (* decodes `End *) in match utf_8_len.(b1) with | 0 -> ret b2 (malformed d.t 0 1) d | 1 -> ret b2 (r_utf_8 d.t 0 1) d | 2 -> if d.t_len < 2 then ret decode_utf_8 (malformed d.t 0 1) d else if d.t_len < 3 then ret decode_utf_8 (r_utf_8 d.t 0 2) d else ret b2 (r_utf_8 d.t 0 2) d | 3 -> if d.t_len < 3 then ret decode_utf_8 (malformed d.t 0 d.t_len) d else ret decode_utf_8 (r_utf_8 d.t 0 3) d | 4 -> if d.t_len < 3 then ret decode_utf_8 (malformed d.t 0 d.t_len) d else (d.t_need <- 4; t_fill t_decode_utf_8 d) | _ -> assert false let guessed_utf_16 d be v = (* start decoder after `UTF_16{BE,LE} guess. *) let decode_utf_16, t_decode_utf_16, t_decode_utf_16_lo, j0, j1 = if be then decode_utf_16be, t_decode_utf_16be, t_decode_utf_16be_lo, 0, 1 else decode_utf_16le, t_decode_utf_16le, t_decode_utf_16le_lo, 1, 0 in let b3 k d = if d.t_len < 3 then decode_utf_16 d (* decodes `End *) else begin (* copy d.t.(2) to d.t.(0) and decode. *) d.t_need <- 2; d.t_len <- 1; unsafe_set_byte d.t 0 (unsafe_byte d.t 2); t_fill k d end in match v with | `BOM -> ret (b3 t_decode_utf_16) (`Uchar u_bom) d | `ASCII u -> ret (b3 t_decode_utf_16) (`Uchar u) d | `Decode -> match r_utf_16 d.t j0 j1 with | `Malformed _ | `Uchar _ as v -> ret (b3 t_decode_utf_16) v d | `Hi hi -> if d.t_len < 3 then ret decode_utf_16 (malformed_pair be hi "" 0 0) d else (b3 (t_decode_utf_16_lo hi)) d let guess_encoding d = (* guess encoding and start decoder. *) let setup d = match r_encoding d.t 0 d.t_len with | `UTF_8 r -> d.encoding <- `UTF_8; d.k <- decode_utf_8; begin match r with | `BOM -> ret decode_utf_8 (`Uchar u_bom) d | `Decode -> guessed_utf_8 d | `End -> `End end | `UTF_16BE r -> d.encoding <- `UTF_16BE; d.k <- decode_utf_16be; guessed_utf_16 d true r | `UTF_16LE r -> d.encoding <- `UTF_16LE; d.k <- decode_utf_16le; guessed_utf_16 d false r in (t_need d 3; t_fill setup d) (* Character post-processors. Used for BOM handling, newline normalization and position tracking. The [pp_remove_bom] is only used for the first character to remove a possible initial BOM and handle UTF-16 endianness recognition. *) let nline d = d.col <- 0; d.line <- d.line + 1 (* inlined. *) let ncol d = d.col <- d.col + 1 (* inlined. *) let ncount d = d.count <- d.count + 1 (* inlined. *) let cr d b = d.last_cr <- b (* inlined. *) let pp_remove_bom utf16 pp d = function(* removes init. BOM, handles UTF-16. *) | `Uchar 0xFEFF (* BOM *) -> if utf16 then (d.encoding <- `UTF_16BE; d.k <- decode_utf_16be); d.removed_bom <- true; d.pp <- pp; d.k d | `Uchar 0xFFFE (* BOM reversed from decode_utf_16be *) when utf16 -> d.encoding <- `UTF_16LE; d.k <- decode_utf_16le; d.removed_bom <- true; d.pp <- pp; d.k d | `Malformed _ | `Uchar _ as v -> d.removed_bom <- false; d.pp <- pp; d.pp d v let pp_nln_none d = function | `Uchar 0x000A (* LF *) as v -> let last_cr = d.last_cr in cr d false; ncount d; if last_cr then v else (nline d; v) | `Uchar 0x000D (* CR *) as v -> cr d true; ncount d; nline d; v | `Uchar (0x0085 | 0x000C | 0x2028 | 0x2029) (* NEL | FF | LS | PS *) as v -> cr d false; ncount d; nline d; v | `Uchar _ | `Malformed _ as v -> cr d false; ncount d; ncol d; v let pp_nln_readline d = function | `Uchar 0x000A (* LF *) -> let last_cr = d.last_cr in cr d false; if last_cr then d.k d else (ncount d; nline d; `Uchar d.nl) | `Uchar 0x000D (* CR *) -> cr d true; ncount d; nline d; `Uchar d.nl | `Uchar (0x0085 | 0x000C | 0x2028 | 0x2029) (* NEL | FF | LS | PS *) -> cr d false; ncount d; nline d; `Uchar d.nl | `Uchar _ | `Malformed _ as v -> cr d false; ncount d; ncol d; v let pp_nln_nlf d = function | `Uchar 0x000A (* LF *) -> let last_cr = d.last_cr in cr d false; if last_cr then d.k d else (ncount d; nline d; `Uchar d.nl) | `Uchar 0x000D (* CR *) -> cr d true; ncount d; nline d; `Uchar d.nl | `Uchar 0x0085 (* NEL *) -> cr d false; ncount d; nline d; `Uchar d.nl | `Uchar (0x000C | 0x2028 | 0x2029) as v (* FF | LS | PS *) -> cr d false; ncount d; nline d; v | `Uchar _ | `Malformed _ as v -> cr d false; ncount d; ncol d; v let pp_nln_ascii d = function | `Uchar 0x000A (* LF *) -> let last_cr = d.last_cr in cr d false; if last_cr then d.k d else (ncount d; nline d; `Uchar d.nl) | `Uchar 0x000D (* CR *) -> cr d true; ncount d; nline d; `Uchar d.nl | `Uchar (0x0085 | 0x000C | 0x2028 | 0x2029) as v (* NEL | FF | LS | PS *) -> cr d false; ncount d; nline d; v | `Uchar _ | `Malformed _ as v -> cr d false; ncount d; ncol d; v let decode_fun = function | `UTF_8 -> decode_utf_8 | `UTF_16 -> decode_utf_16be (* see [pp_remove_bom]. *) | `UTF_16BE -> decode_utf_16be | `UTF_16LE -> decode_utf_16le | `US_ASCII -> decode_us_ascii | `ISO_8859_1 -> decode_iso_8859_1 let decoder ?nln ?encoding src = let pp, nl = match nln with | None -> pp_nln_none, 0x000A (* not used. *) | Some (`ASCII nl) -> pp_nln_ascii, nl | Some (`NLF nl) -> pp_nln_nlf, nl | Some (`Readline nl) -> pp_nln_readline, nl in let encoding, k = match encoding with | None -> `UTF_8, guess_encoding | Some e -> (e :> decoder_encoding), decode_fun e in let i, i_pos, i_max = match src with | `Manual -> "", 1, 0 (* implies src_rem d = 0. *) | `Channel _ -> String.create io_buffer_size, 1, 0 (* idem. *) | `String s -> s, 0, String.length s - 1 in { src = (src :> src); encoding; nln = (nln :> nln option); nl; i; i_pos; i_max; t = String.create 4; t_len = 0; t_need = 0; removed_bom = false; last_cr = false; line = 1; col = 0; count = 0; pp = pp_remove_bom (encoding = `UTF_16) pp; k } let decode d = d.k d let decoder_line d = d.line let decoder_col d = d.col let decoder_count d = d.count let decoder_removed_bom d = d.removed_bom let decoder_src d = d.src let decoder_nln d = d.nln let decoder_encoding d = d.encoding let set_decoder_encoding d e = d.encoding <- (e :> decoder_encoding); d.k <- decode_fun e (* Encode *) type dst = [ `Channel of out_channel | `Buffer of Buffer.t | `Manual ] type encode = [ `Await | `End | `Uchar of uchar ] type encoder = { dst : dst; (* output destination. *) encoding : encoding; (* encoded encoding. *) mutable o : string; (* current output chunk. *) mutable o_pos : int; (* next output position to write. *) mutable o_max : int; (* maximal output position to write. *) t : string; (* four bytes buffer for overlapping writes. *) mutable t_pos : int; (* next position to read in [t]. *) mutable t_max : int; (* maximal position to read in [t]. *) mutable k : (* encoder continuation. *) encoder -> encode -> [ `Ok | `Partial ] } (* On encodes that overlap two (or more) [e.o] buffers, we encode the character to the temporary buffer [o.t] and continue with [tmp_flush] to write this data on the different [e.o] buffers. If the [e.o] buffers are not too small this is faster than continuation based byte per byte writes. *) let o_rem e = e.o_max - e.o_pos + 1 (* remaining bytes to write in [e.o]. *) let dst e s j l = (* set [e.o] with [s]. *) if (j < 0 || l < 0 || j + l > String.length s) then invalid_bounds j l; e.o <- s; e.o_pos <- j; e.o_max <- j + l - 1 let partial k e = function `Await -> k e | `Uchar _ | `End -> invalid_encode () let flush k e = match e.dst with(* get free storage in [d.o] and [k]ontinue. *) | `Manual -> e.k <- partial k; `Partial | `Buffer b -> Buffer.add_substring b e.o 0 e.o_pos; e.o_pos <- 0; k e | `Channel oc -> output oc e.o 0 e.o_pos; e.o_pos <- 0; k e let t_range e max = e.t_pos <- 0; e.t_max <- max let rec t_flush k e = (* flush [d.t] up to [d.t_max] in [d.i]. *) let blit e l = unsafe_blit e.t e.t_pos e.o e.o_pos l; e.o_pos <- e.o_pos + l; e.t_pos <- e.t_pos + l in let rem = o_rem e in let len = e.t_max - e.t_pos + 1 in if rem < len then (blit e rem; flush (t_flush k) e) else (blit e len; k e) (* Encoders. *) let rec encode_utf_8 e v = let k e = e.k <- encode_utf_8; `Ok in match v with | `Await -> k e | `End -> flush k e | `Uchar u as v -> let rem = o_rem e in if u <= 0x007F then if rem < 1 then flush (fun e -> encode_utf_8 e v) e else (unsafe_set_byte e.o e.o_pos u; e.o_pos <- e.o_pos + 1; k e) else if u <= 0x07FF then begin let s, j, k = if rem < 2 then (t_range e 1; e.t, 0, t_flush k) else let j = e.o_pos in (e.o_pos <- e.o_pos + 2; e.o, j, k) in unsafe_set_byte s j (0xC0 lor (u lsr 6)); unsafe_set_byte s (j + 1) (0x80 lor (u land 0x3F)); k e end else if u <= 0xFFFF then begin let s, j, k = if rem < 3 then (t_range e 2; e.t, 0, t_flush k) else let j = e.o_pos in (e.o_pos <- e.o_pos + 3; e.o, j, k) in unsafe_set_byte s j (0xE0 lor (u lsr 12)); unsafe_set_byte s (j + 1) (0x80 lor ((u lsr 6) land 0x3F)); unsafe_set_byte s (j + 2) (0x80 lor (u land 0x3F)); k e end else begin let s, j, k = if rem < 4 then (t_range e 3; e.t, 0, t_flush k) else let j = e.o_pos in (e.o_pos <- e.o_pos + 4; e.o, j, k) in unsafe_set_byte s j (0xF0 lor (u lsr 18)); unsafe_set_byte s (j + 1) (0x80 lor ((u lsr 12) land 0x3F)); unsafe_set_byte s (j + 2) (0x80 lor ((u lsr 6) land 0x3F)); unsafe_set_byte s (j + 3) (0x80 lor (u land 0x3F)); k e end let rec encode_utf_16be e v = let k e = e.k <- encode_utf_16be; `Ok in match v with | `Await -> k e | `End -> flush k e | `Uchar u -> let rem = o_rem e in if u < 0x10000 then begin let s, j, k = if rem < 2 then (t_range e 1; e.t, 0, t_flush k) else let j = e.o_pos in (e.o_pos <- e.o_pos + 2; e.o, j, k) in unsafe_set_byte s j (u lsr 8); unsafe_set_byte s (j + 1) (u land 0xFF); k e end else begin let s, j, k = if rem < 4 then (t_range e 3; e.t, 0, t_flush k) else let j = e.o_pos in (e.o_pos <- e.o_pos + 4; e.o, j, k) in let u' = u - 0x10000 in let hi = (0xD800 lor (u' lsr 10)) in let lo = (0xDC00 lor (u' land 0x3FF)) in unsafe_set_byte s j (hi lsr 8); unsafe_set_byte s (j + 1) (hi land 0xFF); unsafe_set_byte s (j + 2) (lo lsr 8); unsafe_set_byte s (j + 3) (lo land 0xFF); k e end let rec encode_utf_16le e v = (* encode_uft_16be with bytes swapped. *) let k e = e.k <- encode_utf_16le; `Ok in match v with | `Await -> k e | `End -> flush k e | `Uchar u -> let rem = o_rem e in if u < 0x10000 then begin let s, j, k = if rem < 2 then (t_range e 1; e.t, 0, t_flush k) else let j = e.o_pos in (e.o_pos <- e.o_pos + 2; e.o, j, k) in unsafe_set_byte s j (u land 0xFF); unsafe_set_byte s (j + 1) (u lsr 8); k e end else begin let s, j, k = if rem < 4 then (t_range e 3; e.t, 0, t_flush k) else let j = e.o_pos in (e.o_pos <- e.o_pos + 4; e.o, j, k) in let u' = u - 0x10000 in let hi = (0xD800 lor (u' lsr 10)) in let lo = (0xDC00 lor (u' land 0x3FF)) in unsafe_set_byte s j (hi land 0xFF); unsafe_set_byte s (j + 1) (hi lsr 8); unsafe_set_byte s (j + 2) (lo land 0xFF); unsafe_set_byte s (j + 3) (lo lsr 8); k e end let encode_fun = function | `UTF_8 -> encode_utf_8 | `UTF_16 -> encode_utf_16be | `UTF_16BE -> encode_utf_16be | `UTF_16LE -> encode_utf_16le let encoder encoding dst = let o, o_pos, o_max = match dst with | `Manual -> "", 1, 0 (* implies o_rem e = 0. *) | `Buffer _ | `Channel _ -> String.create io_buffer_size, 0, io_buffer_size - 1 in { dst = (dst :> dst); encoding = (encoding :> encoding); o; o_pos; o_max; t = String.create 4; t_pos = 1; t_max = 0; k = encode_fun encoding} let encode e v = e.k e (v :> encode) let encoder_encoding e = e.encoding let encoder_dst e = e.dst (* Manual sources and destinations. *) module Manual = struct let src = src let dst = dst let dst_rem = o_rem end (* Strings folders and Buffer encoders *) module String = struct let encoding_guess s = match r_encoding s 0 (max (String.length s) 3) with | `UTF_8 d -> `UTF_8, (d = `BOM) | `UTF_16BE d -> `UTF_16BE, (d = `BOM) | `UTF_16LE d -> `UTF_16LE, (d = `BOM) let fold_utf_8 f acc s = let rec loop acc f s i l = if i = l then acc else let need = unsafe_array_get utf_8_len (unsafe_byte s i) in if need = 0 then loop (f acc i (malformed s i 1)) f s (i + 1) l else let rem = l - i in if rem < need then f acc i (malformed s i rem) else loop (f acc i (r_utf_8 s i need)) f s (i + need) l in loop acc f s 0 (String.length s) let fold_utf_16be f acc s = let rec loop acc f s i l = if i = l then acc else let rem = l - i in if rem < 2 then f acc i (malformed s i 1) else match r_utf_16 s i (i + 1) with | `Uchar _ | `Malformed _ as v -> loop (f acc i v) f s (i + 2) l | `Hi hi -> if rem < 4 then f acc i (malformed s i rem) else loop (f acc i (r_utf_16_lo hi s (i + 2) (i + 3))) f s (i + 4) l in loop acc f s 0 (String.length s) let fold_utf_16le f acc s = (* [fold_utf_16be], bytes swapped. *) let rec loop acc f s i l = if i = l then acc else let rem = l - i in if rem < 2 then f acc i (malformed s i 1) else match r_utf_16 s (i + 1) i with | `Uchar _ | `Malformed _ as v -> loop (f acc i v) f s (i + 2) l | `Hi hi -> if rem < 4 then f acc i (malformed s i rem) else loop (f acc i (r_utf_16_lo hi s (i + 3) (i + 2))) f s (i + 4) l in loop acc f s 0 (String.length s) end module Buffer = struct let add_utf_8 b u = let w byte = Buffer.add_char b (unsafe_chr byte) in (* inlined. *) if u <= 0x007F then (w u) else if u <= 0x07FF then (w (0xC0 lor (u lsr 6)); w (0x80 lor (u land 0x3F))) else if u <= 0xFFFF then (w (0xE0 lor (u lsr 12)); w (0x80 lor ((u lsr 6) land 0x3F)); w (0x80 lor (u land 0x3F))) else (w (0xF0 lor (u lsr 18)); w (0x80 lor ((u lsr 12) land 0x3F)); w (0x80 lor ((u lsr 6) land 0x3F)); w (0x80 lor (u land 0x3F))) let add_utf_16be b u = let w byte = Buffer.add_char b (unsafe_chr byte) in (* inlined. *) if u < 0x10000 then (w (u lsr 8); w (u land 0xFF)) else let u' = u - 0x10000 in let hi = (0xD800 lor (u' lsr 10)) in let lo = (0xDC00 lor (u' land 0x3FF)) in w (hi lsr 8); w (hi land 0xFF); w (lo lsr 8); w (lo land 0xFF) let add_utf_16le b u = (* swapped add_utf_16be. *) let w byte = Buffer.add_char b (unsafe_chr byte) in (* inlined. *) if u < 0x10000 then (w (u land 0xFF); w (u lsr 8)) else let u' = u - 0x10000 in let hi = (0xD800 lor (u' lsr 10)) in let lo = (0xDC00 lor (u' land 0x3FF)) in w (hi land 0xFF); w (hi lsr 8); w (lo land 0xFF); w (lo lsr 8) end (*--------------------------------------------------------------------------- Copyright (c) 2012 Daniel C. Bünzli All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of Daniel C. Bünzli nor the names of contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ---------------------------------------------------------------------------*) end (*--------------------------------------------------------------------------- Copyright (c) 2012 Daniel C. Bünzli. All rights reserved. Distributed under the BSD3 license, see license at the end of the file. jsonm release 0.9.1 ---------------------------------------------------------------------------*) (* Braced non-terminals in comments refer to RFC 4627 non-terminals. *) let io_buffer_size = 65536 (* IO_BUFFER_SIZE 4.0.0 *) let pp = Format.fprintf (* Unsafe string byte manipulations. If you don't believe the authors's invariants, replacing with safe versions makes everything safe in the module. He won't be upset. *) let unsafe_blit = String.unsafe_blit let unsafe_set_byte s j byte = String.unsafe_set s j (Char.unsafe_chr byte) let unsafe_byte s j = Char.code (String.unsafe_get s j) (* Characters and their classes *) let ux_eoi = max_int (* End of input, outside unicode range. *) let ux_soi = max_int - 1 (* Start of input, outside unicode range. *) let u_nl = 0x0A (* \n *) let u_sp = 0x20 (* *) let u_quot = 0x22 (* '' *) let u_lbrack = 0x5B (* [ *) let u_rbrack = 0x5D (* ] *) let u_lbrace = 0x7B (* { *) let u_rbrace = 0x7D (* } *) let u_colon = 0x3A (* : *) let u_dot = 0x2E (* . *) let u_comma = 0x2C (* , *) let u_minus = 0x2D (* - *) let u_slash = 0x2F (* / *) let u_bslash = 0x5C (* \ *) let u_times = 0x2A (* * *) let must_escape u = u <= 0x1F || u = 0x22 || u = 0x5C let is_digit u = 0x30 <= u && u <= 0x39 let is_hex_digit u = 0x30 <= u && u <= 0x39 || 0x41 <= u && u <= 0x46 || 0x61 <= u && u <= 0x66 let is_white = function (* N.B. Uutf normalizes U+000D to U+000A. *) | 0x20 | 0x09 | 0x0A -> true | _ -> false let is_val_sep = function (* N.B. Uutf normalizes U+000D to U+000A. *) | 0x20 | 0x09 | 0x0A | 0x2C | 0x5D | 0x7D -> true | _ -> false (* Data model *) type lexeme = [ | `Null | `Bool of bool | `String of string | `Float of float | `Name of string | `As | `Ae | `Os | `Oe ] let pp_lexeme ppf = function | `Null -> pp ppf "`Null" | `Bool b -> pp ppf "@[`Bool %b@]" b | `String s -> pp ppf "@[`String %S@]" s | `Name s -> pp ppf "@[`Name %S@]" s | `Float f -> pp ppf "@[`Float %s@]" (string_of_float f) | `As -> pp ppf "`As" | `Ae -> pp ppf "`Ae" | `Os -> pp ppf "`Os" | `Oe -> pp ppf "`Oe" (* Decode *) type error = [ | `Illegal_BOM | `Illegal_escape of [ `Not_hex_uchar of int | `Not_esc_uchar of int | `Not_lo_surrogate of int | `Lone_lo_surrogate of int | `Lone_hi_surrogate of int ] | `Illegal_string_uchar of int | `Illegal_bytes of string | `Illegal_literal of string | `Illegal_number of string | `Unclosed of [ `As | `Os | `String | `Comment ] | `Expected of [ `Comment | `Value | `Name | `Name_sep | `Json | `Eoi | `Aval of bool (* [true] if first array value *) | `Omem of bool (* [true] if first object member *) ]] let err_bom = `Error (`Illegal_BOM) let err_not_hex u = `Error (`Illegal_escape (`Not_hex_uchar u)) let err_not_esc u = `Error (`Illegal_escape (`Not_esc_uchar u)) let err_not_lo p = `Error (`Illegal_escape (`Not_lo_surrogate p)) let err_lone_lo p = `Error (`Illegal_escape (`Lone_lo_surrogate p)) let err_lone_hi p = `Error (`Illegal_escape (`Lone_hi_surrogate p)) let err_str_char u = `Error (`Illegal_string_uchar u) let err_bytes bs = `Error (`Illegal_bytes bs) let err_unclosed_comment = `Error (`Unclosed `Comment) let err_unclosed_string = `Error (`Unclosed `String) let err_unclosed_arr = `Error (`Unclosed `As) let err_unclosed_obj = `Error (`Unclosed `Os) let err_number s = `Error (`Illegal_number s) let err_literal s = `Error (`Illegal_literal s) let err_exp_comment = `Error (`Expected `Comment) let err_exp_value = `Error (`Expected `Value) let err_exp_name = `Error (`Expected `Name) let err_exp_nsep = `Error (`Expected `Name_sep) let err_exp_arr_fst = `Error (`Expected (`Aval true)) let err_exp_arr_nxt = `Error (`Expected (`Aval false)) let err_exp_obj_fst = `Error (`Expected (`Omem true)) let err_exp_obj_nxt = `Error (`Expected (`Omem false)) let err_exp_json = `Error (`Expected `Json) let err_exp_eoi = `Error (`Expected `Eoi) let pp_uchar ppf u = if u <= 0x1F (* most control chars *) then Uutf.pp_cp ppf u else let b = Buffer.create 4 in Uutf.Buffer.add_utf_8 b u; pp ppf "'%s' (%a)" (Buffer.contents b) Uutf.pp_cp u let pp_error ppf = function | `Illegal_BOM -> pp ppf "@[illegal@ initial@ BOM@ in@ character@ stream@]" | `Illegal_escape r -> pp ppf "@[illegal@ escape,@ "; begin match r with | `Not_hex_uchar u -> pp ppf "%a@ not@ a@ hex@ digit@]" pp_uchar u | `Not_esc_uchar u -> pp ppf "%a@ not@ an@ escaped@ character@]" pp_uchar u | `Lone_lo_surrogate p -> pp ppf "%a@ lone@ low@ surrogate@]" Uutf.pp_cp p | `Lone_hi_surrogate p -> pp ppf "%a@ lone@ high@ surrogate@]" Uutf.pp_cp p | `Not_lo_surrogate p -> pp ppf "%a@ not@ a@ low@ surrogate@]" Uutf.pp_cp p end | `Illegal_string_uchar u -> pp ppf "@[illegal@ character@ in@ JSON@ string@ (%a)@]" pp_uchar u | `Illegal_bytes bs -> let l = String.length bs in pp ppf "@[illegal@ bytes@ in@ character@ stream@ ("; if l > 0 then pp ppf "%02X" (Char.code (bs.[0])); for i = 1 to l - 1 do pp ppf " %02X" (Char.code (bs.[i])) done; pp ppf ")@]" | `Illegal_number n -> pp ppf "@[illegal@ number@ (%s)@]" n | `Illegal_literal l -> pp ppf "@[illegal@ literal@ (%s)@]" l | `Unclosed r -> pp ppf "@[unclosed@ "; begin match r with | `As -> pp ppf "array@]"; | `Os -> pp ppf "object@]"; | `String -> pp ppf "string@]"; | `Comment -> pp ppf "comment@]" end | `Expected r -> pp ppf "@[expected@ "; begin match r with | `Comment -> pp ppf "JavaScript@ comment@]" | `Value -> pp ppf "JSON@ value@]" | `Name -> pp ppf "member@ name@]" | `Name_sep -> pp ppf "name@ separator@ (':')@]" | `Aval true -> pp ppf "value@ or@ array@ end@ (value@ or@ ']')@]" | `Aval false -> pp ppf "value@ separator@ or@ array@ end@ (','@ or@ ']')@]" | `Omem true -> pp ppf "member@ name@ or@ object@ end@ ('\"'@ or@ '}')@]" | `Omem false ->pp ppf "value@ separator@ or@ object@ end@ (','@ or@ '}')@]" | `Json -> pp ppf "JSON@ text@ ('{'@ or@ '[')@]" | `Eoi -> pp ppf "end@ of@ input@]" end type pos = int * int type encoding = [ `UTF_8 | `UTF_16 | `UTF_16BE | `UTF_16LE ] type src = [ `Channel of in_channel | `String of string | `Manual ] type decode = [ `Await | `End | `Lexeme of lexeme | `Error of error ] type uncut = [ `Comment of [ `M | `S ] * string | `White of string ] let pp_decode ppf = function | `Lexeme l -> pp ppf "@[`Lexeme @[(%a)@]@]" pp_lexeme l | `Await -> pp ppf "`Await" | `End -> pp ppf "`End" | `Error e -> pp ppf "@[`Error @[(%a)@]@]" pp_error e | `White s -> pp ppf "@[`White @[%S@]@]" s | `Comment (style, s) -> let pr_style ppf = function `M -> pp ppf "`M" | `S -> pp ppf "`S" in pp ppf "@[`Comment @[(%a, %S)@]@]" pr_style style s type decoder = { u : Uutf.decoder; (* Unicode character decoder. *) buf : Buffer.t; (* string accumulation buffer. *) mutable uncut : bool; (* [true] to bufferize comments and white space. *) mutable s_line : int; (* last saved start line. *) mutable s_col : int; (* last saved start column. *) mutable e_line : int; (* last saved end line. *) mutable e_col : int; (* last saved end column. *) mutable c : Uutf.uchar; (* character lookahead. *) mutable stack : (* stack of open arrays and objects. *) [ `As of pos | `Os of pos ] list; mutable next_name : bool; (* [true] if next decode should be [`Name]. *) mutable last_start : bool; (* [true] if last lexeme was `As or `Os. *) mutable k : (* decoder continuation. *) decoder -> [ decode | uncut ] } let baddc d c = Uutf.Buffer.add_utf_8 d.buf c let badd d = Uutf.Buffer.add_utf_8 d.buf d.c let buf d = let t = Buffer.contents d.buf in (Buffer.clear d.buf; t) let dpos d = Uutf.decoder_line d.u, Uutf.decoder_col d.u let spos d = d.s_line <- Uutf.decoder_line d.u; d.s_col <- Uutf.decoder_col d.u let epos d = d.e_line <- Uutf.decoder_line d.u; d.e_col <- Uutf.decoder_col d.u let stack_range d = match d.stack with [] -> assert false | `As (l,c) :: _ | `Os (l,c) :: _ -> d.s_line <- l; d.s_col <- c; epos d let dpop d = match (spos d; epos d; d.stack) with | _ :: (`Os _ :: _ as ss) -> d.next_name <- true; d.stack <- ss | _ :: (`As _ :: _ as ss) -> d.next_name <- false; d.stack <- ss | _ :: [] -> d.next_name <- false; d.stack <- [] | [] -> assert false let ret_eoi _ = `End let ret (v : [< decode | uncut]) k d = d.k <- k; v let rec readc k d = match Uutf.decode d.u with | `Uchar u -> d.c <- u; k d | `End -> d.c <- ux_eoi; k d | `Await -> ret `Await (readc k) d | `Malformed bs -> d.c <- Uutf.u_rep; epos d; ret (err_bytes bs) k d let rec r_scomment k d = (* single line comment. // was eaten. *) if (d.c <> u_nl && d.c <> ux_eoi) then (badd d; readc (r_scomment k) d) else (epos d; ret (`Comment (`S, buf d)) (readc k) d) let rec r_mcomment closing k d = (* multiline comment. /* was eaten. *) if (d.c = ux_eoi) then (epos d; ret err_unclosed_comment ret_eoi d) else if closing then begin if (d.c = u_slash) then (epos d; ret (`Comment (`M, buf d)) (readc k) d)else if (d.c = u_times) then (badd d; readc (r_mcomment true k) d) else (baddc d u_times; badd d; readc (r_mcomment false k) d) end else begin if (d.c = u_times) then readc (r_mcomment true k) d else (badd d; readc (r_mcomment false k) d) end let r_comment k d = (* comment, / was eaten. *) if d.c = u_slash then readc (r_scomment k) d else if d.c = u_times then readc (r_mcomment false k) d else (epos d; ret err_exp_comment k d) let rec r_ws_uncut k d = if (is_white d.c) then (epos d; badd d; readc (r_ws_uncut k) d) else ret (`White (buf d)) k d let rec r_white_uncut k d = (* {ws} / comment *) if (is_white d.c) then (spos d; r_ws_uncut (r_white_uncut k) d) else if (d.c = u_slash) then (spos d; readc (r_comment (r_white_uncut k)) d) else k d let rec r_ws k d = if (is_white d.c) then readc (r_ws k) d else k d (* {ws} *) let r_white k d = if d.uncut then r_white_uncut k d else r_ws k d let rec r_u_escape hi u count k d = (* unicode escapes. *) let error err k d = baddc d Uutf.u_rep; ret err k d in if count > 0 then if not (is_hex_digit d.c) then (epos d; error (err_not_hex d.c) (readc k) d) else let u = u * 16 + (if d.c <= 0x39 (* 9 *) then d.c - 0x30 else if d.c <= 0x46 (* F *) then d.c - 0x37 else d.c - 0x57) in (epos d; readc (r_u_escape hi u (count - 1) k) d) else match hi with | Some hi -> (* combine high and low surrogate into scalar value. *) if u < 0xDC00 || u > 0xDFFF then error (err_not_lo u) k d else let u = ((((hi land 0x3FF) lsl 10) lor (u land 0x3FF)) + 0x10000) in (baddc d u; k d) | None -> if u < 0xD800 || u > 0xDFFF then (baddc d u; k d) else if u > 0xDBFF then error (err_lone_lo u) k d else if d.c <> u_bslash then error (err_lone_hi u) k d else readc (fun d -> if d.c <> 0x75 (* u *) then error (err_lone_hi u) (r_escape k) d else readc (r_u_escape (Some u) 0 4 k) d) d and r_escape k d = match d.c with | 0x22 (* '' *)-> baddc d u_quot; readc k d | 0x5C (* \ *) -> baddc d u_bslash; readc k d | 0x2F (* / *) -> baddc d u_slash; readc k d | 0x62 (* b *) -> baddc d 0x08; readc k d | 0x66 (* f *) -> baddc d 0x0C; readc k d | 0x6E (* n *) -> baddc d u_nl; readc k d | 0x72 (* r *) -> baddc d 0x0D; readc k d | 0x74 (* t *) -> baddc d 0x09; readc k d | 0x75 (* u *) -> readc (r_u_escape None 0 4 k) d | c -> epos d; baddc d Uutf.u_rep; ret (err_not_esc c) (readc k) d let rec r_string k d = (* {string}, '' eaten. *) if d.c = ux_eoi then (epos d; ret err_unclosed_string ret_eoi d) else if not (must_escape d.c) then (badd d; readc (r_string k) d) else if d.c = u_quot then (epos d; readc k d) else if d.c = u_bslash then readc (r_escape (r_string k)) d else (epos d; baddc d Uutf.u_rep; ret (err_str_char d.c) (readc (r_string k)) d) let rec r_float k d = (* {number} *) if not (is_val_sep d.c) && d.c <> ux_eoi then (epos d; badd d; readc (r_float k) d) else let s = buf d in try ret (`Lexeme (`Float (float_of_string s))) k d with | Failure _ -> ret (err_number s) k d let rec r_literal k d = (* {true} / {false} / {null} *) if not (is_val_sep d.c) && d.c <> ux_eoi then (epos d; badd d; readc (r_literal k) d) else match buf d with | "true" -> ret (`Lexeme (`Bool true)) k d | "false" -> ret (`Lexeme (`Bool false)) k d | "null" -> ret (`Lexeme `Null) k d | s -> ret (err_literal s) k d let r_value err k d = match d.c with (* {value} *) | 0x5B (* [ *) -> (* {begin-array} *) spos d; epos d; d.last_start <- true; d.stack <- `As (dpos d) :: d.stack; ret (`Lexeme `As) (readc k) d | 0x7B (* { *) -> (* {begin-object} *) spos d; epos d; d.last_start <- true; d.next_name <- true; d.stack <- `Os (dpos d) :: d.stack; ret (`Lexeme `Os) (readc k) d | 0x22 (* '' *) -> let lstring k d = ret (`Lexeme (`String (buf d))) k d in spos d; readc (r_string (lstring k)) d | 0x66 (* f *) | 0x6E (* n *) | 0x74 (* t *) -> spos d; r_literal k d | u when is_digit u || u = u_minus -> spos d; r_float k d | _ -> err k d let rec discard_to c1 c2 err k d = if d.c = c1 || d.c = c2 || d.c = ux_eoi then ret err k d else (epos d; readc (discard_to c1 c2 err k) d) let r_arr_val k d = (* [{value-separator}] {value} / {end-array} *) let nxval err k d = spos d; discard_to u_comma u_rbrack err k d in let last_start = d.last_start in d.last_start <- false; if d.c = ux_eoi then (stack_range d; ret err_unclosed_arr ret_eoi d) else if d.c = u_rbrack then (dpop d; ret (`Lexeme `Ae) (readc k) d) else if last_start then r_value (nxval err_exp_arr_fst) k d else if d.c = u_comma then readc (r_white (r_value (nxval err_exp_value) k)) d else nxval err_exp_arr_nxt k d let nxmem err k d = spos d; d.next_name <- true; discard_to u_comma u_rbrace err k d let r_obj_value k d = (* {name-separator} {value} *) d.next_name <- true; if d.c = u_colon then readc (r_white (r_value (nxmem err_exp_value) k)) d else nxmem err_exp_nsep k d let r_obj_name k d = (* [{value-separator}] string / end-object *) let r_name err k d = let ln k d = ret (`Lexeme (`Name (buf d))) k d in if d.c <> u_quot then nxmem err k d else (spos d; readc (r_string (ln k)) d) in let last_start = d.last_start in d.last_start <- false; d.next_name <- false; if d.c = ux_eoi then (stack_range d; ret err_unclosed_obj ret_eoi d) else if d.c = u_rbrace then (dpop d; ret (`Lexeme `Oe) (readc k) d) else if last_start then r_name err_exp_obj_fst k d else if d.c = u_comma then readc (r_white (r_name err_exp_name k)) d else nxmem err_exp_obj_nxt k d let r_end _ d = (* end of input *) if d.c = ux_eoi then ret `End ret_eoi d else let drain k d = spos d; discard_to ux_eoi ux_eoi err_exp_eoi k d in drain ret_eoi d let rec r_lexeme d = match d.stack with | `As _ :: _ -> r_white (r_arr_val r_lexeme) d | `Os _ :: _ -> if d.next_name then r_white (r_obj_name r_lexeme) d else r_white (r_obj_value r_lexeme) d | [] -> r_white (r_end r_lexeme) d let rec r_json k d = (* {begin-array} / {begin-object} *) let err k d = spos d; discard_to u_lbrack u_lbrace err_exp_json (r_json k)d in if d.c = u_lbrack || d.c = u_lbrace then r_value err k d else err k d let r_start d = (* start of input *) let bom k d = if Uutf.decoder_removed_bom d.u then ret err_bom k d else k d in readc (bom (r_white (r_json r_lexeme))) d let decoder ?encoding src = let u = Uutf.decoder ?encoding ~nln:(`ASCII 0x000A) src in { u; buf = Buffer.create 1024; uncut = false; s_line = 1; s_col = 0; e_line = 1; e_col = 0; c = ux_soi; next_name = false; last_start = false; stack = []; k = r_start } let decode_uncut d = d.uncut <- true; d.k d let decode d = match (d.uncut <- false; d.k d) with | #decode as v -> (v :> [> decode]) | `Comment _ | `White _ -> assert false let decoder_src d = Uutf.decoder_src d.u let decoded_range d = (d.s_line, d.s_col), (d.e_line, d.e_col) let decoder_encoding d = match Uutf.decoder_encoding d.u with | #encoding as enc -> enc | `US_ASCII | `ISO_8859_1 -> assert false (* Encode *) let invalid_arg fmt = let b = Buffer.create 20 in (* for thread safety. *) let ppf = Format.formatter_of_buffer b in let k ppf = Format.pp_print_flush ppf (); invalid_arg (Buffer.contents b) in Format.kfprintf k ppf fmt let invalid_bounds j l = invalid_arg "invalid bounds (index %d, length %d)" j l let expect e v = invalid_arg "%a encoded but expected %s" pp_decode v e let expect_await v = expect "`Await" v let expect_end l = expect "`End" (`Lexeme l) let expect_mem_value l = expect "any `Lexeme but `Name, `Oe or `Ae" (`Lexeme l) let expect_arr_value_ae l = expect "any `Lexeme but `Name or `Oe" (`Lexeme l) let expect_name_or_oe l = expect "`Lexeme (`Name _ | `Oe)" (`Lexeme l) let expect_json v = expect "`Lexeme (`As | `Os)" v let expect_lend lstart v = expect (if lstart = `As then "`Lexeme `Ae" else "`Lexeme `Oe") v type dst = [ `Channel of out_channel | `Buffer of Buffer.t | `Manual ] type encode = [ `Await | `End | `Lexeme of lexeme ] type encoder = { dst : dst; (* output destination. *) minify : bool; (* [true] for compact output. *) mutable o : string; (* current output chunk. *) mutable o_pos : int; (* next output position to write. *) mutable o_max : int; (* maximal output position to write. *) buf : Buffer.t; (* buffer to format floats. *) mutable stack : [`As | `Os ] list; (* stack of open arrays and objects. *) mutable nest : int; (* nesting level (String.length stack). *) mutable next_name : bool; (* [true] if next encode should `Name. *) mutable last_start : bool; (* [true] if last encode was [`As | `Os]. *) mutable k : (* decoder continuation. *) encoder -> [ encode | uncut ] -> [ `Ok | `Partial ] } let o_rem e = e.o_max - e.o_pos + 1 (* remaining bytes to write in [e.o]. *) let dst e s j l = (* set [e.o] with [s]. *) if (j < 0 || l < 0 || j + l > String.length s) then invalid_bounds j l; e.o <- s; e.o_pos <- j; e.o_max <- j + l - 1 let partial k e = function `Await -> k e | v -> expect_await v let flush k e = match e.dst with (* get free space in [d.o] and [k]ontinue. *) | `Manual -> e.k <- partial k; `Partial | `Buffer b -> Buffer.add_substring b e.o 0 e.o_pos; e.o_pos <- 0; k e | `Channel oc -> output oc e.o 0 e.o_pos; e.o_pos <- 0; k e let rec writeb b k e = (* write byte [b] and [k]ontinue. *) if e.o_pos > e.o_max then flush (writeb b k) e else (unsafe_set_byte e.o e.o_pos b; e.o_pos <- e.o_pos + 1; k e) let rec writes s j l k e = (* write [l] bytes from [s] starting at [j]. *) let rem = o_rem e in if rem >= l then (unsafe_blit s j e.o e.o_pos l; e.o_pos <- e.o_pos + l; k e) else begin unsafe_blit s j e.o e.o_pos rem; e.o_pos <- e.o_pos + rem; flush (writes s (j + rem) (l - rem) k) e end let rec writebuf j l k e = (* write [l] bytes from [e.buf] starting at [j]. *) let rem = o_rem e in if rem >= l then (Buffer.blit e.buf j e.o e.o_pos l; e.o_pos <- e.o_pos + l; k e) else begin Buffer.blit e.buf j e.o e.o_pos rem; e.o_pos <- e.o_pos + rem; flush (writebuf (j + rem) (l - rem) k) e end let w_indent k e = let rec loop indent k e = let spaces e indent = let max = e.o_pos + indent - 1 in for j = e.o_pos to max do unsafe_set_byte e.o j u_sp done; e.o_pos <- max + 1 in let rem = o_rem e in if rem < indent then (spaces e rem; flush (loop (indent - rem) k) e) else (spaces e indent; k e) in loop (e.nest * 2) k e let w_json_string s k e = (* escapes as mandated by the standard. *) let rec loop s j pos max k e = if pos > max then (if j > max then k e else writes s j (pos - j) k e) else let next = pos + 1 in let escape esc = (* assert (String.length esc = 2 ). *) writes s j (pos - j) (writes esc 0 2 (loop s next next max k)) e in match unsafe_byte s pos with | 0x22 -> escape "\\\"" | 0x5C -> escape "\\\\" | 0x0A -> escape "\\n" | c when c <= 0x1F -> let hex d = (if d < 10 then 0x30 + d else 0x41 + (d - 10)) in writes s j (pos - j) (writes "\\u00" 0 4 (writeb (hex (c lsr 4)) (writeb (hex (c land 0xF)) (loop s next next max k)))) e | _ -> loop s j next max k e in writeb u_quot (loop s 0 0 (String.length s - 1) (writeb u_quot k)) e let w_name n k e = e.last_start <- false; e.next_name <- false; w_json_string n (writeb u_colon k) e let w_value ~in_obj l k e = match l with | `String s -> e.last_start <- false; e.next_name <- in_obj; w_json_string s k e | `Bool b -> e.last_start <- false; e.next_name <- in_obj; if b then writes "true" 0 4 k e else writes "false" 0 5 k e | `Float f -> e.last_start <- false; e.next_name <- in_obj; Buffer.clear e.buf; Printf.bprintf e.buf "%.16g" f; writebuf 0 (Buffer.length e.buf) k e | `Os -> e.last_start <- true; e.next_name <- true; e.nest <- e.nest + 1; e.stack <- `Os :: e.stack; writeb u_lbrace k e | `As -> e.last_start <- true; e.next_name <- false; e.nest <- e.nest + 1; e.stack <- `As :: e.stack; writeb u_lbrack k e | `Null -> e.last_start <- false; e.next_name <- in_obj; writes "null" 0 4 k e | `Oe | `Ae | `Name _ as l -> if in_obj then expect_mem_value l else expect_arr_value_ae l let w_lexeme k e l = let epop e = e.last_start <- false; e.nest <- e.nest - 1; e.stack <- List.tl e.stack; match e.stack with | `Os :: _ -> e.next_name <- true; | _ -> e.next_name <- false in match List.hd e.stack with | `Os -> (* inside object. *) if not e.next_name then w_value ~in_obj:true l k e else begin match l with | `Name n -> let name n k e = if e.minify then w_name n k e else writeb u_nl (w_indent (w_name n (writeb u_sp k))) e in if e.last_start then name n k e else writeb u_comma (name n k) e | `Oe -> if e.minify || e.last_start then (epop e; writeb u_rbrace k e) else (epop e; writeb u_nl (w_indent (writeb u_rbrace k)) e) | _ -> expect_name_or_oe l end | `As -> (* inside array. *) begin match l with | `Ae -> if e.minify || e.last_start then (epop e; writeb u_rbrack k e) else (epop e; writeb u_nl (w_indent (writeb u_rbrack k)) e) | l -> let value l k e = if e.minify then w_value ~in_obj:false l k e else writeb u_nl (w_indent (w_value ~in_obj:false l k)) e in if e.last_start then value l k e else writeb u_comma (value l k) e end let encode_ k e = function | `Lexeme l -> if e.stack = [] then expect_end l else w_lexeme k e l | `End as v -> if e.stack = [] then flush k e else expect_lend (List.hd e.stack) v | `White w -> writes w 0 (String.length w) k e | `Comment (`S, c) -> writes "//" 0 2 (writes c 0 (String.length c) (writeb u_nl k)) e | `Comment (`M, c) -> writes "/*" 0 2 (writes c 0 (String.length c) (writes "*/" 0 2 k)) e | `Await -> `Ok let rec encode_loop e = e.k <- encode_ encode_loop; `Ok let rec encode_json e = function (* first [k] to start with [`Os] or [`As]. *) | `Lexeme (`Os | `As as l) -> w_value ~in_obj:true (* irrelevant *) l encode_loop e | `End | `Lexeme _ as v -> expect_json v | `White _ | `Comment _ as v -> encode_ (fun e -> e.k <- encode_json; `Ok) e v | `Await -> `Ok let encoder ?(minify = true) dst = let o, o_pos, o_max = match dst with | `Manual -> "", 1, 0 (* implies [o_rem e = 0]. *) | `Buffer _ | `Channel _ -> String.create io_buffer_size, 0, io_buffer_size - 1 in { dst = (dst :> dst); minify; o; o_pos; o_max; buf = Buffer.create 30; stack = []; nest = 0; next_name = false; last_start = false; k = encode_json } let encode e v = e.k e (v :> [ encode | uncut ]) let encoder_dst e = e.dst let encoder_minify e = e.minify (* Manual *) module Manual = struct let src d = Uutf.Manual.src d.u let dst = dst let dst_rem = o_rem end (* Uncut *) module Uncut = struct let decode = decode_uncut let pp_decode = pp_decode let encode e v = e.k e (v :> [ encode | uncut]) end (* String conversion *) exception Escape of ((int * int) * (int * int)) * error type t = [ `Null | `Bool of bool | `Float of float| `String of string | `A of t list | `O of (string * t) list ] let json_of_src ?encoding src = let dec d = match decode d with | `Lexeme l -> l | `Error e -> raise (Escape (decoded_range d, e)) | `End | `Await -> assert false in let rec value v k d = match v with | `Os -> obj [] k d | `As -> arr [] k d | `Null | `Bool _ | `String _ | `Float _ as v -> k v d | _ -> assert false and arr vs k d = match dec d with | `Ae -> k (`A (List.rev vs)) d | v -> value v (fun v -> arr (v :: vs) k) d and obj ms k d = match dec d with | `Oe -> k (`O (List.rev ms)) d | `Name n -> value (dec d) (fun v -> obj ((n, v) :: ms) k) d | _ -> assert false in let d = decoder ?encoding src in try `JSON (value (dec d) (fun v _ -> v) d) with | Escape (r, e) -> `Error (r, e) let of_string str: t = match json_of_src (`String str) with | `JSON j -> j | `Error _ -> failwith "json_of_string" let json_to_dst ~minify dst (json:t) = let enc e l = ignore (encode e (`Lexeme l)) in let rec value v k e = match v with | `A vs -> arr vs k e | `O ms -> obj ms k e | `Null | `Bool _ | `Float _ | `String _ as v -> enc e v; k e and arr vs k e = enc e `As; arr_vs vs k e and arr_vs vs k e = match vs with | v :: vs' -> value v (arr_vs vs' k) e | [] -> enc e `Ae; k e and obj ms k e = enc e `Os; obj_ms ms k e and obj_ms ms k e = match ms with | (n, v) :: ms -> enc e (`Name n); value v (obj_ms ms k) e | [] -> enc e `Oe; k e in let e = encoder ~minify dst in let finish e = ignore (encode e `End) in match json with | `A _ | `O _ as json -> value json finish e | _ -> invalid_arg "invalid json text" let to_string (json:t) = let buf = Buffer.create 1024 in json_to_dst ~minify:false (`Buffer buf) json; Buffer.contents buf let json_output = ref None let json_buffer = ref [] let add json = json_buffer := json :: !json_buffer let set_output write = json_output := Some write let verbose () = !json_output <> None let output () = match !json_output with | None -> () | Some write -> let json = `A (List.rev !json_buffer) in write (to_string json) (*--------------------------------------------------------------------------- Copyright (c) 2012 Daniel C. Bünzli All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of Daniel C. Bünzli nor the names of contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ---------------------------------------------------------------------------*) opam-1.1.1/src/core/opamProcess.ml0000644000175000017500000001760112272210733015262 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) type t = { p_name : string; p_args : string list; p_pid : int; p_cwd : string; p_time : float; p_stdout : string option; p_stderr : string option; p_env : string option; p_info : string option; p_metadata: (string * string) list; } let open_flags = [Unix.O_WRONLY; Unix.O_CREAT; Unix.O_APPEND] let output_lines oc lines = List.iter (fun line -> output_string oc line; output_string oc "\n"; flush oc; ) lines; output_string oc "\n"; flush oc let option_map fn = function | None -> None | Some o -> Some (fn o) let option_default d = function | None -> d | Some v -> v let make_info ?code ~cmd ~args ~cwd ~env_file ~stdout_file ~stderr_file ~metadata () = let b = ref [] in let print name str = b := (name, str) :: !b in let print_opt name = function | None -> () | Some s -> print name s in print "opam-version" (OpamVersion.to_string OpamVersion.full); print "os" (OpamGlobals.os_string ()); print "command" (String.concat " " (cmd :: args)); print "path" cwd; List.iter (fun (k,v) -> print k v) metadata; print_opt "exit-code" (option_map string_of_int code); print_opt "env-file" env_file; print_opt "stdout-file" stdout_file; print_opt "stderr-file" stderr_file; List.rev !b let string_of_info ?(color=`yellow) info = let b = Buffer.create 1024 in List.iter (fun (k,v) -> Printf.bprintf b "%s %-20s %s\n" (OpamGlobals.colorise color "#") (OpamGlobals.colorise color k) v) info; Buffer.contents b let create ?info_file ?env_file ?stdout_file ?stderr_file ?env ?(metadata=[]) ~verbose cmd args = let nothing () = () in let tee f = let fd = Unix.openfile f open_flags 0o644 in let close_fd () = Unix.close fd in if verbose then ( flush stderr; let chan = Unix.open_process_out ("tee -a " ^ Filename.quote f) in let close () = match Unix.close_process_out chan with | _ -> close_fd () in Unix.descr_of_out_channel chan, close ) else fd, close_fd in let stdout_fd, close_stdout = match stdout_file with | None -> Unix.stdout, nothing | Some f -> tee f in let stderr_fd, close_stderr = match stderr_file with | None -> Unix.stderr, nothing | Some f -> tee f in let env = match env with | None -> Unix.environment () | Some e -> e in let time = Unix.gettimeofday () in let cwd = Sys.getcwd () in let () = (* write the env file before running the command*) match env_file with | None -> () | Some f -> let chan = open_out f in let env = Array.to_list env in (* Remove dubious variables *) let env = List.filter (fun line -> not (OpamMisc.contains line '$')) env in output_lines chan env; close_out chan in let () = (* write the info file *) match info_file with | None -> () | Some f -> let chan = open_out f in let info = make_info ~cmd ~args ~cwd ~env_file ~stdout_file ~stderr_file ~metadata () in output_string chan (string_of_info info); close_out chan in let pid = Unix.create_process_env cmd (Array.of_list (cmd :: args)) env Unix.stdin stdout_fd stderr_fd in close_stdout (); close_stderr (); { p_name = cmd; p_args = args; p_pid = pid; p_cwd = cwd; p_time = time; p_stdout = stdout_file; p_stderr = stderr_file; p_env = env_file; p_info = info_file; p_metadata = metadata; } type result = { r_code : int; r_duration : float; r_info : (string * string) list; r_stdout : string list; r_stderr : string list; r_cleanup : string list; } (* XXX: the function might block for ever for some channels kinds *) let read_lines f = try let ic = open_in f in let lines = ref [] in begin try while true do let line = input_line ic in lines := line :: !lines; done with _ -> () end; close_in ic; List.rev !lines with _ -> [] let wait p = let rec iter () = let _, status = Unix.waitpid [] p.p_pid in match status with | Unix.WEXITED code -> let duration = Unix.gettimeofday () -. p.p_time in let stdout = option_default [] (option_map read_lines p.p_stdout) in let stderr = option_default [] (option_map read_lines p.p_stderr) in let cleanup = OpamMisc.filter_map (fun x -> x) [ p.p_info; p.p_env; p.p_stderr; p.p_stdout ] in let info = make_info ~code ~cmd:p.p_name ~args:p.p_args ~cwd:p.p_cwd ~metadata:p.p_metadata ~env_file:p.p_env ~stdout_file:p.p_stdout ~stderr_file:p.p_stderr () in { r_code = code; r_duration = duration; r_info = info; r_stdout = stdout; r_stderr = stderr; r_cleanup = cleanup; } | _ -> iter () in iter () let run ?env ?(verbose=false) ?name ?(metadata=[]) cmd args = let file f = match name with | None -> None | Some n -> Some (f n) in let stdout_file = file (Printf.sprintf "%s.out") in let stderr_file = file (Printf.sprintf "%s.err") in let env_file = file (Printf.sprintf "%s.env") in let info_file = file (Printf.sprintf "%s.info") in let env = match env with Some e -> e | None -> Unix.environment () in let p = create ~env ?info_file ?env_file ?stdout_file ?stderr_file ~verbose ~metadata cmd args in wait p let is_success r = r.r_code = 0 let is_failure r = r.r_code <> 0 let safe_unlink f = try Unix.unlink f with _ -> () let clean_files r = List.iter safe_unlink r.r_cleanup let truncate_str = "...[truncated]" (* Truncate long lines *) let truncate_line str = if String.length str <= OpamGlobals.log_line_limit then str else String.sub str 0 (OpamGlobals.log_line_limit) ^ truncate_str (* Take the last [n] elements of [l] *) let rec truncate = function | [] -> [] | l -> if List.length l < OpamGlobals.log_limit then List.map truncate_line l else if List.length l = OpamGlobals.log_limit then truncate_str :: l else match l with | [] -> [] | _ :: t -> truncate t let string_of_result ?(color=`yellow) r = let b = Buffer.create 2048 in let print = Buffer.add_string b in let println str = print str; Buffer.add_char b '\n' in print (string_of_info ~color r.r_info); if r.r_stdout <> [] then print (OpamGlobals.colorise color "### stdout ###\n"); List.iter (fun s -> print (OpamGlobals.colorise color "# "); println s) (truncate r.r_stdout); if r.r_stderr <> [] then print (OpamGlobals.colorise color "### stderr ###\n"); List.iter (fun s -> print (OpamGlobals.colorise color "# "); println s) (truncate r.r_stderr); Buffer.contents b opam-1.1.1/src/core/opamParallel.mli0000644000175000017500000000536612272210733015556 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) (** Concurrent process execution *) (** Functor argument *) module type G = sig include Graph.Sig.I include Graph.Topological.G with type t := t and module V := V val has_cycle: t -> bool val scc_list: t -> V.t list list val string_of_vertex: V.t -> string end type error = | Process_error of OpamProcess.result | Internal_error of string | Package_error of string (** Functor signature *) module type SIG = sig module G : G (** [iter n t pre child paren] parallel iteration on [n] cores. [child] is evaluated in a remote process and when it as finished, whereas [pre] and [post] are evaluated on the current process (respectively before and after the child process has been created). *) val iter: int -> G.t -> pre:(G.V.t -> unit) -> child:(G.V.t -> unit) -> post:(G.V.t -> unit) -> unit (** Parallel iteration on a list. *) val iter_l: int -> G.vertex list -> pre:(G.V.t -> unit) -> child:(G.V.t -> unit) -> post:(G.V.t -> unit) -> unit (** Map-reduce on a graph *) val map_reduce: int -> G.t -> map:(G.V.t -> 'a) -> merge:('a -> 'a -> 'a) -> init:'a -> 'a (** Map-reduce on a list. *) val map_reduce_l: int -> G.vertex list -> map:(G.V.t -> 'a) -> merge:('a -> 'a -> 'a) -> init:'a -> 'a (** Build a graph on concurrent tasks from a list of tasks. *) val create: G.V.t list -> G.t (** Errors ([errors], [remaining]) *) exception Errors of (G.V.t * error) list * G.V.t list (** The graph is cyclic. *) exception Cyclic of G.V.t list list end (** Functor *) module Make (G : G) : SIG with module G = G opam-1.1.1/src/core/opamSystem.ml0000644000175000017500000004357112272210733015135 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) exception Process_error of OpamProcess.result exception Internal_error of string exception Command_not_found of string let log fmt = OpamGlobals.log "SYSTEM" fmt let internal_error fmt = Printf.ksprintf (fun str -> log "error: %s" str; raise (Internal_error str) ) fmt let process_error r = raise (Process_error r) let command_not_found cmd = raise (Command_not_found cmd) module Sys2 = struct (* same as [Sys.is_directory] except for symlinks, which returns always [false]. *) let is_directory file = Unix.( (lstat file).st_kind = S_DIR ) end let (/) = Filename.concat let temp_basename prefix = Printf.sprintf "%s-%d-%06x" prefix (Unix.getpid ()) (Random.int 0xFFFFFF) let rec mk_temp_dir () = let s = Filename.temp_dir_name / temp_basename "opam" in if Sys.file_exists s then mk_temp_dir () else s let safe_mkdir dir = if not (Sys.file_exists dir) then try log "mkdir %s" dir; Unix.mkdir dir 0o755 with Unix.Unix_error(Unix.EEXIST,_,_) -> () let mkdir dir = let rec aux dir = if not (Sys.file_exists dir) then begin aux (Filename.dirname dir); safe_mkdir dir; end in aux dir let temp_files = Hashtbl.create 1024 let rec temp_file ?dir prefix = let temp_dir = match dir with | None -> !OpamGlobals.root_dir / "log" | Some d -> d in mkdir temp_dir; let file = temp_dir / temp_basename prefix in if Hashtbl.mem temp_files file then temp_file ?dir prefix else ( Hashtbl.add temp_files file true; file ) let remove_file file = if Sys.file_exists file || (try let _ = Unix.lstat file in true with _ -> false) then ( try log "rm %s" file; Unix.unlink file with e -> internal_error "Cannot remove %s (%s)." file (Printexc.to_string e) ) let string_of_channel ic = let n = 32768 in let s = String.create n in let b = Buffer.create 1024 in let rec iter ic b s = let nread = try input ic s 0 n with End_of_file -> 0 in if nread > 0 then ( Buffer.add_substring b s 0 nread; iter ic b s ) in iter ic b s; Buffer.contents b let read file = let ic = open_in_bin file in let s = string_of_channel ic in close_in ic; s let write file contents = mkdir (Filename.dirname file); let oc = open_out_bin file in output_string oc contents; close_out oc let chdir dir = if Sys.file_exists dir then ( Unix.chdir dir ) else internal_error "%s does not exist." dir let in_dir dir fn = let reset_cwd = let cwd = try Some (Sys.getcwd ()) with _ -> None in fun () -> match cwd with | None -> () | Some cwd -> try chdir cwd with _ -> () in chdir dir; try let r = fn () in reset_cwd (); r with e -> reset_cwd (); raise e let list kind dir = if Sys.file_exists dir then in_dir dir (fun () -> let d = Sys.readdir (Sys.getcwd ()) in let d = Array.to_list d in let l = List.filter kind d in List.sort compare (List.rev_map (Filename.concat dir) l) ) else [] let files_with_links = list (fun f -> try not (Sys.is_directory f) with _ -> true) let files_all_not_dir = list (fun f -> try not (Sys2.is_directory f) with _ -> true) let directories_strict = list (fun f -> try Sys2.is_directory f with _ -> false) let directories_with_links = list (fun f -> try Sys.is_directory f with _ -> false) let rec_files dir = let rec aux accu dir = let d = directories_with_links dir in let f = files_with_links dir in List.fold_left aux (f @ accu) d in aux [] dir let files dir = files_with_links dir let rec_dirs dir = let rec aux accu dir = let d = directories_with_links dir in List.fold_left aux (d @ accu) d in aux [] dir let dirs dir = directories_with_links dir (* XXX: won't work on windows *) let remove_dir dir = log "rmdir %s" dir; if Sys.file_exists dir then ( let err = Sys.command (Printf.sprintf "rm -rf %s" dir) in if err <> 0 then internal_error "Cannot remove %s (error %d)." dir err ) let with_tmp_dir fn = let dir = mk_temp_dir () in try mkdir dir; let e = fn dir in remove_dir dir; e with e -> remove_dir dir; raise e let remove file = if Sys.file_exists file && Sys2.is_directory file then remove_dir file else remove_file file let getchdir s = let p = Sys.getcwd () in chdir s; p let normalize s = getchdir (getchdir s) let needs_normalization f = Sys.file_exists f && Filename.is_relative f let real_path p = if not (needs_normalization p) then p else if Sys.is_directory p then normalize p else ( let dir = let d = Filename.dirname p in if needs_normalization d then normalize d else d in let base = Filename.basename p in if base = "." then dir else dir / base ) type command = string list let default_env = Unix.environment () let reset_env = lazy ( let env = OpamMisc.env () in let env = List.rev_map (fun (k,v as c) -> match k with | "PATH" -> k, String.concat ":" (OpamMisc.reset_env_value ~prefix:!OpamGlobals.root_dir v) | _ -> c ) env in let env = List.rev_map (fun (k,v) -> k^"="^v) env in Array.of_list env ) let command_exists ?(env=default_env) name = let open OpamGlobals in let cmd, args = "/bin/sh", ["-c"; Printf.sprintf "type %s" name] in let r = OpamProcess.run ~env ~name:(temp_file "type") ~verbose:false cmd args in OpamProcess.clean_files r; OpamProcess.is_success r let runs = ref [] let print_stats () = match !runs with | [] -> () | l -> OpamGlobals.msg "%d external processes called:\n %s\n%!" (List.length l) (String.concat "\n " (List.map (String.concat " ") l)) let log_file name = match name with | None -> temp_file "log" | Some n -> temp_file ~dir:(Sys.getcwd ()) n let log_cleanup r = if not !OpamGlobals.debug then OpamProcess.clean_files r let run_process ?verbose ?(env=default_env) ~name ?metadata command = let chrono = OpamGlobals.timer () in runs := command :: !runs; match command with | [] -> invalid_arg "run_process" | cmd :: args -> (* Check that the command doesn't contain whitespaces *) if None <> try Some (String.index cmd ' ') with Not_found -> None then OpamGlobals.warning "Command %S contains 1 space" cmd; if command_exists ~env cmd then ( let verbose = match verbose with | None -> !OpamGlobals.debug || !OpamGlobals.verbose | Some b -> b in let r = OpamProcess.run ~env ~name ~verbose ?metadata cmd args in let str = String.concat " " (cmd :: args) in log "[%s] (in %.3fs) %s" (Filename.basename name) (chrono ()) str; r ) else (* Display a user-friendly message if the command does not exist *) command_not_found cmd let command ?verbose ?env ?name ?metadata cmd = let name = log_file name in let r = run_process ?verbose ?env ~name ?metadata cmd in if OpamProcess.is_success r then log_cleanup r else process_error r let commands ?verbose ?env ?name ?metadata ?(keep_going=false) commands = let name = log_file name in let run = run_process ?verbose ?env ~name ?metadata in let command r0 c = if keep_going || OpamProcess.is_success r0 then let r = run c in (if OpamProcess.is_failure r0 then r0 else r) else r0 in match commands with | [] -> () | c1::c -> let r = List.fold_left command (run c1) c in if OpamProcess.is_success r then log_cleanup r else process_error r let read_command_output ?verbose ?env ?metadata cmd = let name = log_file None in let r = run_process ?verbose ?env ~name ?metadata cmd in if OpamProcess.is_success r then (log_cleanup r; r.OpamProcess.r_stdout) else process_error r (* Return [None] if the command does not exist *) let read_command_output_opt ?verbose ?env cmd = try Some (read_command_output ?verbose ?env cmd) with Command_not_found _ -> None let copy src dst = if Sys.is_directory src then internal_error "Cannot copy %s: it is a directory." src; if Sys.file_exists dst && Sys.is_directory dst then internal_error "Cannot copy to %s: it is a directory." dst; if Sys.file_exists dst then remove_file dst; mkdir (Filename.dirname dst); if src <> dst then command ["cp"; src; dst ] module Tar = struct let extensions = [ [ "tar.gz" ; "tgz" ], 'z' ; [ "tar.bz2" ; "tbz" ], 'j' ; [ "tar.xz" ; "txz" ], 'J' ; [ "tar.lzma" ; "tlz" ], 'Y' ] let guess_type f = let ic = open_in f in let c1 = input_char ic in let c2 = input_char ic in close_in ic; match c1, c2 with | '\031', '\139' -> Some 'z' | 'B' , 'Z' -> Some 'j' | '\xfd', '\x37' -> Some 'J' | '\x5d', '\x00' -> Some 'Y' | _ -> None let match_ext file ext = List.exists (Filename.check_suffix file) ext let is_archive f = List.exists (fun suff -> Filename.check_suffix f suff) (List.concat (List.rev_map fst extensions)) let extract_function file = let command c dir = command [ "tar" ; Printf.sprintf "xf%c" c ; file; "-C" ; dir ] in let ext = List.fold_left (fun acc (ext, c) -> match acc with | Some f -> Some f | None -> if match_ext file ext then Some (command c) else None) None extensions in match ext with | Some f -> Some f | None -> match guess_type file with | None -> None | Some c -> Some (command c) end module Zip = struct let is_archive f = Filename.check_suffix f "zip" let extract_function file = Some (fun dir -> command [ "unzip" ; file; "-d"; dir ]) end let is_tar_archive = Tar.is_archive let extract file dst = let kind, extract_function = if Zip.is_archive file then "zip", Zip.extract_function else "tar", Tar.extract_function in with_tmp_dir (fun tmp_dir -> match extract_function file with | None -> internal_error "%s is not a valid %s archive." file kind | Some f -> f tmp_dir; if Sys.file_exists dst then internal_error "Extracting the archive will overwrite %s." dst; match directories_strict tmp_dir with | [x] -> mkdir (Filename.dirname dst); command [ "mv"; x; dst] | _ -> internal_error "The archive %S contains multiple root directories." file ) let extract_in file dst = if not (Sys.file_exists dst) then internal_error "%s does not exist." file; match Tar.extract_function file with | None -> internal_error "%s is not a valid tar archive." file | Some f -> f dst let link src dst = if Sys.file_exists src then ( mkdir (Filename.dirname dst); if Sys.file_exists dst then remove_file dst; try log "ln -s %s %s" src dst; Unix.symlink src dst with Unix.Unix_error (Unix.EXDEV, _, _) -> (* Fall back to copy if hard links are not supported *) copy src dst ) else internal_error "link: %s does not exist." src let flock file = let l = ref 0 in let id = string_of_int (Unix.getpid ()) in let max_l = 5 in let rec loop () = if Sys.file_exists file && !l < max_l then begin let ic = open_in file in let pid = input_line ic in close_in ic; OpamGlobals.msg "Another process (%s) has already locked %S. Retrying in 1s (%d/%d)\n" pid file !l max_l; Unix.sleep 1; incr l; loop () end else if Sys.file_exists file then internal_error "Too many attempts. Cancelling." else begin let oc = open_out file in output_string oc id; flush oc; close_out oc; OpamGlobals.log id "locking %s" file; end in loop () let funlock file = let id = string_of_int (Unix.getpid ()) in if Sys.file_exists file then ( let ic = open_in file in try let s = input_line ic in close_in ic; if s = id then ( log "unlocking %s (%s)" file id; log "rm %s" file; Unix.unlink file; ) else internal_error "Cannot unlock %s (%s)." file s with _ -> OpamGlobals.error "%s is broken, removing it and continuing anyway." file; close_in ic; log "rm %s" file; try Unix.unlink file with _ -> () ) else log "Cannot find %s, but continuing anyway..." file let ocaml_version = lazy ( match read_command_output_opt ~verbose:false [ "ocamlc" ; "-version" ] with | Some (h::_) -> let version = OpamMisc.strip h in log "ocamlc version: %s" version; Some version | Some [] -> internal_error "`ocamlc -version` is empty." | None -> None ) (* Reset the path to get the system compiler *) let system command = lazy ( let env = Lazy.force reset_env in match read_command_output_opt ~verbose:false ~env command with | None -> None | Some (h::_) -> Some (OpamMisc.strip h) | Some ([]) -> internal_error "%S is empty." (String.concat " " command) ) let system_ocamlc_where = system [ "ocamlc"; "-where" ] let system_ocamlc_version = system [ "ocamlc"; "-version" ] let download_command = let retry = string_of_int OpamGlobals.download_retry in let wget src = let wget = [ "wget"; "--content-disposition"; "--no-check-certificate"; "-t"; retry; src ] in command wget in let curl command src = let curl = [ command; "--write-out"; "%{http_code}\\n"; "--insecure"; "--retry"; retry; "--retry-delay"; "2"; "-OL"; src ] in match read_command_output curl with | [] -> internal_error "curl: empty response while downloading %s" src | l -> let code = List.hd (List.rev l) in try if int_of_string code >= 400 then raise Exit with _ -> internal_error "curl: code %s while downloading %s" code src in lazy ( match OpamGlobals.curl_command with | Some cmd -> curl cmd | None -> if command_exists "curl" then curl "curl" else if command_exists "wget" then wget else internal_error "Cannot find curl nor wget." ) let really_download ~overwrite ~src ~dst = let download = (Lazy.force download_command) in let aux () = download src; match list (fun _ -> true) "." with ( [] | _::_::_ ) -> internal_error "Too many downloaded files." | [filename] -> if not overwrite && Sys.file_exists dst then internal_error "The downloaded file will overwrite %s." dst; commands [ [ "rm"; "-f"; dst ]; [ "mv"; filename; dst ]; ]; dst in try with_tmp_dir (fun tmp_dir -> in_dir tmp_dir aux) with | Internal_error s as e -> OpamGlobals.error "%s" s; raise e | _ -> internal_error "Cannot download %s, please check your connection settings." src let download ~overwrite ~filename:src ~dst:dst = if dst = src then dst else if Sys.file_exists src then ( if not overwrite && Sys.file_exists dst then internal_error "The downloaded file will overwrite %s." dst; commands [ [ "rm"; "-f"; dst ]; [ "cp"; src; dst ] ]; dst ) else really_download ~overwrite ~src ~dst let patch p = let max_trying = 5 in if not (Sys.file_exists p) then internal_error "Patch file %S not found." p; let patch ~dryrun n = let opts = if dryrun then let open OpamGlobals in match OpamGlobals.os () with | FreeBSD | OpenBSD | NetBSD | DragonFly -> [ "-t"; "-C" ] | Unix | Linux | Darwin -> [ "--dry-run" ] | Win32 | Cygwin (* this is probably broken *) | Other _ -> [ "--dry-run" ] else [] in let verbose = if dryrun then Some false else None in command ?verbose ("patch" :: ("-p" ^ string_of_int n) :: "-i" :: p :: opts) in let rec aux n = if n = max_trying then internal_error "Patch %s does not apply." p else if None = try Some (patch ~dryrun:true n) with _ -> None then aux (succ n) else patch ~dryrun:false n in aux 0 let () = let with_opam_info m = let git_version = match OpamVersion.git with | None -> "" | Some v -> Printf.sprintf " (%s)" (OpamVersion.to_string v) in let opam_version = Printf.sprintf "%s%s" (OpamVersion.to_string OpamVersion.current) git_version in let os = OpamGlobals.os_string () in Printf.sprintf "# %-15s %s\n\ # %-15s %s\n\ %s" "opam-version" opam_version "os" os m in Printexc.register_printer (function | Process_error r -> Some (OpamProcess.string_of_result r) | Internal_error m -> Some (with_opam_info m) | Command_not_found c -> Some (Printf.sprintf "%S: command not found." c) | Sys.Break -> Some "User interruption" | Unix.Unix_error (e, fn, msg) -> let msg = if msg = "" then "" else " on " ^ msg in let error = Printf.sprintf "%s: %S failed%s: %s" Sys.argv.(0) fn msg (Unix.error_message e) in Some (with_opam_info error) | _ -> None ) opam-1.1.1/src/core/opamPackage.mli0000644000175000017500000001017512272210733015347 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) (** {2 Package name and versions} *) (** Versions *) module Version: sig include OpamMisc.ABSTRACT (** A pinned package version *) val pinned: t (** Compare two versions using the Debian version scheme *) val compare: t -> t -> int end (** Names *) module Name: sig include OpamMisc.ABSTRACT (** Compare two package names *) val compare: t -> t -> int (** global configuration package *) val global_config: t end (** Package (name x version) pairs *) include OpamMisc.ABSTRACT (** Return the package name *) val name: t -> Name.t (** Return None if [nv] is not a valid package name *) val of_string_opt: string -> t option (** Return the version name *) val version: t -> Version.t (** Create a new pair (name x version) *) val create: Name.t -> Version.t -> t (** Guess the package name from a filename. This function extracts [name] and [version] from {i /path/to/$name.$version/opam} *) val of_filename: OpamFilename.t -> t option (** Guess the package name from a directory name. This function extracts {i $name} and {i $version} from {i /path/to/$name.$version/} *) val of_dirname: OpamFilename.Dir.t -> t option (** Guess the package name from an archive file. This function extract {i $name} and {i $version} from {i /path/to/$name.$version+opam.tar.gz} *) val of_archive: OpamFilename.t -> t option (** Convert a set of pairs to a map [name -> versions] *) val to_map: Set.t -> Version.Set.t Name.Map.t (** Extract the versions from a collection of packages *) val versions_of_packages: Set.t -> Version.Set.t (** Return the list of versions for a given package *) val versions_of_name: Set.t -> Name.t -> Version.Set.t (** Extract the naes from a collection of packages *) val names_of_packages: Set.t -> Name.Set.t (** Return all the packages with the given name *) val packages_of_name: Set.t -> Name.t -> Set.t (** Return all the packages with one of the given names *) val packages_of_names: Set.t -> Name.Set.t -> Set.t (** Compare two packages *) val compare: t -> t -> int (** Are two packages equal ? *) val equal: t -> t -> bool (** Hash a package *) val hash: t -> int (** Return all the package descriptions in a given directory *) val list: OpamFilename.Dir.t -> Set.t (** Return all the package descriptions in the current directory (and their eventual prefixes). *) val prefixes: OpamFilename.Dir.t -> string option Map.t (** {2 Errors} *) (** Unknown package: either the name is unknown, or the version does not exist. *) val unknown: Name.t -> Version.t option -> 'a (** Unavailable package: the package exists in the database, but it is not available due to compiler/OS constraints. *) val unavailable: Name.t -> Version.t option -> 'a (** Unavailable because the package is pinned. *) val unavailable_because_pinned: Name.t -> Version.t option -> 'a (** Create a (path)-pinned package. *) val pinned: Name.t -> t (** Check if a package is pinned. *) val is_pinned: t -> bool (** Parallel executions. *) module Parallel: OpamParallel.SIG with type G.V.t = t opam-1.1.1/src/core/opamFilename.mli0000644000175000017500000001617012272210733015535 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) (** Typed filename manipulation *) (** Basenames *) module Base: OpamMisc.ABSTRACT (** Directory names *) module Dir: OpamMisc.ABSTRACT (** Return the current working directory *) val cwd: unit -> Dir.t (** Remove a directory *) val rmdir: Dir.t -> unit (** Clean the contents of a directory. *) val cleandir: Dir.t -> unit (** Create a directory *) val mkdir: Dir.t -> unit (** List the sub-directory recursively *) val rec_dirs: Dir.t -> Dir.t list (** List the sub-directory (do not recurse) *) val dirs: Dir.t -> Dir.t list (** Evaluate a function in a given directory *) val in_dir: Dir.t -> (unit -> 'a) -> 'a (** Execute a list of commands in a given directory *) val exec: Dir.t -> ?env:(string * string) list -> ?name:string -> ?metadata:(string * string) list -> ?keep_going:bool -> string list list -> unit (** Move a directory *) val move_dir: src:Dir.t -> dst:Dir.t -> unit (** Copy a directory *) val copy_dir: src:Dir.t -> dst:Dir.t -> unit (** Link a directory *) val link_dir: src:Dir.t -> dst:Dir.t -> unit (** Does the directory existsb ? *) val exists_dir: Dir.t -> bool (** Return the parent directory *) val dirname_dir: Dir.t -> Dir.t (** Return the deeper directory name *) val basename_dir: Dir.t -> Base.t (** Turn a full path into a list of directory names *) val to_list_dir: Dir.t -> Dir.t list (** Creation from a raw string (as {i http://}) *) val raw_dir: string -> Dir.t (** Execute a function in a temp directory *) val with_tmp_dir: (Dir.t -> 'a) -> 'a include OpamMisc.ABSTRACT (** Generic filename *) type generic_file = | D of Dir.t | F of t (** Create a filename from a Dir.t and a basename *) val create: Dir.t -> Base.t -> t (** Create a file from a basename and the current working directory as dirname *) val of_basename: Base.t -> t (** Creation from a raw string (as {i http://}) *) val raw: string -> t (** Prettify a filename: - replace /path/to/opam/foo by /foo - replace /path/to/home/foo by ~/foo *) val prettify: t -> string (** Prettify a dirname. *) val prettify_dir: Dir.t -> string (** Return the directory name *) val dirname: t -> Dir.t (** Return the base name *) val basename: t -> Base.t (** Retrieves the contents from the hard disk. *) val read: t -> string (** Open a channel from a given file. *) val open_in: t -> in_channel (** Removes everything in [filename] if existed. *) val remove: t -> unit (** Removes everything in [filename] if existed, then write [contents] instead. *) val write: t -> string -> unit (** see [Sys.file_exists] *) val exists: t -> bool (** Check whether a file has a given suffix *) val check_suffix: t -> string -> bool (** Add a file extension *) val add_extension: t -> string -> t (** Remove the file extension *) val chop_extension: t -> t (** List all the filenames, recursively *) val rec_files: Dir.t -> t list (** List all the filename. Do not recurse. *) val files: Dir.t -> t list (** Apply a function on the contents of a file *) val with_contents: (string -> 'a) -> t -> 'a (** Copy a file in a directory. If [root] is set, copy also the sub-directories. For instance, [copy_in ~root:"/foo" "/foo/bar/gni" "/toto"] creates ["/toto/bar/gni"]. *) val copy_in: ?root:Dir.t -> t -> Dir.t -> unit (** Move a file *) val move: src:t -> dst:t -> unit (** Symlink a file in a directory *) val link_in: t -> Dir.t -> unit (** Read a symlinked file *) val readlink: t -> t (** Is a symlink ? *) val is_symlink: t -> bool (** Copy a file *) val copy: src:t -> dst:t -> unit (** Symlink a file. If symlink is not possible on the system, use copy instead. *) val link: src:t -> dst:t -> unit (** Extract an archive in a given directory (it rewrites the root to match [Dir.t] dir if needed) *) val extract: t -> Dir.t -> unit (** Extract an archive in a given directory (which should already exists) *) val extract_in: t -> Dir.t -> unit (** Extract a generic file *) val extract_generic_file: generic_file -> Dir.t -> unit (** Check whether a filename starts by a given Dir.t *) val starts_with: Dir.t -> t -> bool (** Check whether a filename ends with a given suffix *) val ends_with: string -> t -> bool (** Remove a prefix from a file name *) val remove_prefix: Dir.t -> t -> string (** Remove a suffix from a filename *) val remove_suffix: Base.t -> t -> string (** download a remote file in a given directory. Return the location of the downloaded file if the download is successful. *) val download: overwrite:bool -> t -> Dir.t -> t (** same as [download], but with a specified destination filename instead of a directory *) val download_as: overwrite:bool -> t -> t -> unit (** iterate downloads until one is sucessful *) val download_iter: overwrite:bool -> t list -> Dir.t -> t (** Apply a patch to a directory *) val patch: t -> Dir.t -> unit (** Compute the MD5 digest of a file *) val digest: t -> string (** Compute the MD5 digest a file. Return the empty list if the file does not exist. *) val checksum: t -> string list (** Compute the MD5 digest for all files in a directory. *) val checksum_dir: Dir.t -> string list (** Create an empty file *) val touch: t -> unit (** Change file permissions *) val chmod: t -> int -> unit (** File locks *) val with_flock: t -> ('a -> 'b) -> 'a -> 'b (** [copy_if_check t src dst] copies all the files from one directory to another. Do nothing if OPAMDONOTCOPYFILE is set to a non-empty value. *) val copy_files: src:Dir.t -> dst:Dir.t -> unit module OP: sig (** Create a new directory *) val (/): Dir.t -> string -> Dir.t (** Create a new filename *) val (//): Dir.t -> string -> t end (** Simple structure to hanle file attributes *) module Attribute: sig include OpamMisc.ABSTRACT (** Get remote filename *) val base: t -> Base.t (** MD5 digest of the remote file *) val md5: t -> string (** File permission *) val perm: t -> int option (** Constructor*) val create: Base.t -> string -> int -> t end (** Convert a filename to an attribute, relatively to a root *) val to_attribute: Dir.t -> t -> Attribute.t opam-1.1.1/src/core/opamVariable.mli0000644000175000017500000000563612272210733015547 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) (** {2 Variable names} *) include OpamMisc.ABSTRACT (** Shortcut to variables *) type variable = t (** Variable contents *) type variable_contents = | B of bool | S of string (** Pretty print of variable contents *) val string_of_variable_contents: variable_contents -> string (** the variable [enable] *) val enable: t (** the variable [installed] *) val installed: t (** Section names *) module Section: sig include OpamMisc.ABSTRACT (** Graph of fully-qualified sections *) module G : Graph.Sig.I with type V.t = t (** Iteration in topological order *) val graph_iter : (G.V.t -> unit) -> G.t -> unit (** Shortcut to sections *) type section = t (** Fully qualified section names *) module Full: sig include OpamMisc.ABSTRACT (** Create a fully qualified section *) val create: OpamPackage.Name.t -> section -> t (** All the sections in a package *) val all: OpamPackage.Name.t -> t (** Return the package name in which the section is *) val package: t -> OpamPackage.Name.t (** Return the optional section OpamPackage.Name.t: [None] means all available sections. *) val section: t -> section option end end (** Fully qualified variables *) module Full: sig include OpamMisc.ABSTRACT (** Create a variable local for a given library/syntax extension *) val create_local: OpamPackage.Name.t -> Section.t -> variable -> t (** Create a global variable for a package *) val create_global: OpamPackage.Name.t -> variable -> t (** Return the package the variable is defined in *) val package: t -> OpamPackage.Name.t (** Return the section (library or syntax extension) the package is defined in *) val section: t -> Section.t option (** Return the variable name *) val variable: t -> variable end opam-1.1.1/src/core/opamPackage.ml0000644000175000017500000002021612272210733015173 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) open OpamMisc.OP let log fmt = OpamGlobals.log "PACKAGE" fmt module Version = struct type version = | Version of string | Pinned type t = version let to_string = function | Version x -> x | Pinned -> "pinned" let of_string = function | "pinned" -> Pinned | v -> Version v let pinned = Pinned let compare x y = match (x,y) with | Version v1, Version v2 -> Debian.Version.compare v1 v2 | Pinned , Pinned -> 0 | Pinned , _ -> 1 | _ , Pinned -> -1 let to_json x = `String (to_string x) module O = struct type t = version let to_string = to_string let compare = compare let to_json = to_json end module Set = OpamMisc.Set.Make(O) module Map = OpamMisc.Map.Make(O) end module Name = struct type t = string let to_string x = x let of_string x = x let global_config = OpamGlobals.global_config let compare n1 n2 = match compare (String.lowercase n1) (String.lowercase n2) with | 0 -> compare n1 n2 | i -> i let to_json x = `String x module O = struct type t = string let to_string = to_string let compare = compare let to_json = to_json end module Set = OpamMisc.Set.Make(O) module Map = OpamMisc.Map.Make(O) end type t = { name : Name.t; version: Version.t; } let create name version = { name; version } let pinned name = { name; version = Version.pinned } let name t = t.name let version t = t.version let is_pinned t = t.version = Version.pinned let sep = '.' let of_string_opt s = if OpamMisc.contains s ' ' || OpamMisc.contains s '\n' then None else match OpamMisc.cut_at s sep with | None -> None | Some (n, v) -> Some { name = Name.of_string n; version = Version.of_string v } let of_string s = match of_string_opt s with | Some x -> x | None -> OpamGlobals.error_and_exit "%s is not a valid versioned package name" s let to_string t = Printf.sprintf "%s%c%s" (Name.to_string t.name) sep (Version.to_string t.version) let compare nv1 nv2 = match Name.compare nv1.name nv2.name with | 0 -> Version.compare nv1.version nv2.version | i -> i let hash nv = Hashtbl.hash nv let equal nv1 nv2 = compare nv1 nv2 = 0 let to_json nv = `O [ ("name", Name.to_json (name nv)); ("version", Version.to_json (version nv)); ] module O = struct type tmp = t type t = tmp let compare = compare let to_string = to_string let to_json = to_json end module Set = OpamMisc.Set.Make (O) module Map = OpamMisc.Map.Make (O) let to_map nv = Set.fold (fun nv map -> let name = name nv in let version = version nv in let versions = if Name.Map.mem name map then Name.Map.find name map else Version.Set.empty in Name.Map.add name (Version.Set.add version versions) (Name.Map.remove name map) ) nv Name.Map.empty (* $DIR/$NAME.$VERSION/ *) let of_dirname f = f |> OpamFilename.basename_dir |> OpamFilename.Base.to_string |> of_string_opt (* $DIR/$NAME.$VERSION/opam *) let of_filename f = if OpamFilename.basename f = OpamFilename.Base.of_string "opam" then of_dirname (OpamFilename.dirname f) else None (* $NAME.$VERSION+opam.tar.gz *) let of_archive f = let base = OpamFilename.basename f in match OpamMisc.cut_at (OpamFilename.Base.to_string base) '+' with | None -> None | Some (s,_) -> of_string_opt s let list dir = log "list %s" (OpamFilename.Dir.to_string dir); if OpamFilename.exists_dir dir then ( let files = OpamFilename.rec_files dir in List.fold_left (fun set f -> match of_filename f with | None -> set | Some p -> if not (Set.mem p set) then Set.add p set else let suffix = Filename.concat (to_string p) "opam" in let files = List.filter (OpamFilename.ends_with suffix) files in OpamGlobals.error_and_exit "Multiple definition of package %s in %s:\n %s" (to_string p) (OpamFilename.Dir.to_string dir) (String.concat "\n " (List.map OpamFilename.to_string files)); ) Set.empty files ) else Set.empty let prefixes dir = log "prefixes %s" (OpamFilename.Dir.to_string dir); if OpamFilename.exists_dir dir then ( let files = OpamFilename.rec_files dir in List.fold_left (fun map f -> match of_filename f with | None -> map | Some p -> let dirname = OpamFilename.dirname_dir (OpamFilename.dirname f) in let suffix = OpamFilename.Dir.to_string dirname in let prefix = match OpamMisc.remove_prefix ~prefix:(OpamFilename.Dir.to_string dir) suffix with | "" -> None | p -> (* drop the leading '/' from the prefix *) Some String.(sub p 1 (length p - 1)) in Map.add p prefix map ) Map.empty files ) else Map.empty let versions_of_packages nvset = Set.fold (fun nv vset -> Version.Set.add (version nv) vset) nvset Version.Set.empty let names_of_packages nvset = Set.fold (fun nv vset -> Name.Set.add (name nv) vset) nvset Name.Set.empty let packages_of_name nvset n = Set.fold (fun nv set -> if name nv = n then Set.add nv set else set) nvset Set.empty let packages_of_names nvset nameset = Name.Set.fold (fun name acc -> Set.union acc (packages_of_name nvset name)) nameset Set.empty let versions_of_name packages n = versions_of_packages (Set.filter (fun nv -> name nv = n) packages) let unknown name version = match version with | None -> OpamGlobals.error_and_exit "%S is not a valid package." (Name.to_string name) | Some v -> OpamGlobals.error_and_exit "The package %S has no version %s." (Name.to_string name) (Version.to_string v) let unavailable name version = match version with | None -> OpamGlobals.error_and_exit "%S is not available for your compiler or your OS." (Name.to_string name) | Some v -> OpamGlobals.error_and_exit "Version %s of %S is not available for your compiler or your OS." (Version.to_string v) (Name.to_string name) let unavailable_because_pinned name = function | None -> OpamGlobals.error_and_exit "%S is not available because the package is pinned." (Name.to_string name) | Some v -> OpamGlobals.error_and_exit "Version %s of %S is not available because the package is pinned." (Version.to_string v) (Name.to_string name) module Graph = struct module Vertex = struct include O let equal x y = compare x y = 0 let hash = Hashtbl.hash end module PG = Graph.Imperative.Digraph.ConcreteBidirectional (Vertex) module Topological = Graph.Topological.Make (PG) module Traverse = Graph.Traverse.Dfs(PG) module Components = Graph.Components.Make(PG) module Parallel = OpamParallel.Make(struct let string_of_vertex = to_string include PG include Topological include Traverse include Components end) end module Parallel = Graph.Parallel opam-1.1.1/src/core/opamVersion.mli0000644000175000017500000000275012272210733015441 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) (** OPAM versions *) include OpamMisc.ABSTRACT (** The current OPAM version *) val current: t (** The 'git' version of OPAM *) val git: t option (** The full version (current + git) *) val full: t (** Magic string *) val magic: string (** Display the version message *) val message: unit -> unit (** Version comparison *) val compare: t -> t -> int opam-1.1.1/src/core/opamFilter.mli0000644000175000017500000000425112272210733015237 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) (** Manage filters *) open OpamTypes (** Pretty-print *) val to_string: filter -> string (** Type of filter environment. *) type env = full_variable -> variable_contents option (** Return the contents of a variable. Return [None] if the variable is not defined in the given environment. *) val contents_of_variable: env -> full_variable -> variable_contents option (** Return the contents of a variable. Fail if an exception if the variable is not defined in the given environment. *) val contents_of_variable_exn: env -> full_variable -> variable_contents (** Substitute a string. *) val substitute_string: env -> string -> string (** Substitute a file. *) val substitute_file: env -> basename -> unit (** Evaluate a filter. *) val eval: env -> filter -> bool (** Evaluate an optional filter. *) val eval_opt: env -> filter option -> bool (** Filter a list of commands by: - evaluating the substitution strings; and - removing the commands with a filter evaluating to "false" *) val commands: env -> command list -> string list list opam-1.1.1/src/core/opamRepository.mli0000644000175000017500000001234012272210733016167 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) (** Mangagement of OPAM repositories. *) open OpamTypes include OpamMisc.ABSTRACT with type t := repository exception Unknown_backend (** Default repository address*) val default_address: address (** Pretty-print *) val to_string: repository -> string (** Compare repositories *) val compare: repository -> repository -> int (** Default repository *) val default: unit -> repository (** Create a local repository on a given path *) val local: dirname -> repository (** Get the list of packages *) val packages: repository -> package_set (** Get the list of packages (and their eventual prefixes) *) val packages_with_prefixes: repository -> string option package_map (** Get the list of all compiler *) val compilers: repository -> compiler_set (** Get the list of compilers (and their eventual prefixes) *) val compilers_with_prefixes: repository -> string option compiler_map (** {2 Repository Collection Operations } *) (** Sort a collection of repositories by priority *) val sort: repository repository_name_map -> repository list (** Generate a package index from a collection of repositories *) val package_index: repository repository_name_map -> (repository_name * string option) package_map (** Generate a compiler index from a collection of repositories *) val compiler_index: repository repository_name_map -> (repository_name * string option) compiler_map (** {2 State} *) (** Get the meaningful checksum off an url file *) val url_checksum: OpamFilename.t -> checksums (** Get all the package files *) val package_files: repository -> string option -> package -> archive:bool -> filename list (** Compute a package state (ie. a list of checksums). *) val package_state: repository -> string option -> package -> [`all|`partial of bool] -> checksums (** Get all the compiler files *) val compiler_files: repository -> string option -> compiler -> filename list (** Compute a compiler state (ie. a list of checksums). *) val compiler_state: repository -> string option -> compiler -> checksums (** {2 Repository backends} *) (** Initialize {i $opam/repo/$repo} *) val init: repository -> unit (** Update {i $opam/repo/$repo}. *) val update: repository -> unit (** Backend signature *) module type BACKEND = sig (** [pull_url package local_dir checksum remote_url] pull the contents of [remote_url] into [local_dir]. Can return either a file or a directory. [checksum] is the optional expected checksum. *) val pull_url: package -> dirname -> string option -> address -> generic_file download (** [pull_repo] pull the contents of a repository. *) val pull_repo: repository -> unit (** [pull_archive repo archive] pull [archive] in the given repository. *) val pull_archive: repository -> filename -> filename download (** Return the (optional) revision of a given repository. Only useful for VCS backends. *) val revision: repository -> version option end (** Download an url *) val pull_url: repository_kind -> package -> dirname -> string option -> address -> generic_file download (** Pull and fix the resulting digest *) val pull_url_and_fix_digest: repository_kind -> package -> dirname -> string -> filename -> address -> generic_file download (** [check_digest file expected] check that the [file] digest is the one [expected]. *) val check_digest: filename -> string option -> unit (** Pull an archive in a repository *) val pull_archive: repository -> package -> filename download (** Get the optional revision associated to a backend. *) val revision: repository -> version option (** [make_archive ?gener_digest repo prefix package] builds the archive for the given [package]. By default, the digest that appears in {i $NAME.$VERSION/url} is not modified, unless [gener_digest] is set. *) val make_archive: ?gener_digest:bool -> repository -> string option -> package -> unit (** Register a repository backend *) val register_backend: repository_kind -> (module BACKEND) -> unit (** Find a backend *) val find_backend: repository_kind -> (module BACKEND) (** {2 Misc} *) (** Parallel iterations *) module Parallel: OpamParallel.SIG with type G.V.t = repository opam-1.1.1/src/core/opamGlobals.ml0000644000175000017500000002054312272210733015226 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) (* Convention: all the global OPAM variables can be set using environment variables using OPAM *) let check var = ref ( try OpamMisc.getenv ("OPAM"^var) <> "" with Not_found -> false ) let debug = check "DEBUG" let verbose = check "VERBOSE" let color_tri_state = try (match OpamMisc.getenv "OPAMCOLOR" with | "always" -> `Always | "never" -> `Never | _ -> `Auto ) with | Not_found -> `Auto let color = ref (color_tri_state = `Always) let keep_build_dir = check "KEEPBUILDDIR" let no_base_packages = check "NOBASEPACKAGES" let no_checksums = check "NOCHECKSUMS" let yes = check "YES" let strict = check "STRICT" let build_test = check "BUILDTEST" let build_doc = check "BUILDDOC" let dryrun = check "DRYRUN" let fake = check "FAKE" let print_stats = check "STATS" let utf8_msgs = check "UTF8MSGS" let autoremove = check "AUTOREMOVE" let do_not_copy_files = check "DONOTCOPYFILES" let sync_archives = check "SYNCARCHIVES" let compat_mode_1_0 = check "COMPATMODE_1_0" let use_external_solver = ref (not !(check "NOASPCUD")) let curl_command = try Some (OpamMisc.getenv "OPAMCURL") with Not_found -> None let jobs = ref ( try Some (int_of_string (OpamMisc.getenv "OPAMJOBS")) with _ -> None ) let download_retry = try max 1 (int_of_string (OpamMisc.getenv "OPAMRETRY")) with _ -> 10 let cudf_file = ref ( try Some (OpamMisc.getenv "OPAMCUDFFILE") with _ -> None ) let solver_timeout = try float_of_string (OpamMisc.getenv "OPAMSOLVERTIMEOUT") with _ -> 5. let aspcud_criteria = try OpamMisc.strip (OpamMisc.getenv "OPAMCRITERIA") with _ -> "-removed,-notuptodate,-new" let default_repository_name = "default" let default_repository_address = "https://opam.ocaml.org" let default_build_command = [ [ "./build.sh" ] ] let global_config = "global-config" let system = "system" let switch: [`Env of string | `Command_line of string | `Not_set ] ref = ref ( try `Env (OpamMisc.getenv "OPAMSWITCH") with _ -> `Not_set ) let external_tags = ref ([] : string list) let home = try OpamMisc.getenv "HOME" with _ -> Sys.getcwd () let default_opam_dir = Filename.concat home ".opam" let root_dir = ref ( try OpamMisc.getenv "OPAMROOT" with _ -> default_opam_dir ) let timer () = if !debug then let t = Sys.time () in fun () -> Sys.time () -. t else fun () -> 0. (* For forked process, we want to get the time since the beginning of the parent process. *) let global_start_time = Unix.gettimeofday () type text_style = [ `bold | `underline | `black | `red | `green | `yellow | `blue | `magenta | `cyan | `white ] (* not nestable *) let colorise (c: text_style) s = if not !color then s else let code = match c with | `bold -> "01" | `underline -> "04" | `black -> "30" | `red -> "31" | `green -> "32" | `yellow -> "33" | `blue -> "1;34" | `magenta -> "35" | `cyan -> "36" | `white -> "37" in Printf.sprintf "\027[%sm%s\027[m" code s let indent_left str n = if String.length str >= n then str else let nstr = String.make n ' ' in String.blit str 0 nstr 0 (String.length str); nstr let acolor_with_width width c oc s = let str = colorise c s in output_string oc str; match width with | None -> () | Some w -> if String.length str >= w then () else output_string oc (String.make (w-String.length str) ' ') let acolor c oc s = acolor_with_width None c oc s let acolor_w width c oc s = acolor_with_width (Some width) c oc s let timestamp () = let time = Unix.gettimeofday () -. global_start_time in let tm = Unix.gmtime time in let msec = time -. (floor time) in Printf.ksprintf (colorise `blue) "%.2d:%.2d.%.3d" (tm.Unix.tm_hour * 60 + tm.Unix.tm_min) tm.Unix.tm_sec (int_of_float (1000.0 *. msec)) let log section fmt = Printf.ksprintf (fun str -> if !debug then Printf.eprintf "%s %06d %a %s\n%!" (timestamp ()) (Unix.getpid ()) (acolor_w 30 `yellow) section str ) fmt let error fmt = Printf.ksprintf (fun str -> Printf.eprintf "%a %s\n%!" (acolor `red) "[ERROR]" str ) fmt let warning fmt = Printf.ksprintf (fun str -> Printf.eprintf "%a %s\n%!" (acolor `yellow) "[WARNING]" str ) fmt let note fmt = Printf.ksprintf (fun str -> Printf.eprintf "%a %s\n%!" (acolor `blue) "[NOTE]" str ) fmt exception Exit of int exception Package_error of string let error_and_exit fmt = Printf.ksprintf (fun str -> error "%s" str; raise (Exit 66) ) fmt let display_messages = ref true let msg fmt = Printf.ksprintf (fun str -> flush stderr; if !display_messages then ( print_string str; flush stdout; ) ) fmt let header_msg fmt = let markl, markr = match !utf8_msgs with | true -> colorise `yellow "\xF0\x9F\x90\xAB " (* UTF-8 *), "" | false -> let mark = colorise `cyan "=-=-=" in mark, mark in Printf.ksprintf (fun str -> flush stderr; if !display_messages then ( print_char '\n'; print_string markl; print_char ' '; print_string (colorise `bold str); print_char ' '; print_string markr; print_char '\n'; flush stdout; ) ) fmt let header_error fmt = let mark = colorise `red "=====" in Printf.ksprintf (fun head fmt -> Printf.ksprintf (fun contents -> output_char stderr '\n'; output_string stderr mark; output_char stderr ' '; output_string stderr (colorise `bold "ERROR"); output_char stderr ' '; output_string stderr (colorise `bold head); output_char stderr ' '; output_string stderr mark; output_char stderr '\n'; output_string stderr contents; output_char stderr '\n'; flush stderr; ) fmt ) fmt type os = | Darwin | Linux | FreeBSD | OpenBSD | NetBSD | DragonFly | Cygwin | Win32 | Unix | Other of string let osref = ref None let os () = match !osref with | None -> let os = match Sys.os_type with | "Unix" -> begin match OpamMisc.uname_s () with | Some "Darwin" -> Darwin | Some "Linux" -> Linux | Some "FreeBSD" -> FreeBSD | Some "OpenBSD" -> OpenBSD | Some "NetBSD" -> NetBSD | Some "DragonFly" -> DragonFly | _ -> Unix end | "Win32" -> Win32 | "Cygwin" -> Cygwin | s -> Other s in osref := Some os; os | Some os -> os let string_of_os = function | Darwin -> "darwin" | Linux -> "linux" | FreeBSD -> "freebsd" | OpenBSD -> "openbsd" | NetBSD -> "netbsd" | DragonFly -> "dragonfly" | Cygwin -> "cygwin" | Win32 -> "win32" | Unix -> "unix" | Other x -> x let os_string () = string_of_os (os ()) let makecmd = ref (fun () -> match os () with | FreeBSD | OpenBSD | NetBSD | DragonFly -> "gmake" | _ -> "make" ) let log_limit = 10 let log_line_limit = 5 * 80 let default_jobs = 1 let exit i = raise (Exit i) opam-1.1.1/src/core/opamFormat.mli0000644000175000017500000001667212272210733015254 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) (** Format of OPAM configuration files. *) open OpamTypes (** The empty file *) val empty : file (** map a file *) val map: (string -> value -> (string * value) option) -> file -> file (** Get all the variable definitions from a list of items *) val variables : file_item list -> (string * value) list (** Get all the sections from a list of items *) val sections : file_item list -> (string * file_section) list (** Check whether a list of items contains only valid variable definitions *) val is_valid : file_item list -> string list -> bool (** Find all the invalid fields *) val invalid_fields : file_item list -> string list -> string list (** {2 Parsing functions} *) (** All the following parsing function raise [Bad_format] in case the input does not have the right format. *) exception Bad_format of string (** Raise [Bad_format]. *) val bad_format: ('a, unit, string, 'b) format4 -> 'a (** Parse a boolean *) val parse_bool : value -> bool (** Parse an integer *) val parse_int: value -> int (** Parse an ident *) val parse_ident : value -> string (** Parse a symbol *) val parse_symbol : value -> string (** Parse a string *) val parse_string : value -> string (** Parse a list of 'things' *) val parse_list : (value -> 'a) -> value -> 'a list (** Parse a list of list of 'things' *) val parse_list_list: (value -> 'a) -> value -> 'a list (** Parse a group of 'things' *) val parse_group : (value -> 'a) -> value -> 'a list (** Parse a value and its option of 'things' *) val parse_option : (value -> 'a) -> (value list -> 'b) -> value -> 'a * 'b option (** Parse a value and a single optional value *) val parse_single_option : (value -> 'a) -> (value -> 'b) -> value -> 'a * 'b option (** Parse a string with an optional argument *) val parse_string_option : (value list -> 'a) -> value -> string * 'a option (** Parse a list of strings *) val parse_string_list : value -> string list (** Parse a single string *) val parse_single_string: value list -> string (** Parse a pair of strings *) val parse_pair: (value -> 'a) -> (value -> 'b) -> value -> 'a * 'b (** Try to parse the value using function from the list. All the parsing functions are tried until one succeeds. The first argument is a debug message. *) val parse_or: (string * (value -> 'a)) list -> value -> 'a (** Parse a sequence of values *) val parse_sequence: (string * (value -> 'a)) list -> value -> 'a list (** {2 Creation functions} *) (** Create a boolean *) val make_bool : bool -> value (** Create an integer *) val make_int: int -> value (** Create an ident *) val make_ident : string -> value (** Create a symbol *) val make_symbol : string -> value (** Create a string *) val make_string : string -> value (** Create a list of 'things' *) val make_list : ('a -> value) -> 'a list -> value (** Create a list of strings *) val make_string_list: string list -> value (** Create a group of 'things' *) val make_group : ('a -> value) -> 'a list -> value (** Create a value and its optional arguments *) val make_option : ('a -> value) -> ('b -> value list) -> ('a * 'b option) -> value (** Create a pair *) val make_pair: ('a -> value) -> ('b -> value) -> ('a * 'b) -> value (** Create a pair of strings *) val make_string_pair: string * string -> value (** {2 Printing functions} *) (** Print a value *) val string_of_value : value -> string (** Print a list of values *) val string_of_values : value list -> string (** Print a file *) val string_of_file: simplify:bool -> indent:bool -> ?ignore:(string list) -> file -> string (** {2 Finding functions} *) (** Get the value of a field *) val assoc : file_item list -> string -> (value -> 'a) -> 'a (** Get the value of a field. If the field does not exist, return None *) val assoc_option : file_item list -> string -> (value -> 'a) -> 'a option (** Get the value of a field. If the variable does not exist, return a default value *) val assoc_default : 'a -> file_item list -> string -> (value -> 'a) -> 'a (** Get the value associated to a variable. If the variable does not exists, return [] *) val assoc_list : file_item list -> string -> (value -> 'a list) -> 'a list (** Get the string list associated to a variable. If the variable does not exist, return [] *) val assoc_string_list : file_item list -> string -> string list (** Get one section of a certain kind *) val get_section_by_kind : file_item list -> string -> file_section (** Get all the sections of a certain kind *) val get_all_section_by_kind : file_item list -> string -> file_section list (** Get sections *) val assoc_sections: file_item list -> string -> (file_section -> 'a) -> 'a list (** {2 Formula} *) (** This section is dedicated to the parsing and creatin of dependency and conflict formaulas. It's maybe easier to do that directly in the parser ... *) open OpamTypes (** Parse package formula where AND are implicit: [x y -> x & y] *) val parse_formula : value -> formula (** Build a formula where AND are implicit. *) val make_formula : formula -> value (** Parse optional package formula where OR are implicit: [x y -> x | y] *) val parse_opt_formula : value -> formula (** Build a formula where OR are implicit. *) val make_opt_formula : formula -> value (** Parse compiler constraints *) val parse_compiler_constraint: value -> compiler_constraint (** Build a compiler constraint *) val make_compiler_constraint: compiler_constraint -> value (** Parse an OS constraint *) val parse_os_constraint: value -> (bool * string) generic_formula (** Build an OS constraint *) val make_os_constraint: (bool * string) generic_formula -> value (** {2 Environment variables} *) (** Parsing *) val parse_env_variable: value -> (string * string * string) (** Making *) val make_env_variable: (string * string * string) -> value (** {2 filter expressions} *) (** Parsing *) val parse_filter: value list -> filter (** Creation *) val make_filter: filter -> value list (** Parse a command *) val parse_command: value -> command (** Create a command *) val make_command: command -> value (** Parse a list of commands *) val parse_commands: value -> command list (** Create a list of commands *) val make_commands: command list -> value (** Parse a list of commands *) val parse_messages: value -> (string * filter option) list (** {2 Tags} *) (** Parse tags *) val parse_tags: value -> tags (** Make tags *) val make_tags: tags -> value opam-1.1.1/src/core/opamParser.mly0000644000175000017500000000535512272210733015274 0ustar i33173i33173/**************************************************************************/ /* */ /* Copyright 2012-2013 OCamlPro */ /* Copyright 2012 INRIA */ /* */ /* All rights reserved.This file is distributed under the terms of the */ /* GNU Lesser General Public License version 3.0 with linking */ /* exception. */ /* */ /* OPAM 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 General Public */ /* License for more details. */ /* */ /**************************************************************************/ %{ open OpamTypes %} %token STRING IDENT SYMBOL %token BOOL %token EOF %token LBRACKET RBRACKET %token LPAR RPAR %token LBRACE RBRACE %token COLON %token INT %left LPAR RPAR %left LBRACE RBRACE %left LBRACKET RBRACKET %left STRING IDENT BOOL SYMBOL %left COLON %start main value %type OpamTypes.file> main %type value %% main: | items EOF { fun file_name -> { file_contents = $1; file_name; file_format = OpamVersion.current } } ; items: | item items { $1 :: $2 } | { [] } ; item: | IDENT COLON value { Variable ($1, $3) } | IDENT STRING LBRACE items RBRACE { Section {section_kind=$1; section_name=$2; section_items= $4} } ; value: | BOOL { Bool $1 } | INT { Int $1 } | STRING { String $1 } | SYMBOL { Symbol $1 } | IDENT { Ident $1 } | LPAR values RPAR { Group $2 } | LBRACKET values RBRACKET { List $2 } | value LBRACE values RBRACE { Option ($1, $3) } ; values: | { [] } | value values { $1 :: $2 } ; %% let error lexbuf exn msg = let curr = lexbuf.Lexing.lex_curr_p in let start = lexbuf.Lexing.lex_start_p in OpamGlobals.error "File %S, line %d, character %d-%d: %s." curr.Lexing.pos_fname start.Lexing.pos_lnum (start.Lexing.pos_cnum - start.Lexing.pos_bol) (curr.Lexing.pos_cnum - curr.Lexing.pos_bol) msg; raise exn let main t l f = try main t l f with | Lexer_error msg as e -> error l e msg | Parsing.Parse_error as e -> error l e "parse error" opam-1.1.1/src/core/opamRepositoryName.ml0000644000175000017500000000232712272210733016623 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) include OpamMisc.Base let default = of_string OpamGlobals.default_repository_name opam-1.1.1/src/core/opamSystem.mli0000644000175000017500000001503612272210733015301 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) (** Low-level untyped system operations *) (** Exception raised when subprocess fails *) exception Process_error of OpamProcess.result (** raise [Process_error] *) val process_error: OpamProcess.result -> 'a (** Exception raised when a computation in the current process fails. *) exception Internal_error of string (** Raise [Internal_error] *) val internal_error: ('a, unit, string, 'b) format4 -> 'a (** [with_tmp_dir fn] executes [fn] in a tempory directory *) val with_tmp_dir: (string -> 'a) -> 'a (** [copy src dst] copies [src] to [dst]. Remove [dst] before the copy if it is a link. *) val copy: string -> string -> unit (** [link src dst] links [src] to [dst]. Remove [dst] if it is a file, not a directory. *) val link: string -> string -> unit (** [real_path p] returns the real path associated to [p]: [..] are expanded and relative paths become absolute. *) val real_path: string -> string (** Return the contents of a channel. *) val string_of_channel: in_channel -> string (** [read filename] returns the contents of [filename] *) val read: string -> string (** [write filename contents] write [contents] to [filename] *) val write: string -> string -> unit (** [remove filename] removes [filename]. Works whether [filename] is a file or a directory *) val remove: string -> unit (** [remove_file filename] removes [filename]. Works only for normal files (or also at least for symlinks) *) val remove_file: string -> unit (** [remove_dir filename] removes [filename]. Works only for directory (not for symlinks or other files). *) val remove_dir: string -> unit (** Change the current working directory *) val chdir: string -> unit (** [in_dir dir fn] evaluates [fn] in the directory [dir] *) val in_dir: string -> (unit -> 'a) -> 'a (** [files_with_links dir] returns the files in the directory [dir]. Links simulating directory are ignored, others links are returned. *) val files_with_links: string -> string list (** [rec_files dir] returns the list of all files in [dir], recursively. Links behaving like directory are crossed. *) val rec_files: string -> string list (** Return the list of files in the current directory. *) val files: string -> string list (** [rec_dirs dir] return the list list of all directories recursively (going through symbolink links). *) val rec_dirs: string -> string list (** Return the list of directories in the current directory. *) val dirs: string -> string list (** Return the version of the current OCaml compiler. If no OCaml compiler is present in the path, then it returns [None]. *) val ocaml_version: string option Lazy.t (** Return the path where the system ocamlc library is installed *) val system_ocamlc_where: string option Lazy.t (** Return the version of the system compiler *) val system_ocamlc_version: string option Lazy.t (** [directories_with_links dir] returns the directories in the directory [dir]. Links pointing to directory are also returned. *) val directories_with_links: string -> string list (** a command is a list of words *) type command = string list (** Test wether a command exists in the environment. *) val command_exists: ?env:string array -> string -> bool (** [command cmd] executes the command [cmd] in the correct OPAM environment. *) val command: ?verbose:bool -> ?env:string array -> ?name:string -> ?metadata:(string * string) list -> command -> unit (** [commands cmds] executes the commands [cmds] in the correct OPAM environment. It stops whenever one command fails unless [keep_going] is set to [true]. In this case, the first error is re-raised at the end. *) val commands: ?verbose:bool -> ?env:string array -> ?name:string -> ?metadata:(string * string) list -> ?keep_going:bool -> command list -> unit (** [read_command_output cmd] executes the command [cmd] in the correct OPAM environment and return the lines from stdout if the command exists normally. If the command does not exist or if the command exited with a non-empty exit-code, throw an error. *) val read_command_output: ?verbose:bool -> ?env:string array -> ?metadata:(string * string) list -> command -> string list (** Test whether the file is an archive, by looking as its extension *) val is_tar_archive: string -> bool (** [extract filename dirname] extracts the archive [filename] into [dirname]. [dirname] should not exists and [filename] should contain only one top-level directory.*) val extract: string -> string -> unit (** [extract_in filename dirname] extracts the archive [filename] into [dirname]. [dirname] should already exists. *) val extract_in: string -> string -> unit (** Create a directory. Do not fail if the directory already exist. *) val mkdir: string -> unit (** {2 File locking function} *) (** [flock ()] takes the global file lock. If the lock is already taken, sleep for 1s and then retry. Abort after 5 tentatives. *) val flock: string -> unit (** [funlock ()] unlocks the global file lock. Work only if the current processus is the same as the one who took the lock at the first place. *) val funlock: string -> unit (** {2 Misc} *) (** download compiler sources *) val download: overwrite:bool -> filename:string -> dst:string -> string (** Apply a patch file in the current directory. *) val patch: string -> unit (** Create a tempory file in {i ~/.opam/logs/XXX} *) val temp_file: ?dir:string -> string -> string (** Print stats *) val print_stats: unit -> unit opam-1.1.1/src/core/opamLineLexer.mll0000644000175000017500000000323312272210733015703 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) { let get_words words = function | [] -> words | wchars -> String.concat "" (List.rev wchars) :: words } let normalchar = [^' ' '\t' '\n' '\\'] rule main wchars words lines = parse | '\n' { main [] [] (List.rev (get_words words wchars) :: lines) lexbuf } | [' ' '\t']+ { main [] (get_words words wchars) lines lexbuf } | '\\' (_ normalchar* as w) | (normalchar+ as w) { main (w::wchars) words lines lexbuf } | _ { assert false } | eof { List.rev (List.rev words :: lines) } { let main = main [] [] [] } opam-1.1.1/src/core/opamSwitch.ml0000644000175000017500000000247312272210733015106 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) include OpamMisc.Base let default = of_string OpamGlobals.system let not_installed s = OpamGlobals.error_and_exit "The compiler switch %s is not installed." (to_string s) opam-1.1.1/src/core/opamFormula.mli0000644000175000017500000001115412272210733015417 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) (** Management of formulas *) (** binary operations *) type relop = [`Eq|`Neq|`Geq|`Gt|`Leq|`Lt] (** Pretty-printing of relops *) val string_of_relop: relop -> string (** Parsing relops *) val relop_of_string: string -> relop (** Version constraints for OPAM *) type version_constraint = relop * OpamPackage.Version.t (** Formula atoms for OPAM *) type atom = OpamPackage.Name.t * version_constraint option (** Pretty-printing of atoms *) val string_of_atom: atom -> string (** AND formulas *) type 'a conjunction = 'a list (** Pretty print AND formulas *) val string_of_conjunction: ('a -> string) -> 'a conjunction -> string (** OR formulas *) type 'a disjunction = 'a list (** Pretty print OR formulas *) val string_of_disjunction: ('a -> string) -> 'a disjunction -> string (** CNF formulas (Conjunctive Normal Form) *) type 'a cnf = 'a disjunction conjunction (** DNF formulas (Disjunctive Normal Form) *) type 'a dnf = 'a conjunction disjunction (** Pretty print CNF formulas *) val string_of_cnf: ('a -> string) -> 'a cnf -> string (** Pretty print DNF formulas *) val string_of_dnf: ('a -> string) -> 'a dnf -> string (** General formulas *) type 'a formula = | Empty | Atom of 'a | Block of 'a formula | And of 'a formula * 'a formula | Or of 'a formula * 'a formula (** Eval a formula *) val eval: ('a -> bool) -> 'a formula -> bool (** Check a relational operator against an integer from compare *) val check_relop: relop -> int -> bool (** Evaluate a relational operator between versions *) val eval_relop: relop -> OpamPackage.Version.t -> OpamPackage.Version.t -> bool (** Pretty print a formula *) val string_of_formula: ('a -> string) -> 'a formula -> string (** Convert a list of formulas to an AND-formula *) val ands: 'a formula list -> 'a formula (** Convert a list of formulas to an OR-formula *) val ors: 'a formula list -> 'a formula (** Map function *) val map: ('a -> 'b formula) -> 'a formula -> 'b formula (** Iter function *) val iter: ('a -> unit) -> 'a formula -> unit (** Fold function *) val fold_left: ('a -> 'b -> 'a) -> 'a -> 'b formula -> 'a (** Expressions composed entirely of version constraints *) type version_formula = version_constraint formula (** An atom is: [name] * ([relop] * [version]) formula. Examples of valid formulae: - "foo" \{> "1" & (<"3" | ="5")\} - "foo" \{= "1" | > "4"\} | ("bar" "bouh") *) type t = (OpamPackage.Name.t * version_formula) formula (** Convert a formula to CNF *) val cnf_of_formula: 'a formula -> 'a formula (** Convert a formula to DNF *) val dnf_of_formula: 'a formula -> 'a formula (** Transform a formula where versions can be expressed using formulas to a flat atom formula *) val to_atom_formula: t -> atom formula (** Convert an atom-formula to a t-formula *) val of_atom_formula: atom formula -> t (** {2 Atoms} *) (** Return all the atoms *) val atoms: t -> atom list (** Pretty print the formula *) val to_string: t -> string (** Return a conjunction. If the initial formula is not a conjunction, then fail. *) val to_conjunction: t -> atom conjunction (** Return a formula from a conjunction of atoms *) val of_conjunction: atom conjunction -> t (** Return a disjunction. It the initial formula is not a disjunction, then fail. *) val to_disjunction: t -> atom disjunction (** Return a formula from a disjunction of atoms *) val of_disjunction: atom disjunction -> t (** Return an equivalent CNF formula *) val to_cnf: t -> atom cnf (** Return an equivalent DNF formula *) val to_dnf: t -> atom dnf opam-1.1.1/src/core/opamMisc.ml0000644000175000017500000002603512272210733014540 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) module type SET = sig include Set.S val map: (elt -> elt) -> t -> t val choose_one : t -> elt val of_list: elt list -> t val to_string: t -> string val to_json: t -> OpamJson.t val find: (elt -> bool) -> t -> elt end module type MAP = sig include Map.S val to_string: ('a -> string) -> 'a t -> string val to_json: ('a -> OpamJson.t) -> 'a t -> OpamJson.t val values: 'a t -> 'a list val keys: 'a t -> key list val union: ('a -> 'a -> 'a) -> 'a t -> 'a t -> 'a t val of_list: (key * 'a) list -> 'a t end module type ABSTRACT = sig type t val of_string: string -> t val to_string: t -> string val to_json: t -> OpamJson.t module Set: SET with type elt = t module Map: MAP with type key = t end module type OrderedType = sig include Set.OrderedType val to_string: t -> string val to_json: t -> OpamJson.t end let debug = ref false let string_of_list f = function | [] -> "{}" | l -> let buf = Buffer.create 1024 in let n = List.length l in let i = ref 0 in Buffer.add_string buf "{ "; List.iter (fun x -> incr i; Buffer.add_string buf (f x); if !i <> n then Buffer.add_string buf ", "; ) l; Buffer.add_string buf " }"; Buffer.contents buf let rec pretty_list = function | [] -> "" | [a] -> a | [a;b] -> Printf.sprintf "%s and %s" a b | h::t -> Printf.sprintf "%s, %s" h (pretty_list t) let max_print = 100 module Set = struct module Make (O : OrderedType) = struct module S = Set.Make(O) include S let fold f set i = let r = ref i in S.iter (fun elt -> r := f elt !r ) set; !r let choose_one s = match elements s with | [x] -> x | [] -> raise Not_found | _ -> invalid_arg "choose_one" let of_list l = List.fold_left (fun set e -> add e set) empty l let to_string s = if not !debug && S.cardinal s > max_print then Printf.sprintf "%d elements" (S.cardinal s) else let l = S.fold (fun nv l -> O.to_string nv :: l) s [] in string_of_list (fun x -> x) (List.rev l) let map f t = S.fold (fun e set -> S.add (f e) set) t S.empty let find fn s = choose (filter fn s) let to_json t = let elements = S.elements t in let jsons = List.map O.to_json elements in `A jsons end end module Map = struct module Make (O : OrderedType) = struct module M = Map.Make(O) include M let fold f map i = let r = ref i in M.iter (fun key value-> r:= f key value !r ) map; !r let map f map = fold (fun key value map -> add key (f value) map ) map empty let mapi f map = fold (fun key value map -> add key (f key value) map ) map empty let values map = List.rev (M.fold (fun _ v acc -> v :: acc) map []) let keys map = List.rev (M.fold (fun k _ acc -> k :: acc) map []) let union f m1 m2 = M.fold (fun k v m -> if M.mem k m then M.add k (f v (M.find k m)) (M.remove k m) else M.add k v m ) m1 m2 let to_string string_of_value m = if not !debug && M.cardinal m > max_print then Printf.sprintf "%d elements" (M.cardinal m) else let s (k,v) = Printf.sprintf "%s:%s" (O.to_string k) (string_of_value v) in let l = fold (fun k v l -> s (k,v)::l) m [] in string_of_list (fun x -> x) l let of_list l = List.fold_left (fun map (k,v) -> add k v map) empty l let to_json json_of_value t = let bindings = M.bindings t in let jsons = List.map (fun (k,v) -> `O [ ("key" , O.to_json k); ("value", json_of_value v) ] ) bindings in `A jsons end end module Base = struct type t = string let of_string x = x let to_string x = x let to_json x = `String x module O = struct type t = string let to_string = to_string let compare = compare let to_json = to_json end module Set = Set.Make(O) module Map = Map.Make(O) end let filter_map f l = let rec loop accu = function | [] -> List.rev accu | h :: t -> match f h with | None -> loop accu t | Some x -> loop (x::accu) t in loop [] l module OInt = struct type t = int let compare = compare let to_string = string_of_int let to_json i = `String (string_of_int i) end module IntMap = Map.Make(OInt) module IntSet = Set.Make(OInt) module OString = struct type t = string let compare = compare let to_string x = x let to_json x = `String x end module StringSet = Set.Make(OString) module StringMap = Map.Make(OString) module StringSetSet = Set.Make(StringSet) module StringSetMap = Map.Make(StringSet) module OP = struct let (|>) f g = g f let (++) f g x = g (f x) let finally f clean = let safe_clean () = try clean () with _ -> () in let result = try f () with e -> safe_clean (); raise e in safe_clean (); result end let strip str = let p = ref 0 in let l = String.length str in let fn = function | ' ' | '\t' | '\r' | '\n' -> true | _ -> false in while !p < l && fn (String.unsafe_get str !p) do incr p; done; let p = !p in let l = ref (l - 1) in while !l >= p && fn (String.unsafe_get str !l) do decr l; done; String.sub str p (!l - p + 1) let starts_with ~prefix s = let x = String.length prefix in let n = String.length s in n >= x && String.sub s 0 x = prefix let ends_with ~suffix s = let x = String.length suffix in let n = String.length s in n >= x && String.sub s (n - x) x = suffix let remove_prefix ~prefix s = if starts_with ~prefix s then let x = String.length prefix in let n = String.length s in String.sub s x (n - x) else s let remove_suffix ~suffix s = if ends_with ~suffix s then let x = String.length suffix in let n = String.length s in String.sub s 0 (n - x) else s let cut_at_aux fn s sep = try let i = fn s sep in let name = String.sub s 0 i in let version = String.sub s (i+1) (String.length s - i - 1) in Some (name, version) with _ -> None let cut_at = cut_at_aux String.index let rcut_at = cut_at_aux String.rindex let contains s c = try let _ = String.index s c in true with Not_found -> false let split s c = Re_str.split (Re_str.regexp (Printf.sprintf "[%c]" c)) s let split_delim s c = Re_str.split_delim (Re_str.regexp (Printf.sprintf "[%c]" c)) s (* Remove from a ':' separated list of string the one with the given prefix *) let reset_env_value ~prefix v = let v = split_delim v ':' in List.filter (fun v -> not (starts_with ~prefix v)) v (* if rsync -arv return 4 lines, this means that no files have changed *) let rsync_trim = function | [] -> [] | _ :: t -> match List.rev t with | _ :: _ :: _ :: l -> List.filter ((<>) "./") l | _ -> [] let exact_match re s = try let subs = Re.exec re s in let subs = Array.to_list (Re.get_all_ofs subs) in let n = String.length s in let subs = List.filter (fun (s,e) -> s=0 && e=n) subs in List.length subs > 0 with Not_found -> false (* XXX: not optimized *) let insert comp x l = let rec aux = function | [] -> [x] | h::t when comp h x < 0 -> h::aux t | l -> x :: l in aux l let env = lazy ( let e = Unix.environment () in List.rev_map (fun s -> match cut_at s '=' with | None -> s, "" | Some p -> p ) (Array.to_list e) ) let getenv n = List.assoc n (Lazy.force env) let env () = Lazy.force env let indent_left s ?(visual=s) nb = let nb = nb - String.length visual in if nb <= 0 then s else s ^ String.make nb ' ' let indent_right s ?(visual=s) nb = let nb = nb - String.length visual in if nb <= 0 then s else String.make nb ' ' ^ s let sub_at n s = if String.length s <= n then s else String.sub s 0 n let pretty_backtrace () = match Printexc.get_backtrace () with | "" -> "" | b -> let b = String.concat "\n " (split b '\n') in Printf.sprintf "Backtrace:\n %s\n" b let default_columns = 100 let with_process_in cmd f = let ic = Unix.open_process_in cmd in try let r = f ic in ignore (Unix.close_process_in ic) ; r with exn -> ignore (Unix.close_process_in ic) ; raise exn let get_terminal_columns () = try (* terminfo *) with_process_in "tput cols" (fun ic -> int_of_string (input_line ic)) with _ -> try (* GNU stty *) with_process_in "stty size" (fun ic -> match split (input_line ic) ' ' with | [_ ; v] -> int_of_string v | _ -> failwith "stty") with _ -> try (* shell envvar *) int_of_string (getenv "COLUMNS") with _ -> default_columns let terminal_columns = let v = Lazy.lazy_from_fun get_terminal_columns in fun () -> if Unix.isatty Unix.stdout then Lazy.force v else max_int let uname_s () = try with_process_in "uname -s" (fun ic -> Some (strip (input_line ic))) with _ -> None let shell_of_string = function | "tcsh" | "csh" -> `csh | "zsh" -> `zsh | "bash" -> `bash | "fish" -> `fish | _ -> `sh let guess_shell_compat () = try shell_of_string (Filename.basename (getenv "SHELL")) with _ -> `sh let guess_dot_profile shell = let home f = try Filename.concat (getenv "HOME") f with _ -> f in match shell with | `fish -> List.fold_left Filename.concat (home ".config") ["fish"; "config.fish"] | `zsh -> home ".zshrc" | `bash -> let bash_profile = home ".bash_profile" in let bashrc = home ".bashrc" in if Sys.file_exists bash_profile then bash_profile else bashrc | _ -> home ".profile" let prettify_path s = let aux ~short ~prefix = let prefix = Filename.concat prefix "" in if starts_with ~prefix s then let suffix = remove_prefix ~prefix s in Some (Filename.concat short suffix) else None in match aux ~short:"~" ~prefix:(getenv "HOME") with | Some p -> p | None -> s opam-1.1.1/src/core/opamPath.mli0000644000175000017500000002441612272210733014713 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) (** The various paths where OPAM configuration files are stored. *) open OpamTypes (** {2 Global paths} *) (** Type of path root *) type t = dirname (** Default root path *) val root: unit -> t (** State cache *) val state_cache: t -> filename (** Update cache *) val update_cache: t -> filename (** lock file *) val lock: t -> filename (** Main configuration file: {i $opam/config} *) val config: t -> filename (** Compiler aliases *) val aliases: t -> filename (** Package directroy {i $opam/packages/} *) val packages_dir: t -> dirname (** Package sub-directory {i $opam/packages/$NAME/$NAME.$VERSION/} *) val packages: t -> package -> dirname (** OPAM files: {i $opam/packages/$NAME/$NAME.$VERSION/opam} *) val opam: t -> package -> filename (** URL files: {i $opam/packages/$NAME/$NAME.$VERSION/url} *) val url: t -> package -> filename (** Additional files: {i $opam/packages/$NAME/$NAME.$VERSION/files} *) val files: t -> package -> dirname (** Tempory folder for dev packages {i $opam/packages.dev/} *) val dev_packages_dir: t -> dirname (** Tempory folder for dev packages {i $opam/packages.dev/$NAME.$VERSION/} *) val dev_package: t -> package -> dirname (** Description file: {i $opam/packages/$NAME/$NAME.$VERSION/descr} *) val descr: t -> package -> filename (** Archives dir *) val archives_dir: t -> dirname (** Archive file: {i $opam/archives/$NAME.$VERSION+opam.tar.gz} *) val archive: t -> package -> filename (** Compiler files: {i $opam/compilers/$VERSION/$COMP.comp} *) val compiler_comp: t -> compiler -> filename (** Compiler description files: {i $opam/compilers/$VERSION/$COMP.descr} *) val compiler_descr: t -> compiler -> filename (** Compiler files: {i $opam/compilers/} *) val compilers_dir: t -> dirname (** Compiler subdir {i $opam/compilers/$VERSION/$COMP} *) val compilers: t -> compiler -> dirname (** Return the repository index: {i $opam/repo/package-index} *) val package_index: t -> filename (** Return the repository index: {i $opam/repo/compiler-index} *) val compiler_index: t -> filename (** Init scripts *) val init: t -> dirname (** Log dir {i $opam/log} *) val log: t -> dirname (** The directory where global backups are stored *) val backup_dir: t -> dirname (** Backup file for state export *) val backup: t -> filename (** Switch related paths *) module Switch: sig (** Root dir: {i $opam/$switch} *) val root: t -> switch -> dirname (** lock file: {i $opam/lock} *) val lock: t -> switch -> filename (** The directory where backups are stored for this switch *) val backup_dir: t -> switch -> dirname (** Backup file for state export *) val backup: t -> switch -> filename (** Library path for a given package: {i $opam/$switch/lib/$name} *) val lib: t -> switch -> name -> dirname (** Library path: {i $opam/$switch/lib} *) val lib_dir: t -> switch -> dirname (** DLL paths *) val stublibs: t -> switch -> dirname (** toplevel path: {i $opam/$switch/lib/toplevel} *) val toplevel: t -> switch -> dirname (** Documentation path for a given package: {i $opam/$switch/doc/$name} *) val doc: t -> switch -> name -> dirname (** Documentation path: {i $opam/$switch/doc/} *) val doc_dir: t -> switch -> dirname (** Shared directory: {i $opam/$switch/share} *) val share_dir: t -> switch -> dirname (** Share directory for a given package: {i $opam/$switch/share/$package} *) val share: t -> switch -> name -> dirname (** Etc directory: {i $opam/$switch/etc} *) val etc_dir: t -> switch -> dirname (** Etc directory for a given package: {i $opam/$switch/etc/$package} *) val etc: t -> switch -> name -> dirname (** Man pages path: {i $opam/$switch/man/}. The optional [num] argument will add a {i manN } suffix if specified *) val man_dir: ?num:string -> t -> switch -> dirname (** Installed binaries: {i $opam/$switch/bin} *) val bin: t -> switch -> dirname (** Installed system binaries: {i $opam/$switch/sbin} *) val sbin: t -> switch -> dirname (** List of installed packages with their version: {i $opam/$switch/installed} *) val installed: t -> switch -> filename (** List of packages expliciterly installed by the user: {i $opam/$switch/installed.roots} *) val installed_roots: t -> switch -> filename (** Tempory folders used to decompress and compile the corresponding archives: {i $opam/$switch/build/$packages} *) val build: t -> switch -> package -> dirname (** Tempory folders used to decompress and compile the OCaml compiler: {i $opam/$switch/build/ocaml} *) val build_ocaml: t -> switch -> dirname (** Tempory folder: {i $opam/$switch/build} *) val build_dir: t -> switch -> dirname (** Tempory location of install files: {i $opam/$switch/build/$package/$name.install} *) val build_install: t -> switch -> package -> filename (** Tempory location of config files: {i $opam/$switch/build/$packages/$name.config} *) val build_config: t -> switch -> package -> filename (** Installed files for a given package: {i $opam/$switch/install/$name.install} *) val install: t -> switch -> name -> filename (** Installed files: {i $opam/$switch/install/} *) val install_dir: t -> switch -> dirname (** Packages to reinstall on next upgrade: {i $opam/$switch/reinstall} *) val reinstall: t -> switch -> filename (** Compile and link flags for a given package: {i $opam/$switch/config/$name.config} *) val config: t -> switch -> name -> filename (** Configuration folder: {i $opam/$switch/config} *) val config_dir: t -> switch -> dirname (** Pinned package file: {i $opam/$switch/pinned} *) val pinned: t -> switch -> filename (** Build dir for all pinned packages: {i $opam/$switch/packages.dev/} *) val dev_packages_dir: t -> switch -> dirname (** Build dir for a given pinned package: {i $opam/$switch/packages.dev/$name.$version/} *) val dev_package: t -> switch -> package -> dirname module Overlay: sig (** Switch metadata overlay (over the global metadata): {i $opam/$switch/overlay/} *) val dir: t -> switch -> dirname (** Switch metadata overlay (over the global metadata): {i $opam/$switch/overlay/$name.$version} *) val package: t -> switch -> package -> dirname (** OPAM overlay: {i $opam/$switch/cache/$name.$version/opam} *) val opam: t -> switch -> package -> filename (** URL overlay: {i $opam/$switch/overlay/$name.$version/url} *) val url: t -> switch -> package -> filename (** Descr orverlay *) val descr: t -> switch -> package -> filename (** Files overlay *) val files: t -> switch -> package -> dirname end end (** Repository paths *) module Repository: sig (** Repository local path: {i $opam/repo/} *) val create: t -> repository_name -> dirname (** Update cache *) val update_cache: repository -> filename (** Return the repo file *) val repo: repository -> filename (** Remote repo file *) val remote_repo: repository -> filename (** Return the repository config: {i $opam/repo/$repo/config} *) val raw_config: dirname -> repository_name -> filename (** Return the repository config: {i $opam/repo/$repo/config} *) val config: repository -> filename (** Packages folder: {i $opam/repo/$repo/packages} *) val packages_dir: repository -> dirname (** Remote package files: {i $remote/packages} *) val remote_packages_dir: repository -> dirname (** Package folder: {i $opam/repo/$repo/packages/XXX/$NAME.$VERSION} *) val packages: repository -> string option -> package -> dirname (** Return the OPAM file for a given package: {i $opam/repo/$repo/packages/XXX/$NAME.$VERSION/opam} *) val opam: repository -> string option -> package -> filename (** Return the description file for a given package: {i $opam/repo/$repo/packages/XXX/$NAME.VERSION/descr} *) val descr: repository -> string option -> package -> filename (** urls {i $opma/repo/$repo/package/XXX/$NAME.$VERSION/url} *) val url: repository -> string option -> package -> filename (** files {i $opam/repo/$repo/packages/XXX/$NAME.$VERSION/files} *) val files: repository -> string option -> package -> dirname (** Return the archive for a given package: {i $opam/repo/$repo/archives/$NAME.$VERSION.tar.gz} *) val archive: repository -> package -> filename (** Remote archive {i $remote/archives/$NAME.$VERSION.tar.gz} *) val remote_archive: repository -> package -> filename (** Return the archive folder: {i $opam/repo/$repo/archives/} *) val archives_dir: repository -> dirname (** Return the upload folder for a given version: {i $opam/repo/$repo/upload/} *) val upload_dir: repository -> dirname (** Compiler files: {i $opam/repo/$repo/compilers/} *) val compilers_dir: repository -> dirname (** Compiler files: {i $opam/repo/$repo/compilers/XXX/$OVERSION.comp} *) val compiler_comp: repository -> string option -> compiler -> filename (** Compiler description files: {i $opam/repo/$repo/compilers/XXX/$OVERSION.descr} *) val compiler_descr: repository -> string option -> compiler -> filename (** Remote compiler files: {i $remote/compilers} *) val remote_compilers_dir: repository -> dirname end opam-1.1.1/src/core/opamMisc.mli0000644000175000017500000001544512272210733014714 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) (** Basic functions *) (** {2 Abstract types} *) (** Collection of abstract values *) module type SET = sig include Set.S (** auto-map *) val map: (elt -> elt) -> t -> t (** Return one element. Fail if the set is not a singleton. *) val choose_one : t -> elt (** Make a set from a list *) val of_list: elt list -> t (** Pretty-print a set *) val to_string: t -> string (** Return a JSON representation of the given set *) val to_json: t -> OpamJson.t (** Find an element in the list *) val find: (elt -> bool) -> t -> elt end (** Dictionaries of abstract values *) module type MAP = sig include Map.S (** Pretty-printing *) val to_string: ('a -> string) -> 'a t -> string (** Return a JSON representation of the given map. *) val to_json: ('a -> OpamJson.t) -> 'a t -> OpamJson.t (** Return the values in the map. *) val values: 'a t -> 'a list (** Return the keys in the map. *) val keys: 'a t -> key list (** A key will be in the union of [m1] and [m2] if it is appears either [m1] or [m2], with the corresponding value. If a key appears in both [m1] and [m2], then the resulting value is built using the function given as argument. *) val union: ('a -> 'a -> 'a) -> 'a t -> 'a t -> 'a t (** Convert an assoc list to a map *) val of_list: (key * 'a) list -> 'a t end (** All abstract types should implement this signature *) module type ABSTRACT = sig (** ABSTRACT type *) type t (** Create an abstract value from a string *) val of_string: string -> t (** Convert an abstract value to a string *) val to_string: t -> string (** Convert an abstract value to a JSON object *) val to_json: t -> OpamJson.t module Set: SET with type elt = t module Map: MAP with type key = t end (** Extended sets and maps *) module type OrderedType = sig include Set.OrderedType val to_string: t -> string val to_json: t -> OpamJson.t end (** Set constructor *) module Set: sig module Make (S: OrderedType): SET with type elt = S.t end (** Map constructor *) module Map: sig module Make (S: OrderedType): MAP with type key = S.t end (** Base module, useful to abstract strings *) module Base: sig type t = string val of_string: string -> t val to_string: t -> string val to_json: t -> OpamJson.t module Map: MAP with type key = string module Set: SET with type elt = string end (** {2 Integer manipulation} *) (** Map of ints *) module IntMap: MAP with type key = int (** Set of ints *) module IntSet: SET with type elt = int (** Display a list of strings *) val string_of_list: ('a -> string) -> 'a list -> string (** Display a pretty list: ["x";"y";"z"] -> "x, y and z" *) val pretty_list: string list -> string (** {2 String manipulation} *) (** Map of strings *) module StringMap: MAP with type key = string (** Set of strings *) module StringSet: SET with type elt = string (** Set of string sets *) module StringSetSet: SET with type elt = StringSet.t (** Map of string sets *) module StringSetMap: MAP with type key = StringSet.t (** Strip a string *) val strip: string -> string (** Does a string starts with the given prefix ? *) val starts_with: prefix:string -> string -> bool (** Does a string ends with the given suffix ? *) val ends_with: suffix:string -> string -> bool (** Remove a prefix *) val remove_prefix: prefix:string -> string -> string (** Remove a suffix *) val remove_suffix: suffix:string -> string -> string (** Cut a string at the first occurence of the given char *) val cut_at: string -> char -> (string * string) option (** Same as [cut_at], but starts from the right *) val rcut_at: string -> char -> (string * string) option (** Does a string contains the given chars ? *) val contains: string -> char -> bool (** Split a string *) val split: string -> char -> string list (** left indenting. [~visual] can be used to indent eg. ANSI colored strings and should correspond to the visible characters of s *) val indent_left: string -> ?visual:string -> int -> string (** right indenting *) val indent_right: string -> ?visual:string -> int -> string (** Cut a string *) val sub_at: int -> string -> string (** {2 Misc} *) (** Remove from a ':' separated list of string the one with the given prefix *) val reset_env_value: prefix:string -> string -> string list (** if rsync -arv return 4 lines, this means that no files have changed *) val rsync_trim: string list -> string list (** Exact regexp matching *) val exact_match: Re.re -> string -> bool (** Filter and map *) val filter_map: ('a -> 'b option) -> 'a list -> 'b list (** Insert a value in an ordered list *) val insert: ('a -> 'a -> int) -> 'a -> 'a list -> 'a list (** Lazy environment variable *) val getenv: string -> string (** Lazy environment *) val env: unit -> (string * string) list (** Return a pretty-printed backtrace *) val pretty_backtrace: unit -> string (** Prettify a local path (eg. replace /home/me/ by '~') *) val prettify_path: string -> string module OP: sig (** Pipe operator *) val (|>): 'a -> ('a -> 'b) -> 'b (** Function composition *) val (++): ('a -> 'b) -> ('b -> 'c) -> 'a -> 'c (** [finally f cleaner] call the [cleaner] function when [f] is complete even in the presence of exceptions. *) val finally: (unit -> 'a) -> (unit -> unit) -> 'a end (** When [stdout] refers to a terminal, query the number of columns. Otherwise return [max_int]. *) val terminal_columns : unit -> int (** Get the output of [uname -s] *) val uname_s: unit -> string option (** Guess the shell compat-mode *) val guess_shell_compat: unit -> [`csh|`zsh|`sh|`bash|`fish] (** Guess the location of .profile *) val guess_dot_profile: [`csh|`zsh|`sh|`bash|`fish] -> string (** / *) val debug: bool ref opam-1.1.1/src/core/opamFormat.ml0000644000175000017500000004556112272210733015102 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) open OpamTypes open OpamMisc.OP type indent_variable = string -> bool let empty = { file_contents = []; file_name = ""; file_format = OpamVersion.current; } let map fn f = let file_contents = List.fold_left (fun accu -> function | Section _ as s -> s :: accu | Variable(k,v) -> match fn k v with | Some (k,v) -> Variable(k,v) :: accu | None -> accu ) [] f.file_contents in let file_contents = List.rev file_contents in { f with file_contents } let variables items = let l = List.fold_left (fun accu -> function | Variable (k,v) -> (k,v) :: accu | _ -> accu ) [] items in List.rev l let sections items = let l = List.fold_left (fun accu -> function | Section s -> (s.section_kind, s) :: accu | _ -> accu ) [] items in List.rev l exception Bad_format of string let bad_format fmt = Printf.ksprintf (fun str -> raise (Bad_format (Printf.sprintf "Bad format! %s" str))) fmt let names items = let tbl = ref OpamMisc.StringMap.empty in let add f = if OpamMisc.StringMap.mem f !tbl then let i = OpamMisc.StringMap.find f !tbl in tbl := OpamMisc.StringMap.add f (i+1) (OpamMisc.StringMap.remove f !tbl) else tbl := OpamMisc.StringMap.add f 1 !tbl in let rec aux items = List.iter (function | Variable (f, _) -> add f | Section s -> aux s.section_items ) items in aux items; !tbl let invalid_fields items fields = let tbl = names items in OpamMisc.StringMap.fold (fun f i accu -> if List.mem f fields && i = 1 then accu else f :: accu ) tbl [] let is_valid items fields = invalid_fields items fields = [] let rec kind = function | Bool b -> Printf.sprintf "bool(%b)" b | Int i -> Printf.sprintf "int(%d)" i | Ident i -> Printf.sprintf "ident(%s)" i | Symbol s -> Printf.sprintf "symbol(%s)" s | String s -> Printf.sprintf "string(%S)" s | List l -> Printf.sprintf "list(%s)" (kinds l) | Group g -> Printf.sprintf "group(%s)" (kinds g) | Option(o,l) -> Printf.sprintf "option(%s,%s)" (kind o) (kinds l) and kinds l = Printf.sprintf "{%s}" (String.concat " " (List.map kind l)) let rec string_of_value = function | Symbol s | Ident s -> Printf.sprintf "%s" s | Int i -> Printf.sprintf "%d" i | Bool b -> Printf.sprintf "%b" b | String s -> Printf.sprintf "%S" s | List l -> Printf.sprintf "[%s]" (string_of_values l) | Group g -> Printf.sprintf "(%s)" (string_of_values g) | Option(v,l) -> Printf.sprintf "%s {%s}" (string_of_value v) (string_of_values l) and string_of_values l = String.concat " " (List.rev (List.rev_map string_of_value l)) let is_list = function | List _ -> true | _ -> false (* Base parsing functions *) let parse_bool = function | Bool b -> b | x -> bad_format "Expecting a bool, got %s" (kind x) let parse_int = function | Int i -> i | x -> bad_format "Expecting an int, got %s" (kind x) let parse_ident = function | Ident i -> i | x -> bad_format "Expecting an ident, got %s" (kind x) let parse_symbol = function | Symbol s -> s | x -> bad_format "Expecting a symbol, got %s" (kind x) let parse_string = function | String s -> s | x -> bad_format "Expecting a string, got %s" (kind x) let parse_list fn = function | List s -> List.rev (List.rev_map fn s) | x -> [fn x] let parse_list_list fn ll = match ll with | List l -> if List.for_all is_list l then List.rev (List.rev_map fn l) else [fn ll] | _ -> [fn ll] let parse_group fn = function | Group g -> List.rev (List.rev_map fn g) | x -> bad_format "Expecting a group, got %s" (kind x) let parse_option f g = function | Option (k,l) -> f k, Some (g l) | k -> f k, None let parse_single_option f g = function | Option (k,[v]) -> f k, Some (g v) | k -> f k, None let parse_string_option f = function | Option (k,l) -> parse_string k, Some (f l) | k -> parse_string k, None let parse_string_list = parse_list parse_string let parse_string_pair_of_list = function | [String x; String y] -> (x,y) | x -> bad_format "Expecting a pair of strings, got %s" (kinds x) let parse_string_pair = function | List [String x; String y] -> (x,y) | x -> bad_format "Expecting a pair of strings, got %s"(kind x) let parse_single_string = function | [String x] -> x | x -> bad_format "Expecting a single string, got %s" (kinds x) let parse_pair fa fb = function | List [a; b] -> (fa a, fb b) | x -> bad_format "Expecting a pair, got %s" (kind x) let parse_or fns v = let dbg = List.map fst fns in let rec aux = function | [] -> bad_format "Expecting %s, got %s" (String.concat " or " dbg) (kind v) | (_,h)::t -> try h v with Bad_format _ -> aux t in aux fns let parse_sequence fns v = let rec aux = function | (_,f) :: fns, h :: t -> f h :: aux (fns, t) | [] , [] -> [] | lfns , l -> bad_format "Expecting %s (%s) got %s" (String.concat ", " (List.map fst lfns)) (String.concat ", " (List.map fst fns)) (string_of_values l) in match v with | List l -> aux (fns, l) | x -> aux (fns, [x]) let make_string str = String str let make_ident str = Ident str let make_symbol str = Symbol str let make_bool b = Bool b let make_int i = Int i let make_list fn l = List (List.rev (List.rev_map fn l)) let make_string_list = make_list make_string let make_group fn g = Group (List.rev (List.rev_map fn g)) let make_option f g = function | (v, None) -> f v | (v, Some o) -> Option (f v, g o) let make_pair fa fb (k,v) = List [fa k; fb v] let make_string_pair = make_pair make_string make_string (* Printing *) let rec pretty_string_of_value depth ~simplify ~indent = function | Symbol s -> s | Ident s -> if !OpamGlobals.compat_mode_1_0 && OpamMisc.contains s ':' then Printf.sprintf "\"%%{%s}%%\"" s else s | Int i -> Printf.sprintf "%d" i | Bool b -> Printf.sprintf "%b" b | String s -> if not !OpamGlobals.compat_mode_1_0 && OpamMisc.starts_with ~prefix:"%{" s && OpamMisc.ends_with ~suffix:"}%" s then String.sub s 2 (String.length s - 4) else Printf.sprintf "%S" s | List[List[]]-> Printf.sprintf "[]" | List l -> pretty_string_of_list depth ~simplify ~indent l | Group g -> Printf.sprintf "(%s)" (pretty_string_of_values (depth+1) ~simplify ~indent g) | Option(v,l) -> Printf.sprintf "%s {%s}" (pretty_string_of_value depth ~simplify ~indent v) (pretty_string_of_values depth ~simplify ~indent l) and pretty_string_of_list depth ~simplify ~indent = function | [] -> "[]" | [v] when depth = 0 && simplify -> pretty_string_of_value (depth+1) ~simplify ~indent v | l -> if depth = 0 && indent && List.length l > 1 then Printf.sprintf "[\n %s\n]" (pretty_string_of_values depth ~simplify ~indent l) else Printf.sprintf "[%s]" (pretty_string_of_values depth ~simplify ~indent l) and pretty_string_of_values depth ~simplify ~indent l = let sep = if depth = 0 && indent then "\n " else " " in String.concat sep (List.rev (List.rev_map (pretty_string_of_value (depth+1) ~simplify ~indent) l)) let incr tab = " " ^ tab let rec string_of_item_aux tab ~simplify ~indent ~ignore = function | Variable (_, List []) -> None | Variable (_, List[List[]]) -> None | Variable (i, v) -> let return ~simplify ~indent = Some (Printf.sprintf "%s%s: %s" tab i (pretty_string_of_value 0 ~simplify ~indent v)) in if List.mem i ignore then return ~simplify:false ~indent:false else return ~simplify ~indent | Section s -> Some (Printf.sprintf "%s%s %S {\n%s\n}" tab s.section_kind s.section_name (string_of_items_aux (incr tab) ~simplify ~indent ~ignore s.section_items)) and string_of_items_aux tab ~simplify ~indent ~ignore is = String.concat "\n" (OpamMisc.filter_map (string_of_item_aux tab ~simplify ~indent ~ignore) is) let string_of_item = string_of_item_aux "" let string_of_items = string_of_items_aux "" let string_of_file ~simplify ~indent ?(ignore=[]) f = let simplify = not !OpamGlobals.compat_mode_1_0 && simplify in string_of_items f.file_contents ~simplify ~indent ~ignore ^ "\n" (* Reading section contents *) let assoc items n parse = try parse (List.assoc n (variables items)) with Not_found -> bad_format "Field %S is missing" n let get_all_section_by_kind items kind = try List.rev_map snd (List.find_all (fun (k,_) -> k=kind) (sections items)) with Not_found -> bad_format "Section kind %S is missing" kind let get_section_by_kind items kind = try snd (List.find (fun (k,_) -> k=kind) (sections items)) with Not_found -> bad_format "Section kind %S is missing" kind let assoc_sections items kind parse = List.rev_map parse (get_all_section_by_kind items kind) let assoc_option items n parse = try Some (parse (List.assoc n (variables items))) with Not_found -> None let assoc_default d items n parse = try parse (List.assoc n (variables items)) with Not_found -> d let assoc_list items n parse = try parse (List.assoc n (variables items)) with Not_found -> [] let assoc_string_list s n = assoc_list s n (parse_list parse_string) (* Parse any constraint list *) let rec parse_constraints t = let version = OpamPackage.Version.of_string in let relop = OpamFormula.relop_of_string in match t with | [] -> Empty | (Symbol r) :: (String v) :: [] -> Atom (relop r, version v) | (Symbol r) :: (String v) :: (Symbol "&") :: t -> And (Atom (relop r, version v), parse_constraints t) | (Symbol r) :: (String v) :: (Symbol "|") :: t -> Or (Atom (relop r, version v), parse_constraints t) | [Group g] -> Block (parse_constraints g) | x -> bad_format "Expecting a list of constraints, got %s" (kinds x) let rec make_constraints t = match t with | Empty -> [] | Atom (r, v) -> [Symbol (OpamFormula.string_of_relop r); String (OpamPackage.Version.to_string v)] | And (x, y) -> make_constraints x @ [Symbol "&"] @ make_constraints y | Or (x, y) -> make_constraints x @ [Symbol "|"] @ make_constraints y | Block g -> [Group (make_constraints g)] (* parse a list of formulas *) let parse_formulas opt t = let name = OpamPackage.Name.of_string in let rec aux = function | [] -> Empty | [String n] -> Atom (name n, Empty) | [Option(String n, g)] -> Atom (name n, parse_constraints g) | [Group g] -> Block (aux g) | [x] -> bad_format "Expected a formula list of the \ form [ \"item\" {condition}... ], \ got %s" (kind x) | e1 :: Symbol "|" :: e2 -> let left = aux [e1] in Or (left, aux e2) | e1 :: Symbol "&" :: e2 -> let left = aux [e1] in And (left, aux e2) | e1 :: e2 when opt -> let left = aux [e1] in Or (left, aux e2) | e1 :: e2 -> let left = aux [e1] in And (left, aux e2) in match t with | List l -> aux l | x -> aux [x] let make_formulas opt t = let name = OpamPackage.Name.to_string in let rec aux = function | Empty -> [] | Atom (n, Empty) -> [String (name n)] | Atom (n, cs) -> [Option(String (name n), make_constraints cs)] | Block f -> [Group (aux f)] | And(e,f) when opt -> aux e @ [Symbol "&"] @ aux f | And(e,f) -> aux e @ aux f | Or(e,f) when opt -> aux e @ aux f | Or(e,f) -> aux e @ [Symbol "|"] @ aux f in List (aux t) let make_formula = make_formulas false let parse_formula = parse_formulas false let parse_opt_formula = parse_formulas true let make_opt_formula = make_formulas true let parse_relop = function | "=" -> `Eq | ">=" -> `Geq | ">" -> `Gt | "<=" -> `Leq | "<" -> `Lt | "!" -> `Neq | _ -> invalid_arg "parse_relop" let string_of_relop = function | `Eq -> "=" | `Geq -> ">=" | `Gt -> ">" | `Leq -> "<=" | `Lt -> "<" | `Neq -> "!" | _ -> invalid_arg "parse_relop" let parse_compiler_constraint t = let rec aux = function | [] -> Empty | [Symbol r; Ident v] when v = OpamCompiler.to_string OpamCompiler.system -> let version = OpamCompiler.Version.of_string v in Atom (parse_relop r, version) | [Symbol r; String v] -> (try Atom (parse_relop r, OpamCompiler.Version.of_string v) with _ -> bad_format "Expecting a relop, got %s" r) | [Group g] -> Block (aux g) | e1::e2 :: Symbol "|" :: e3 -> Or (aux [e1;e2], aux e3) | e1::e2 :: Symbol "&" :: e3 -> And (aux [e1;e2], aux e3) | x -> bad_format "Expecting a compiler constraint, got %s" (kinds x) in match t with | List l -> aux l | x -> aux [x] let make_compiler_constraint t = let rec aux = function | Empty -> [] | Atom (r, v) -> let mk version = [ Symbol (string_of_relop r); version ] in let system = OpamCompiler.to_string OpamCompiler.system in if OpamCompiler.Version.to_string v = system then mk (Ident system) else mk (String (OpamCompiler.Version.to_string v)) | Block f -> [Group (aux f)] | And(e,f) -> aux e @ [Symbol "&"] @ aux f | Or(e,f) -> aux e @ [Symbol "|"] @ aux f in List (aux t) let parse_os_constraint l = let pos s = Atom (true, s) in let neg s = Atom (false, s) in let rec aux = function | [] -> Empty | [Group g] -> Block (aux g) | [String os] -> pos os | [Symbol "!"; String os] -> neg os | String os :: Symbol "&" :: l -> And (pos os, aux l) | Symbol "!" :: String os :: Symbol "&" :: l -> And (neg os, aux l) | String os :: Symbol "|" :: l -> Or (pos os, aux l) | Symbol "!" :: String os :: Symbol "|" :: l -> Or (neg os, aux l) | l -> bad_format "Expecting an OS constraint, got %s" (kinds l) in match l with | List l -> aux l | x -> aux [x] let make_os_constraint l = let rec aux = function | Empty -> [] | Atom (true , os) -> [String os] | Atom (false, os) -> [Symbol "!"; String os] | Block g -> [Group (aux g)] | And(e,f) -> aux e @ [Symbol "&"] @ aux f | Or(e,f) -> aux e @ [Symbol "|"] @ aux f in List (aux l) let parse_env_variable v = let l = parse_sequence [ ("ident" , parse_ident); ("symbol", parse_symbol); ("string", parse_string); ] v in match l with | [ident; symbol; string] -> (ident, symbol, string) | _ -> assert false let make_env_variable (ident, symbol, string) = List [make_ident ident; make_symbol symbol; make_string string] (* Filters *) let rec parse_filter = function | [Bool b] -> FBool b | [String s] -> FString s | [Ident s] -> FIdent s | [Group g] -> parse_filter g | [Symbol "!"; f] -> FNot (parse_filter [f]) | [e; Symbol s; f] -> let e = parse_filter [e] in let f = parse_filter [f] in begin match s with | "=" -> FOp(e,Eq,f) | "!=" -> FOp(e,Neq,f) | ">=" -> FOp(e,Ge,f) | "<=" -> FOp(e,Le,f) | ">" -> FOp(e,Gt,f) | "<" -> FOp(e,Lt,f) | "||" | "|" -> FOr(e,f) | "&&" | "&" -> FAnd(e,f) | _ -> bad_format "Got %s, expecting a valid symbol" s end; | x -> bad_format "Got %s, expecting a filter expression" (kinds x) let lift = function | [x] -> x | l -> Group l let rec make_filter = function | FString s -> [String s] | FIdent s -> [Ident s] | FBool b -> [Bool b] | FOp(e,s,f) -> let s = Symbol (string_of_symbol s) in let e = lift (make_filter e) in let f = lift (make_filter f) in [ e; s; f] | FOr(e,f) -> let e = lift (make_filter e) in let f = lift (make_filter f) in [ e; Symbol "|"; f] | FAnd(e,f) -> let e = lift (make_filter e) in let f = lift (make_filter f) in [ e; Symbol "&"; f ] | FNot f -> [Symbol "!"; lift (make_filter f)] let make_simple_arg = function | CString s -> make_string s | CIdent s -> make_ident s let make_arg = make_option make_simple_arg make_filter let make_command = make_option (make_list make_arg) make_filter let make_commands = make_list make_command let parse_simple_arg = parse_or [ "ident" , (parse_ident ++ fun x -> CIdent x); "string", (parse_string ++ fun x -> CString x); ] let parse_arg = parse_option parse_simple_arg parse_filter let parse_command = parse_option (parse_list parse_arg) parse_filter let parse_commands = parse_or [ "command" , (fun x -> [parse_command x]); "command-list", parse_list parse_command; ] let parse_message = parse_option parse_string parse_filter let parse_messages = parse_list parse_message (* TAGS *) let parse_string_set = parse_string_list ++ OpamMisc.StringSet.of_list let make_string_set = OpamMisc.StringSet.elements ++ make_string_list let parse_tag_line = let fn = parse_string_set in parse_pair fn fn let make_tag_line = let fn = make_string_set in make_pair fn fn let parse_tags v = let l = parse_or [ "tag" , (fun x -> [parse_tag_line x]); "tags", (parse_list parse_tag_line); ] v in OpamMisc.StringSetMap.of_list l let make_tags t = let l = OpamMisc.StringSetMap.bindings t in make_list make_tag_line l opam-1.1.1/src/core/opamCompiler.mli0000644000175000017500000000436212272210733015567 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) (** Compiler names and versions *) (** OCaml compiler versions *) module Version: sig include OpamMisc.ABSTRACT (** Compiler constraint *) type constr = (OpamFormula.relop * t) OpamFormula.formula (** Return the version of the compiler currently installed *) val current: unit -> t option (** Returm the version of the system compiler *) val system: unit -> t option (** Compare OCaml versions *) val compare: t -> t -> int (** Evaluate a relational operator between OCaml versions *) val eval_relop: OpamFormula.relop -> t -> t -> bool end (** Compiler names *) include OpamMisc.ABSTRACT (** Convert a filename into a compiler name. This function extract [name] from {i /path/to/$name.comp}. *) val of_filename: OpamFilename.t -> t option (** List the compiler available in the global state. *) val list: OpamFilename.Dir.t -> Set.t (** List the compiler available in a directory (and their prefix) *) val prefixes: OpamFilename.Dir.t -> string option Map.t (** System compiler *) val system: t (** Errors *) val unknown: t -> 'a (** Return the compiler version *) val version: t -> Version.t opam-1.1.1/src/core/opamSwitch.mli0000644000175000017500000000247612272210733015262 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) (** Compiler switches *) include OpamMisc.ABSTRACT (** Default switch *) val default: t (** Display a nice error message when a switch is not installed. *) val not_installed: t -> 'a opam-1.1.1/src/core/opamRepository.ml0000644000175000017500000003216612272210733016026 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) open OpamTypes open OpamMisc.OP open OpamFilename.OP let log fmt = OpamGlobals.log "REPOSITORY" fmt let compare r1 r2 = match compare r2.repo_priority r1.repo_priority with | 0 -> compare r2.repo_name r1.repo_name | x -> x let to_string r = Printf.sprintf "%s(%d %s %s)" (OpamRepositoryName.to_string r.repo_name) r.repo_priority (OpamTypes.string_of_repository_kind r.repo_kind) (string_of_address r.repo_address) let default_address = OpamGlobals.default_repository_address, None let default () = { repo_name = OpamRepositoryName.default; repo_kind = `http; repo_address = default_address; repo_priority = 0; repo_root = OpamPath.Repository.create (OpamPath.root()) OpamRepositoryName.default; } let local dirname = { repo_name = OpamRepositoryName.of_string "local"; repo_root = dirname; repo_address = ("", None); repo_kind = `local; repo_priority = 0; } let to_json r = `O [ ("name", OpamRepositoryName.to_json r.repo_name); ("kind", `String (string_of_repository_kind r.repo_kind)); ] module O = struct type tmp = repository type t = tmp let compare = compare let to_string = to_string let to_json = to_json end let of_string _ = failwith "TOTO" module Set = OpamMisc.Set.Make(O) module Map = OpamMisc.Map.Make(O) module type BACKEND = sig val pull_url: package -> dirname -> string option -> address -> generic_file download val pull_repo: repository -> unit val pull_archive: repository -> filename -> filename download val revision: repository -> version option end exception Unknown_backend let backends = Hashtbl.create 8 let find_backend r = try Hashtbl.find backends r.repo_kind with Not_found -> raise Unknown_backend let find_backend_by_kind k = try Hashtbl.find backends k with Not_found -> raise Unknown_backend let register_backend name backend = Hashtbl.replace backends name backend (* initialize the current directory *) let init repo = log "init %s" (to_string repo); let module B = (val find_backend repo: BACKEND) in OpamFilename.rmdir repo.repo_root; OpamFilename.mkdir repo.repo_root; OpamFile.Repo_config.write (OpamPath.Repository.config repo) repo; OpamFilename.mkdir (OpamPath.Repository.packages_dir repo); OpamFilename.mkdir (OpamPath.Repository.archives_dir repo); OpamFilename.mkdir (OpamPath.Repository.compilers_dir repo); ignore (B.pull_repo repo) let pull_url kind package local_dirname checksum remote_url = let module B = (val find_backend_by_kind kind: BACKEND) in B.pull_url package local_dirname checksum remote_url let revision repo = let kind = repo.repo_kind in let module B = (val find_backend_by_kind kind: BACKEND) in B.revision repo let pull_url_and_fix_digest kind package dirname checksum file url = match pull_url kind package dirname None url with | Not_available _ | Up_to_date _ | Result (D _) as r -> r | Result (F f) as r -> let actual = OpamFilename.digest f in if checksum <> actual then ( OpamGlobals.msg "Fixing wrong checksum for %s: current value is %s, setting it to %s.\n" (OpamPackage.to_string package) checksum actual; let u = OpamFile.URL.read file in OpamFile.URL.write file (OpamFile.URL.with_checksum u actual) ); r let check_digest filename = function | None -> () | Some expected -> if !OpamGlobals.no_checksums then () else let actual = OpamFilename.digest filename in if actual = expected then () else OpamGlobals.error_and_exit "Wrong checksum for %s:\n\ \ - %s [expected result]\n\ \ - %s [actual result]\n\ This is surely due to outdated package descriptions and should be \ fixed by running `opam update`.\n\ In case an update does not fix that problem, you can use the \ `--no-checksums` command-line option\n\ to /bypass any checksum checks." (OpamFilename.to_string filename) expected actual let pull_archive repo nv = let module B = (val find_backend_by_kind repo.repo_kind: BACKEND) in let filename = OpamPath.Repository.remote_archive repo nv in B.pull_archive repo filename let check_version repo = let repo_version = begin repo |> OpamPath.Repository.repo |> OpamFile.Repo.safe_read |> OpamFile.Repo.opam_version end in if OpamVersion.compare repo_version OpamVersion.current > 0 then OpamGlobals.error_and_exit "\nThe current version of OPAM cannot read the repository. \ You should upgrade to at least version %s.\n" (OpamVersion.to_string repo_version) let extract_prefix repo dir nv = let prefix = let prefix = OpamFilename.Dir.to_string (OpamPath.Repository.packages_dir repo) in prefix ^ Filename.dir_sep in let suffix = let suffix = OpamPackage.to_string nv in Filename.dir_sep ^ suffix in let dir = OpamFilename.Dir.to_string dir in OpamMisc.remove_prefix ~prefix (OpamMisc.remove_suffix ~suffix dir) let file f = if OpamFilename.exists f then [f] else [] let dir d = if OpamFilename.exists_dir d then OpamFilename.rec_files d else [] (* Compiler updates *) let compilers_with_prefixes r = OpamCompiler.prefixes (OpamPath.Repository.compilers_dir r) let compilers repo = OpamCompiler.list (OpamPath.Repository.compilers_dir repo) let compiler_files repo prefix c = let comp = OpamPath.Repository.compiler_comp repo prefix c in let descr = OpamPath.Repository.compiler_descr repo prefix c in file comp @ file descr let compiler_state repo prefix c = let fs = compiler_files repo prefix c in List.flatten (List.map OpamFilename.checksum fs) let packages r = OpamPackage.list (OpamPath.Repository.packages_dir r) let packages_with_prefixes r = OpamPackage.prefixes (OpamPath.Repository.packages_dir r) (* Returns the meaningful checksum of a url file. Uses the hash of the remote archive if present, or its address, not the hash of the url file itself which doesn't really matter *) let url_checksum url = let u = OpamFile.URL.safe_read url in if u = OpamFile.URL.empty then [] else match OpamFile.URL.checksum u with | Some cksum -> [cksum] | None -> [Digest.string (string_of_address (OpamFile.URL.url u))] let package_files repo prefix nv ~archive = let opam = OpamPath.Repository.opam repo prefix nv in let descr = OpamPath.Repository.descr repo prefix nv in let url = OpamPath.Repository.url repo prefix nv in let files = OpamPath.Repository.files repo prefix nv in let archive = if archive then file (OpamPath.Repository.archive repo nv) else [] in file opam @ file descr @ file url @ dir files @ archive let package_important_files repo prefix nv ~archive = let url = OpamPath.Repository.url repo prefix nv in let files = OpamPath.Repository.files repo prefix nv in if archive then let archive = OpamPath.Repository.archive repo nv in file url @ dir files @ file archive else file url @ dir files let package_state repo prefix nv all = let fs = match all with | `all -> package_files repo prefix nv ~archive:true | `partial b -> package_important_files repo prefix nv ~archive:b in let url = OpamPath.Repository.url repo prefix nv in let l = List.map (fun f -> if f = url then url_checksum f else OpamFilename.checksum f) fs in List.flatten l (* Sort repositories by priority *) let sort repositories = let repositories = OpamRepositoryName.Map.values repositories in List.sort compare repositories let package_index repositories = log "package-index"; let repositories = sort repositories in List.fold_left (fun map repo -> let packages = packages_with_prefixes repo in OpamPackage.Map.fold (fun nv prefix map -> if OpamPackage.Map.mem nv map then map else OpamPackage.Map.add nv (repo.repo_name, prefix) map ) packages map ) OpamPackage.Map.empty repositories let compiler_index repositories = log "compiler-index"; let repositories = sort repositories in List.fold_left (fun map repo -> let comps = compilers_with_prefixes repo in OpamCompiler.Map.fold (fun comp prefix map -> if OpamCompiler.Map.mem comp map then map else OpamCompiler.Map.add comp (repo.repo_name, prefix) map ) comps map ) OpamCompiler.Map.empty repositories let update repo = log "update %s" (to_string repo); let module B = (val find_backend repo: BACKEND) in B.pull_repo repo; check_version repo let make_archive ?(gener_digest=false) repo prefix nv = let url_file = OpamPath.Repository.url repo prefix nv in let files_dir = OpamPath.Repository.files repo prefix nv in let archive = OpamPath.Repository.archive repo nv in let archive_dir = OpamPath.Repository.archives_dir repo in if not (OpamFilename.exists_dir archive_dir) then OpamFilename.mkdir archive_dir; (* Download the remote file / fetch the remote repository *) let download download_dir = if OpamFilename.exists url_file then ( let url = OpamFile.URL.read url_file in let checksum = OpamFile.URL.checksum url in let remote_url = OpamFile.URL.url url in let kind = guess_repository_kind (OpamFile.URL.kind url) remote_url in log "downloading %s:%s" (string_of_address remote_url) (string_of_repository_kind kind); if not (OpamFilename.exists_dir download_dir) then OpamFilename.mkdir download_dir; OpamFilename.in_dir download_dir (fun () -> match checksum with | None -> Some (pull_url kind nv download_dir None remote_url) | Some c -> if gener_digest then Some (pull_url_and_fix_digest kind nv download_dir c url_file remote_url) else Some (pull_url kind nv download_dir checksum remote_url) ) ) else None in (* if we've downloaded a file, extract it, otherwise just copy it *) let extract local_filename extract_dir = match local_filename with | None -> () | Some (Not_available u) -> OpamGlobals.error_and_exit "%s is not available" u | Some ( Result r | Up_to_date r ) -> OpamFilename.extract_generic_file r extract_dir in (* Eventually add /files/* into the extracted dir *) let copy_files extract_dir = if OpamFilename.exists_dir files_dir then ( if not (OpamFilename.exists_dir extract_dir) then OpamFilename.mkdir extract_dir; OpamFilename.copy_files ~src:files_dir ~dst:extract_dir; OpamFilename.Set.of_list (OpamFilename.rec_files extract_dir) ) else OpamFilename.Set.empty in (* Finally create the final archive *) let create_archive files extract_root = if not (OpamFilename.Set.is_empty files) || OpamFilename.exists url_file then ( OpamGlobals.msg "Creating %s.\n" (OpamFilename.to_string archive); OpamFilename.exec extract_root [ [ "tar" ; "czf" ; OpamFilename.to_string archive ; OpamPackage.to_string nv ] ]; Some archive ) else None in OpamFilename.with_tmp_dir (fun extract_root -> OpamFilename.with_tmp_dir (fun download_dir -> let local_filename = download download_dir in let extract_dir = extract_root / OpamPackage.to_string nv in extract local_filename extract_dir; let files = copy_files extract_dir in match create_archive files extract_root with | None | Some _ -> () ) ) module Graph = struct module Vertex = struct type t = repository let compare = compare let hash = Hashtbl.hash let equal r1 r2 = compare r1 r2 = 0 end module PG = Graph.Imperative.Digraph.ConcreteBidirectional (Vertex) module Topological = Graph.Topological.Make (PG) module Traverse = Graph.Traverse.Dfs(PG) module Components = Graph.Components.Make(PG) module Parallel = OpamParallel.Make(struct let string_of_vertex = to_string include PG include Topological include Traverse include Components end) end module Parallel = Graph.Parallel let find_backend = find_backend_by_kind opam-1.1.1/src/core/opamFormula.ml0000644000175000017500000001744212272210733015254 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) type relop = [`Eq|`Neq|`Geq|`Gt|`Leq|`Lt] let string_of_relop = function | `Eq -> "=" | `Neq -> "!=" | `Geq -> ">=" | `Gt -> ">" | `Leq -> "<=" | `Lt -> "<" let relop_of_string = function | "=" -> `Eq | "!=" -> `Neq | ">=" -> `Geq | ">" -> `Gt | "<=" -> `Leq | "<" -> `Lt | x -> failwith (x ^ " is not a valid relop") type version_constraint = relop * OpamPackage.Version.t type atom = OpamPackage.Name.t * version_constraint option let string_of_atom = function | n, None -> OpamPackage.Name.to_string n | n, Some (r,c) -> Printf.sprintf "%s (%s %s)" (OpamPackage.Name.to_string n) (string_of_relop r) (OpamPackage.Version.to_string c) type 'a conjunction = 'a list let string_of_conjunction string_of_atom c = Printf.sprintf "(%s)" (String.concat " & " (List.rev_map string_of_atom c)) type 'a disjunction = 'a list let string_of_disjunction string_of_atom c = Printf.sprintf "(%s)" (String.concat " | " (List.rev_map string_of_atom c)) type 'a cnf = 'a list list let string_of_cnf string_of_atom cnf = let string_of_clause c = Printf.sprintf "(%s)" (String.concat " | " (List.rev_map string_of_atom c)) in Printf.sprintf "(%s)" (String.concat " & " (List.rev_map string_of_clause cnf)) type 'a dnf = 'a list list let string_of_dnf string_of_atom cnf = let string_of_clause c = Printf.sprintf "(%s)" (String.concat " & " (List.rev_map string_of_atom c)) in Printf.sprintf "(%s)" (String.concat " | " (List.rev_map string_of_clause cnf)) type 'a formula = | Empty | Atom of 'a | Block of 'a formula | And of 'a formula * 'a formula | Or of 'a formula * 'a formula let string_of_formula string_of_a f = let rec aux = function | Empty -> "0" | Atom a -> string_of_a a | Block x -> Printf.sprintf "(%s)" (aux x) | And(x,y) -> Printf.sprintf "%s & %s" (aux x) (aux y) | Or(x,y) -> Printf.sprintf "%s | %s" (aux x) (aux y) in aux f let rec map f = function | Empty -> Empty | Atom x -> f x | Block x -> Block (map f x) | And(x,y) -> And (map f x, map f y) | Or(x,y) -> Or (map f x, map f y) let rec iter f = function | Empty -> () | Atom x -> f x | Block x -> iter f x | And(x,y) -> iter f x; iter f y | Or(x,y) -> iter f x; iter f y let rec fold_left f i = function | Empty -> i | Atom x -> f i x | Block x -> fold_left f i x | And(x,y) -> fold_left f (fold_left f i x) y | Or(x,y) -> fold_left f (fold_left f i x) y type version_formula = version_constraint formula type t = (OpamPackage.Name.t * version_formula) formula let rec eval atom = function | Empty -> true | Atom x -> atom x | Block x -> eval atom x | And(x,y) -> eval atom x && eval atom y | Or(x,y) -> eval atom x || eval atom y let check_relop relop c = match relop with | `Eq -> c = 0 | `Neq -> c <> 0 | `Geq -> c >= 0 | `Gt -> c > 0 | `Leq -> c <= 0 | `Lt -> c < 0 let eval_relop relop v1 v2 = check_relop relop (OpamPackage.Version.compare v1 v2) let to_string t = let string_of_constraint (relop, version) = Printf.sprintf "%s %s" (string_of_relop relop) (OpamPackage.Version.to_string version) in let string_of_pkg = function | n, Empty -> OpamPackage.Name.to_string n | n, c -> Printf.sprintf "%s %s" (OpamPackage.Name.to_string n) (string_of_formula string_of_constraint c) in string_of_formula string_of_pkg t (* convert a formula to a CNF *) let cnf_of_formula t = let rec mk_left x y = match y with | Block y -> mk_left x y | And (a,b) -> And (mk_left x a, mk_left x b) | Empty -> x | _ -> Or (x,y) in let rec mk_right x y = match x with | Block x -> mk_right x y | And (a,b) -> And (mk_right a y, mk_right b y) | Empty -> y | _ -> mk_left x y in let rec mk = function | Empty -> Empty | Block x -> mk x | Atom x -> Atom x | And (x,y) -> And (mk x, mk y) | Or (x,y) -> mk_right (mk x) (mk y) in mk t (* convert a formula to DNF *) let dnf_of_formula t = let rec mk_left x y = match y with | Block y -> mk_left x y | Or (a,b) -> Or (mk_left x a, mk_left x b) | _ -> And (x,y) in let rec mk_right x y = match x with | Block x -> mk_right x y | Or (a,b) -> Or (mk_right a y, mk_right b y) | _ -> mk_left x y in let rec mk = function | Empty -> Empty | Block x -> mk x | Atom x -> Atom x | Or (x,y) -> Or (mk x, mk y) | And (x,y) -> mk_right (mk x) (mk y) in mk t (* Convert a t an atom formula *) let to_atom_formula (t:t): atom formula = let atom (r,v) = Atom (r, v) in let atoms (x, c) = match cnf_of_formula (map atom c) with | Empty -> Atom (x, None) | cs -> map (fun c -> Atom (x, Some c)) cs in map atoms t (* Convert an atom formula to a t-formula *) let of_atom_formula (a:atom formula): t = let atom (n, v) = match v with | None -> Atom (n, Empty) | Some (r,v) -> Atom (n, Atom (r,v)) in map atom a (* Convert a formula to CNF *) let to_cnf (t : t) = let rec or_formula = function | Atom (x,None) -> [x, None] | Atom (x,Some(r,v)) -> [x, Some(r,v)] | Or(x,y) -> or_formula x @ or_formula y | Empty | Block _ | And _ -> assert false in let rec aux t = match t with | Empty -> [] | Block _ -> assert false | Atom _ | Or _ -> [or_formula t] | And(x,y) -> aux x @ aux y in aux (cnf_of_formula (to_atom_formula t)) (* Convert a formula to DNF *) let to_dnf t = let rec and_formula = function | Atom (x,None) -> [x, None] | Atom (x,Some(r,v)) -> [x, Some(r,v)] | And(x,y) -> and_formula x @ and_formula y | Empty | Block _ | Or _ -> assert false in let rec aux t = match t with | Empty -> [] | Block _ -> assert false | Atom _ | And _ -> [and_formula t] | Or(x,y) -> aux x @ aux y in aux (dnf_of_formula (to_atom_formula t)) let to_conjunction t = match to_dnf t with | [] -> [] | [x] -> x | _ -> OpamGlobals.error_and_exit "%s is not a valid conjunction" (to_string t) let ands = function | [] -> Empty | h::t -> List.fold_left (fun acc elt -> And(acc, elt)) h t let of_conjunction c = of_atom_formula (ands (List.rev_map (fun x -> Atom x) c)) let to_disjunction t = match to_cnf t with | [] -> [] | [x] -> x | _ -> OpamGlobals.error_and_exit "%s is not a valid disjunction" (to_string t) let ors = function | [] -> Empty | h::t -> List.fold_left (fun acc elt -> Or(acc, elt)) h t let of_disjunction d = of_atom_formula (ors (List.rev_map (fun x -> Atom x) d)) let atoms t = fold_left (fun accu x -> x::accu) [] (to_atom_formula t) opam-1.1.1/src/core/opamRepositoryName.mli0000644000175000017500000000234612272210733016775 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) (** Repository names *) include OpamMisc.ABSTRACT (** Default repository name *) val default: t opam-1.1.1/src/core/opamFilter.ml0000644000175000017500000001347712272210733015100 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) open OpamTypes type env = full_variable -> variable_contents option let rec to_string = function | FBool b -> string_of_bool b | FString s -> Printf.sprintf "%S" s | FIdent i -> i | FOp(e,s,f) -> Printf.sprintf "%s %s %s" (to_string e) (string_of_symbol s) (to_string f) | FAnd (e,f) -> Printf.sprintf "%s & %s" (to_string e) (to_string f) | FOr (e,f) -> Printf.sprintf "%s | %s" (to_string e) (to_string f) | FNot e -> Printf.sprintf "!%s" (to_string e) (* Return the contents of a fully qualified variable *) let contents_of_variable env v = let name = OpamVariable.Full.package v in let var = OpamVariable.Full.variable v in match env v with | Some r -> Some r | None -> let name_str = OpamPackage.Name.to_string name in let names = try OpamMisc.split name_str '+' with _ -> [name_str] in let names = List.rev_map OpamPackage.Name.of_string names in let results = List.rev_map (fun name -> let v = OpamVariable.Full.create_global name var in match env v with | None -> OpamGlobals.error_and_exit "%s does not define the variable %s." (OpamPackage.Name.to_string name) (OpamVariable.to_string var) | Some r -> r ) names in let rec compose x y = match x,y with | S "enable" , S "enable" -> S "enable" | S "disable", S "enable" | S "enable" , S "disable" | S "disable", S "disable" -> S "disable" | B b1 , B b2 -> B (b1 && b2) | S b, r | r, S b -> if b = "true" then compose (B true) r else if b = "false" then compose (B false) r else OpamGlobals.error_and_exit "Cannot compose %s and %s" (OpamVariable.string_of_variable_contents x) (OpamVariable.string_of_variable_contents y) in match results with | [] | [_] -> assert false | h::t -> Some (List.fold_left compose h t) let contents_of_variable_exn env var = match contents_of_variable env var with | None -> OpamGlobals.error_and_exit "%s is not a valid variable." (OpamVariable.Full.to_string var) | Some c -> c let substitute_ident env i = let v = OpamVariable.Full.of_string i in contents_of_variable_exn env v (* Substitute the file contents *) let substitute_file env f = let f = OpamFilename.of_basename f in let src = OpamFilename.add_extension f "in" in let contents = OpamFile.Subst.read src in let newcontents = OpamFile.Subst.replace contents (contents_of_variable_exn env) in OpamFile.Subst.write f newcontents (* Substitue the string contents *) let substitute_string env s = OpamFile.Subst.replace_string s (contents_of_variable_exn env) exception Filter_type_error let filter_type_error f actual expected = OpamGlobals.error "\'%s\' has type %s, but a env element of type %s was expected." (to_string f) actual expected; raise Filter_type_error let string_of_variable_contents ident = function | S s -> s | B _ -> filter_type_error (FIdent ident) "bool" "string" let bool_of_variable_contents ident = function | B b -> b | S _ -> filter_type_error (FIdent ident) "string" "bool" let eval_to_string env = function | FString s -> substitute_string env s | FIdent s -> string_of_variable_contents s (substitute_ident env s) | f -> filter_type_error f "bool" "string" let rec eval env = function | FBool b -> b | FString s -> substitute_string env s = "true" | FIdent s -> bool_of_variable_contents s (substitute_ident env s) | FOp(e,s,f) -> (* We are supposed to compare version strings *) let s = match s with | Eq -> (fun a b -> Debian.Version.compare a b = 0) | Neq -> (fun a b -> Debian.Version.compare a b <> 0) | Ge -> (fun a b -> Debian.Version.compare a b >= 0) | Le -> (fun a b -> Debian.Version.compare a b <= 0) | Gt -> (fun a b -> Debian.Version.compare a b > 0) | Lt -> (fun a b -> Debian.Version.compare a b < 0) in s (eval_to_string env e) (eval_to_string env f) | FOr(e,f) -> eval env e || eval env f | FAnd(e,f) -> eval env e && eval env f | FNot e -> not (eval env e) let eval_opt env = function | None -> true | Some f -> try eval env f with _ -> false let arg env (a,f) = if eval_opt env f then try match a with | CString s -> Some (substitute_string env s) | CIdent i -> Some (string_of_variable_contents i (substitute_ident env i)) with _ -> None else None let command env (l, f) = if eval_opt env f then match OpamMisc.filter_map (arg env) l with | [] -> None | l -> Some l else None let commands env l = OpamMisc.filter_map (command env) l opam-1.1.1/src/core/opamFile.mli0000644000175000017500000003215112272210733014671 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) open OpamTypes (** Functions to read and write OPAM configuration files in a typed way *) (** All Configuration files satisfies this signature *) module type IO_FILE = sig (** File contents *) type t (** Empty file *) val empty: t (** Write some contents to a file *) val write: filename -> t -> unit (** Read file contents. Raise an error if the file does not exist. *) val read: filename -> t (** Read file contents. Return [empty] if the file does not exist. *) val safe_read: filename -> t (** Read from channel. *) val read_from_channel: in_channel -> t (** Write to channel. *) val write_to_channel: out_channel -> t -> unit end (** Configuration file: [$opam/config] *) module Config: sig include IO_FILE (** Creation *) val create: switch -> repository_name list -> int -> t (** OCaml switch updates *) val with_switch : t -> switch -> t (** Repository updates *) val with_repositories: t -> repository_name list -> t (** Update opam-version to the current one *) val with_current_opam_version: t -> t (** Return the OPAM version *) val opam_version: t -> opam_version (** Return the list of repository *) val repositories: t -> repository_name list (** Return the OCaml switch *) val switch: t -> switch (** Return the number of jobs *) val jobs: t -> int end (** OPAM files *) module OPAM: sig include IO_FILE (** Create an opam file *) val create: package -> t (** Get OPAM version. *) val opam_version: t -> opam_version (** Package name *) val name: t -> name (** Package version *) val version: t -> version (** Compiler constraint *) val ocaml_version: t -> compiler_constraint option (** OS constraint *) val os: t -> (bool * string) generic_formula (** Availability formula (OS + compiler constraints) *) val available: t -> filter (** Package maintainer(s) *) val maintainer: t -> string list (** File substitutions *) val substs: t -> basename list (** List of environment variables to set-up for the build *) val build_env: t -> (string * string * string) list (** List of command to run for building the package *) val build: t -> command list (** List of command to run for removing the package *) val remove: t -> command list (** Package dependencies *) val depends: t -> formula (** Optional dependencies *) val depopts: t -> formula (** External dependencies *) val depexts: t -> tags option (** Package conflicts *) val conflicts: t -> formula (** List of exported libraries *) val libraries: t -> section list (** List of exported syntax extensions *) val syntax: t -> section list (** Patches *) val patches: t -> (basename * filter option) list (** Homepage(s) *) val homepage: t -> string list (** Author(s) *) val author: t -> string list (** License(s) *) val license: t -> string list (** API documentation *) val doc: t -> string list (** Classification tags *) val tags: t -> string list (** Commands to build and run the tests *) val build_test: t -> command list (** Commands to build the documentation *) val build_doc: t -> command list (** Messages to display before taking action *) val messages: t -> (string * filter option) list (** Messages to display at end of install *) val post_messages: t -> (string * filter option) list (** Where to post bug reports. *) val bug_reports: t -> string list (** construct as [name] *) val with_name: t -> name -> t (** construct as [version] *) val with_version: t -> version -> t (** Construct as [depends] *) val with_depends : t -> formula -> t (** Construct as [depopts] *) val with_depopts : t -> formula -> t (** Construct as [build] *) val with_build: t -> command list -> t (** Construct as [remove] *) val with_remove : t -> command list -> t (** Construct as [libraries] *) val with_libraries : t -> section list -> t (** Construct as [substs] *) val with_substs : t -> basename list -> t (** Construct as [compiler_version] *) val with_ocaml_version: t -> compiler_constraint option -> t (** Construct as [maintainer] *) val with_maintainer: t -> string list -> t (** Construct as [patches] *) val with_patches: t -> (basename * filter option) list -> t (** Construct using [bug_reports] *) val with_bug_reports: t -> string list -> t (** Construct using [depexts] *) val with_depexts: t -> tags option -> t (** Convert to OPAM 1.0 *) val to_1_0: file -> file end (** Package descriptions: [$opam/descr/] *) module Descr: sig include IO_FILE (** Create an abstract description file from a string *) val of_string: string -> t (** Return the first line *) val synopsis: t -> string (** Return the body *) val body: t -> string (** Return the full description *) val full: t -> string end (** Compiler aliases: [$opam/aliases] *) module Aliases: IO_FILE with type t = compiler switch_map (** Import/export file. This difference with [installed] is that we are explicit about root packages. *) module Export: IO_FILE with type t = package_set * package_set (** List of installed packages: [$opam/$oversion/installed] *) module Installed: IO_FILE with type t = package_set (** List of packages explicitly installed by the user: [$opam/$switch/installed.user] *) module Installed_roots: IO_FILE with type t = package_set (** List of packages to reinstall: [$opam/$oversion/reinstall] *) module Reinstall: IO_FILE with type t = package_set (** Compiler version [$opam/compilers/] *) module Comp: sig include IO_FILE (** Create a pre-installed compiler description file *) val create_preinstalled: compiler -> compiler_version -> name list -> (string * string * string) list -> t (** Is it a pre-installed compiler description file *) val preinstalled: t -> bool (** Get OPAM version *) val opam_version: t -> opam_version (** Return the compiler name *) val name: t -> compiler (** Return the compiler version *) val version: t -> compiler_version (** Return the url of the compiler *) val src: t -> address option (** Return the url kind *) val kind: t -> repository_kind option (** Return the list of patches to apply *) val patches: t -> filename list (** Options to give to the "./configure" command *) val configure: t -> string list (** Options to give to the "make" command *) val make: t -> string list (** Options to give to build the package. If this one is provided, nothing should be specified for [configure] and [make]. *) val build: t -> command list (** Packages to install immediately after the creation of OCaml *) val packages: t -> formula (** Linking options to give to the native code compiler *) val asmlink: t -> string list (** Compilation options to give to the native code compiler *) val asmcomp: t -> string list (** Linking options to give to the bytecode compiler *) val bytelink: t -> string list (** Compilation options to give to the bytecode compiler *) val bytecomp: t -> string list (** Linking options to give to the native code compiler *) val asmcomp: t -> string list (** Libraries to link with *) val requires: t -> section list (** Preprocessing options *) val pp: t -> ppflag option (** Environment variable to set-up before running commands in the subtree *) val env: t -> (string * string * string) list (** Convert to OPAM 1.0 *) val to_1_0: file -> file end (** {2 Configuration files} *) (** .install files *) module Dot_install: sig include IO_FILE (** List of files to install in $bin/ *) val bin: t -> (basename optional * basename option) list (** List of files to install in $sbin/ *) val sbin: t -> (basename optional * basename option) list (** List of files to install in $lib/ *) val lib: t -> (basename optional * basename option) list (** List of toplevel files *) val toplevel: t -> (basename optional * basename option) list (** C bindings *) val stublibs: t -> (basename optional * basename option) list (** List of shared files *) val share: t -> (basename optional * basename option) list (** List of etc files *) val etc: t -> (basename optional * basename option) list (** List of doc files *) val doc: t -> (basename optional * basename option) list (** Man pages *) val man: t -> (basename optional * basename option) list (** List of other files to install *) val misc: t -> (basename optional * filename) list end (** .config files *) module Dot_config: sig include IO_FILE (** Create a new .config file (containing only variables) *) val create: (variable * variable_contents) list -> t module type SECTION = sig (** List the available sections *) val available: t -> section list (** Return the section kind *) val kind: t -> section -> string (** Return the list of native-compiler options *) val asmcomp: t -> section -> string list (** Return the list of bytecode-compiler options *) val bytecomp: t -> section -> string list (** Return the list of native-code linking options *) val asmlink: t -> section -> string list (** Return the list of bytecode linking options *) val bytelink: t -> section -> string list (** Return the build requirements *) val requires: t -> section -> section list (** Return the value of variables *) val variable: t -> section -> variable -> variable_contents option (** The list of local variables *) val variables: t -> section -> variable list end (** All library and syntax sections *) module Section: SECTION (** Sections starting by [library] *) module Library: SECTION (** Sections starting by [syntax] *) module Syntax: SECTION (** Top-level variables *) val variable: t -> variable -> variable_contents option (** The list of top-level variables *) val variables: t -> variable list end (** {2 Repository files} *) (** Association between package names and repositories *) module Package_index: IO_FILE with type t = (repository_name * string option) package_map (** Association between compiler names and repositories *) module Compiler_index: IO_FILE with type t = (repository_name * string option) compiler_map (** Repository config: [$opam/repo/$repo/config] *) module Repo_config: IO_FILE with type t = repository (** Pinned package files *) module Pinned: IO_FILE with type t = pin_option name_map (** Repository metadata *) module Repo: sig include IO_FILE val create: ?browse:string -> ?upstream:string -> ?opam_version:string -> ?redirect:(string * filter option) list -> unit -> t (** The minimum OPAM version required for this repository *) val opam_version : t -> OpamVersion.t (** Base URL for browsing packages on the WWW *) val browse: t -> string option (** Base URL for browsing OPAM repository source on the WWW *) val upstream: t -> string option (** Redirections. *) val redirect: t -> (string * filter option) list end (** {2 Substitution files} *) (** Substitution files *) module Subst: sig include IO_FILE (** Substitute the variables appearing in a file *) val replace: t -> (full_variable -> variable_contents)-> t (** Substitute the variables appearing in a string *) val replace_string: string -> (full_variable -> variable_contents) -> string end (** {2 Urls for OPAM repositories} *) module URL: sig include IO_FILE val create: repository_kind option -> address -> t (** URL address *) val url: t -> address (** Backend kind (could be curl/rsync/git/darcs/hg at the moment) *) val kind: t -> repository_kind option (** Archive checksum *) val checksum: t -> string option (** Constructor *) val with_checksum: t -> string -> t end (** {2 urls.txt file *} *) module File_attributes: IO_FILE with type t = file_attribute_set (** List of filenames *) module Filenames: IO_FILE with type t = filename_set (** Prefix of package directories *) module Prefix: IO_FILE with type t = string name_map (** Display statistics about file access. *) val print_stats: unit -> unit opam-1.1.1/src/core/opamTypes.ml0000644000175000017500000003450512272210733014752 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) open OpamMisc.OP exception Lexer_error of string type json = OpamJson.t type basename = OpamFilename.Base.t type dirname = OpamFilename.Dir.t type filename = OpamFilename.t type filename_set = OpamFilename.Set.t type 'a filename_map = 'a OpamFilename.Map.t type 'a download = | Up_to_date of 'a | Not_available of string | Result of 'a type generic_file = OpamFilename.generic_file = | D of dirname | F of filename let download_map fn = function | Up_to_date f -> Up_to_date (fn f) | Result f -> Result (fn f) | Not_available d -> Not_available d let download_dir = download_map (fun d -> D d) let download_file = download_map (fun f -> F f) type version = OpamPackage.Version.t type version_set = OpamPackage.Version.Set.t type name = OpamPackage.Name.t type name_set = OpamPackage.Name.Set.t type 'a name_map = 'a OpamPackage.Name.Map.t type package = OpamPackage.t type package_set = OpamPackage.Set.t type 'a package_map = 'a OpamPackage.Map.t type address = string * string option let string_of_address = function | url, None -> url | url, Some c -> Printf.sprintf "%s#%s" url c let address_of_string str = match OpamMisc.cut_at str '#' with | None -> OpamSystem.real_path str, None | Some (a,c) -> OpamSystem.real_path a, Some c type repository_name = OpamRepositoryName.t type repository_root = dirname type 'a repository_name_map = 'a OpamRepositoryName.Map.t type repository_kind = [`http|`local|`git|`darcs|`hg] let guess_repository_kind kind (address, ext) = match kind with | Some k -> k | None -> if ext = None && Sys.file_exists address then `local else if OpamMisc.starts_with ~prefix:"git" address || OpamMisc.ends_with ~suffix:"git" address then `git else if OpamMisc.starts_with ~prefix:"hg" address then `hg else `http type repository = { repo_root : repository_root; repo_name : repository_name; repo_kind : repository_kind; repo_address : address; repo_priority: int; } let string_of_repository_kind = function | `http -> "http" | `local -> "local" | `git -> "git" | `darcs -> "darcs" | `hg -> "hg" let repository_kind_of_string = function | "wget" | "curl" | "http" -> `http | "rsync" | "local" -> `local | "git" -> `git | "darcs" -> `darcs | "hg" -> `hg | s -> OpamGlobals.error_and_exit "%s is not a valid repository kind." s type variable = OpamVariable.t type full_variable = OpamVariable.Full.t type section = OpamVariable.Section.t type full_section = OpamVariable.Section.Full.t type switch = OpamSwitch.t type switch_set = OpamSwitch.Set.t type 'a switch_map = 'a OpamSwitch.Map.t type file_attribute = OpamFilename.Attribute.t type file_attribute_set = OpamFilename.Attribute.Set.t type compiler = OpamCompiler.t type compiler_set = OpamCompiler.Set.t type 'a compiler_map = 'a OpamCompiler.Map.t type compiler_version = OpamCompiler.Version.t type opam_version = OpamVersion.t type 'a generic_formula = 'a OpamFormula.formula = | Empty | Atom of 'a | Block of 'a generic_formula | And of 'a generic_formula * 'a generic_formula | Or of 'a generic_formula * 'a generic_formula type atom = OpamFormula.atom type formula = OpamFormula.t type 'a conjunction = 'a OpamFormula.conjunction type 'a disjunction = 'a OpamFormula.disjunction type compiler_constraint = OpamCompiler.Version.constr type ppflag = | Camlp4 of string list | Cmd of string list type shell = [`fish|`csh|`zsh|`sh|`bash] let string_of_shell = function | `fish -> "fish" | `csh -> "csh" | `zsh -> "zsh" | `sh -> "sh" | `bash -> "bash" type global_config = { complete : bool; switch_eval: bool; } type user_config = { shell : shell; ocamlinit : bool; dot_profile: filename option; } (* Command line arguments *) (* Upload arguments *) type upload = { upl_opam : filename; upl_descr : filename; upl_archive: filename; } let string_of_upload u = Printf.sprintf "opam=%s descr=%s archive=%s" (OpamFilename.to_string u.upl_opam) (OpamFilename.to_string u.upl_descr) (OpamFilename.to_string u.upl_archive) type config = { conf_is_rec : bool; conf_is_byte: bool; conf_is_link: bool; conf_options: OpamVariable.Section.Full.t list; } type pin_option = | Version of version | Local of dirname | Git of address | Darcs of address | Hg of address | Unpin | Edit type pin_kind = [`version|`git|`darcs|`hg|`local] let repository_kind_of_pin_kind = function | `version -> None | (`git|`darcs|`hg|`local as k) -> Some k let pin_option_of_string ?kind s = match kind with | Some `version -> Version (OpamPackage.Version.of_string s) | Some `git -> Git (address_of_string s) | Some `hg -> Hg (address_of_string s) | Some `darcs -> Darcs (address_of_string s) | Some `local -> Local (OpamFilename.Dir.of_string s) | Some `unpin -> Unpin | None -> if s = "none" then Unpin else if Sys.file_exists s then Local (OpamFilename.Dir.of_string s) else if OpamMisc.contains s ('/') then Git (address_of_string s) else Version (OpamPackage.Version.of_string s) let string_of_pin_kind = function | `version -> "version" | `git -> "git" | `darcs -> "darcs" | `hg -> "hg" | `local -> "local" | `unpin -> "unpin" let pin_kind_of_string = function | "version" -> `version | "git" -> `git | "darcs" -> `darcs | "hg" -> `hg | "rsync" | "local" -> `local | s -> OpamGlobals.error_and_exit "%s is not a valid kind of pinning." s type pin = { pin_package: name; pin_option : pin_option; } let string_of_pin_option = function | Version v -> OpamPackage.Version.to_string v | Git p | Darcs p | Hg p -> string_of_address p | Local p -> OpamFilename.Dir.to_string p | Unpin -> "unpin" | Edit -> "edit" let kind_of_pin_option = function | Version _ -> Some `version | Git _ -> Some `git | Darcs _ -> Some `darcs | Hg _ -> Some `hg | Local _ -> Some `local | _ -> None let option fn = function | None -> "" | Some k -> fn k let string_of_pin p = Printf.sprintf "{package=%s; path=%s; kind=%s}" (OpamPackage.Name.to_string p.pin_package) (string_of_pin_option p.pin_option) (option string_of_pin_kind (kind_of_pin_option p.pin_option)) (** Variable contents *) type variable_contents = OpamVariable.variable_contents = | B of bool | S of string type variable_map = OpamVariable.variable_contents OpamVariable.Map.t type symbol = | Eq | Neq | Le | Ge | Lt | Gt let string_of_symbol = function | Eq -> "=" | Neq -> "!=" | Ge -> ">=" | Le -> "<=" | Gt -> ">" | Lt -> "<" type filter = | FBool of bool | FString of string | FIdent of string | FOp of filter * symbol * filter | FAnd of filter * filter | FOr of filter * filter | FNot of filter let rec string_of_filter = function | FBool b -> string_of_bool b | FString s -> Printf.sprintf "%S" s | FIdent i -> i | FOp(e,s,f) -> Printf.sprintf "%s %s %s" (string_of_filter e) (string_of_symbol s) (string_of_filter f) | FAnd (e,f) -> Printf.sprintf "%s & %s" (string_of_filter e) (string_of_filter f) | FOr (e,f) -> Printf.sprintf "%s | %s" (string_of_filter e) (string_of_filter f) | FNot e -> Printf.sprintf "!%s" (string_of_filter e) type simple_arg = | CString of string | CIdent of string type arg = simple_arg * filter option type command = arg list * filter option type 'a optional = { c: 'a; optional: bool; } type stats = { s_install : int; s_reinstall: int; s_upgrade : int; s_downgrade: int; s_remove : int; } (** Untyped generic file format. *) (** Base values *) type value = | Bool of bool | Int of int | String of string | Symbol of string | Ident of string | List of value list | Group of value list | Option of value * value list (** A file section *) type file_section = { section_kind : string; section_name : string; section_items : file_item list; } (** A file is composed of sections and variable definitions *) and file_item = | Section of file_section | Variable of string * value (** A file is a list of items and the filename *) type file = { file_contents: file_item list; file_name : string; file_format : opam_version; } type 'a action = | To_change of 'a option * 'a | To_delete of 'a | To_recompile of 'a type 'a cause = | Use of 'a list | Required_by of 'a list | Upstream_changes | Unknown let action_contents = function | To_change (_, p) | To_recompile p | To_delete p -> p module type ACTION_GRAPH = sig type package include Graph.Sig.I with type V.t = package action include Graph.Oper.S with type g = t module Parallel: OpamParallel.SIG with type G.t = t and type G.V.t = V.t module Topological: sig val iter: (package action -> unit) -> t -> unit val fold: (package action -> 'a -> 'a) -> t -> 'a -> 'a end type solution = { to_remove : package list; to_process: t; root_causes: (package * package cause) list; } val dump_solution: solution -> unit end module type PKG = sig include Graph.Sig.COMPARABLE val to_string: t -> string val string_of_action: ?causes:(t -> t cause) -> t action -> string end module MakeActionGraph (Pkg: PKG) = struct type package = Pkg.t module Vertex = struct type t = Pkg.t action let compare t1 t2 = Pkg.compare (action_contents t1) (action_contents t2) let hash t = Pkg.hash (action_contents t) let equal t1 t2 = Pkg.equal (action_contents t1) (action_contents t2) end module PG = Graph.Imperative.Digraph.ConcreteBidirectional (Vertex) module Topological = Graph.Topological.Make (PG) module Traverse = Graph.Traverse.Dfs(PG) module Components = Graph.Components.Make(PG) module O = Graph.Oper.I (PG) module Parallel = OpamParallel.Make(struct let string_of_vertex v = Pkg.to_string (action_contents v) include PG include Topological include Traverse include Components end) include PG include O type solution = { to_remove : package list; to_process: t; root_causes: (package * package cause) list; } module Dot = Graph.Graphviz.Dot(struct include PG let edge_attributes _ = [] let default_edge_attributes _ = [] let get_subgraph _ = None let vertex_attributes _ = [] let vertex_name v = Printf.sprintf "%S" (Pkg.string_of_action v) let default_vertex_attributes _ = [] let graph_attributes _ = [] end) let dump_solution g = Dot.output_graph stdout g.to_process end module PackageAction = struct include OpamPackage let string_of_name = OpamPackage.name ++ OpamPackage.Name.to_string let string_of_names ps = String.concat ", " (List.map string_of_name ps) let string_of_cause = function | Upstream_changes -> "[upstream changes]" | Use pkgs -> Printf.sprintf "[use %s]" (string_of_names pkgs) | Required_by pkgs -> Printf.sprintf "[required by %s]" (string_of_names pkgs) | Unknown -> "" let string_of_raw_action = function | To_change (None, p) -> Printf.sprintf " - install %s" (OpamPackage.to_string p) | To_change (Some o, p) -> let f action = Printf.sprintf " - %s %s to %s" action (OpamPackage.to_string o) (OpamPackage.Version.to_string (OpamPackage.version p)) in if OpamPackage.Version.compare (OpamPackage.version o) (OpamPackage.version p) < 0 then f "upgrade" else f "downgrade" | To_recompile p -> Printf.sprintf " - recompile %s" (OpamPackage.to_string p) | To_delete p -> Printf.sprintf " - remove %s" (OpamPackage.to_string p) let string_of_action ?causes a = let causes = match causes with | None -> "" | Some f -> string_of_cause (f (action_contents a)) in match causes with | "" -> string_of_raw_action a | _ -> Printf.sprintf "%s %s" (string_of_raw_action a) causes end module PackageActionGraph = MakeActionGraph(PackageAction) type solution = PackageActionGraph.solution type solver_result = | Nothing_to_do | OK of package action list | Aborted | No_solution | Error of package action list * package action list * package action list type ('a, 'b) result = | Success of 'a | Conflicts of (unit -> 'b) type 'a request = { wish_install: 'a conjunction; wish_remove : 'a conjunction; wish_upgrade: 'a conjunction; } type env = (string * string) list type env_updates = (string * string * string) list type user_action = | Install of name_set | Upgrade of package_set | Reinstall | Depends | Init of name_set | Remove | Switch of name_set | Import of name_set type universe = { u_packages : package_set; u_installed: package_set; u_available: package_set; u_depends : formula package_map; u_depopts : formula package_map; u_conflicts: formula package_map; u_action : user_action; u_installed_roots: package_set; u_pinned : OpamPackage.Version.t Lazy.t name_map; } type 'a updates = { created: 'a; updated: 'a; deleted: 'a; changed: 'a; } type lock = | Read_lock of (unit -> unit) | Global_lock of (unit -> unit) | Switch_lock of (unit -> unit) type tags = OpamMisc.StringSet.t OpamMisc.StringSetMap.t type checksums = string list opam-1.1.1/src/core/opamVariable.ml0000644000175000017500000001052712272210733015371 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) include OpamMisc.Base type variable = t let installed = of_string "installed" let enable = of_string "enable" type variable_contents = | B of bool | S of string let string_of_variable_contents = function | B b -> string_of_bool b | S s -> s module Section = struct include OpamMisc.Base type section = t let section_of_string = of_string let string_of_section = to_string module C = struct type t = string let compare = compare let equal = (=) let hash = Hashtbl.hash end module G = Graph.Imperative.Digraph.ConcreteBidirectional(C) module Topo = Graph.Topological.Make (G) let graph_iter = Topo.iter module Full = struct type t = { package: OpamPackage.Name.t; section: section option; } let create package section = { package; section = Some section } let all package = { package; section = None } let package t = t.package let section t = t.section let of_string str = match OpamMisc.cut_at str '.' with | Some (n,s) -> { package = OpamPackage.Name.of_string n; section = Some (section_of_string s) } | None -> { package = OpamPackage.Name.of_string str; section = None } let to_string t = let n = OpamPackage.Name.to_string t.package in match t.section with | None -> n | Some s -> Printf.sprintf "%s.%s" n (string_of_section s) let to_json x = `String (to_string x) module O = struct type tmp = t type t = tmp let compare = compare let to_string = to_string let to_json = to_json end module Set = OpamMisc.Set.Make (O) module Map = OpamMisc.Map.Make (O) end end module Full = struct type t = { section : Section.Full.t; variable: variable; } let variable t = t.variable let section t = Section.Full.section t.section let package t = Section.Full.package t.section let create_local package section variable = { section = Section.Full.create package section; variable } let create_global package variable = { section = Section.Full.all package; variable } let of_string s = match OpamMisc.rcut_at s ':' with | None -> create_global OpamPackage.Name.global_config (of_string s) | Some (p,v) -> let v = of_string v in match OpamMisc.cut_at p '.' with | None -> create_global (OpamPackage.Name.of_string p) v | Some (p,s) -> create_local (OpamPackage.Name.of_string p) (Section.of_string s) v let to_string t = let package = let n = OpamPackage.Name.to_string (package t) in if n = OpamGlobals.global_config then "" else n in let section = match section t with | None -> "" | Some s -> "." ^ Section.to_string s in let prefix = package ^ section in let prefix = if prefix = "" then "" else prefix ^ ":" in prefix ^ to_string t.variable let to_json x = `String (to_string x) module O = struct type tmp = t type t = tmp let compare = compare let to_string = to_string let to_json = to_json end module Set = OpamMisc.Set.Make(O) module Map = OpamMisc.Map.Make(O) end opam-1.1.1/src/core/opamLexer.mll0000644000175000017500000000776012272210733015104 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) { open OpamParser let newline lexbuf = Lexing.new_line lexbuf let error fmt = Printf.kprintf (fun msg -> raise (OpamTypes.Lexer_error msg)) fmt let char_for_backslash = function | 'n' -> '\010' | 'r' -> '\013' | 'b' -> '\008' | 't' -> '\009' | c -> c let char_for_decimal_code lexbuf i = let c = 100 * (Char.code(Lexing.lexeme_char lexbuf i) - 48) + 10 * (Char.code(Lexing.lexeme_char lexbuf (i+1)) - 48) + (Char.code(Lexing.lexeme_char lexbuf (i+2)) - 48) in if (c < 0 || c > 255) then error "illegal escape sequence" ; Char.chr c let char_for_hexadecimal_code lexbuf i = let d1 = Char.code (Lexing.lexeme_char lexbuf i) in let val1 = if d1 >= 97 then d1 - 87 else if d1 >= 65 then d1 - 55 else d1 - 48 in let d2 = Char.code (Lexing.lexeme_char lexbuf (i+1)) in let val2 = if d2 >= 97 then d2 - 87 else if d2 >= 65 then d2 - 55 else d2 - 48 in Char.chr (val1 * 16 + val2) let buffer_rule r lb = let b = Buffer.create 64 in r b lb ; Buffer.contents b } let space = [' ' '\t' '\r'] let alpha = ['a'-'z' 'A'-'Z' '_'] let digit = ['0'-'9'] let char = ['-' '_' '+'] let achar = alpha | digit | char let ident = alpha achar* (':' achar+)? let symbol = ['=' '<' '>' '!' '+' '|' '&']+ let int = '-'? ['0'-'9']+ rule token = parse | space { token lexbuf } | '\n' { newline lexbuf; token lexbuf } | ":" { COLON } | "{" { LBRACE } | "}" { RBRACE } | "[" { LBRACKET } | "]" { RBRACKET } | "(" { LPAR } | ")" { RPAR } | '\"' { STRING (buffer_rule string lexbuf) } | "(*" { comment 1 lexbuf; token lexbuf } | "#" { comment_line lexbuf; token lexbuf } | "true" { BOOL true } | "false"{ BOOL false } | int { INT (int_of_string (Lexing.lexeme lexbuf)) } | ident { IDENT (Lexing.lexeme lexbuf) } | symbol { SYMBOL (Lexing.lexeme lexbuf) } | eof { EOF } | _ { let token = Lexing.lexeme lexbuf in error "'%s' is not a valid token" token } and string b = parse | '\"' { () } | '\n' { newline lexbuf ; Buffer.add_char b '\n' ; string b lexbuf } | '\\' { Buffer.add_char b (escape lexbuf) ; string b lexbuf } | _ as c { Buffer.add_char b c ; string b lexbuf } | eof { error "unterminated string" } and escape = parse | ['\\' '\"' ''' 'n' 'r' 't' 'b' ' '] as c { char_for_backslash c } | digit digit digit { char_for_decimal_code lexbuf 0 } | 'x' ['0'-'9''a'-'f''A'-'F'] ['0'-'9''a'-'f''A'-'F'] { char_for_hexadecimal_code lexbuf 1 } | "" { error "illegal escape sequence" } and comment n = parse | "*)" { if n > 1 then comment (n-1) lexbuf } | "(*" { comment (n+1)lexbuf } | eof { error "unterminated comment" } | '\n' { newline lexbuf; comment n lexbuf } | _ { comment n lexbuf } and comment_line = parse | [^'\n']* '\n' { newline lexbuf } | [^'\n'] { () } opam-1.1.1/src/core/opamParallel.ml0000644000175000017500000002747112272210733015406 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) let log fmt = OpamGlobals.log "PARALLEL" fmt module type G = sig include Graph.Sig.I include Graph.Topological.G with type t := t and module V := V val has_cycle: t -> bool val scc_list: t -> V.t list list val string_of_vertex: V.t -> string end type error = | Process_error of OpamProcess.result | Internal_error of string | Package_error of string module type SIG = sig module G : G val iter: int -> G.t -> pre:(G.V.t -> unit) -> child:(G.V.t -> unit) -> post:(G.V.t -> unit) -> unit val iter_l: int -> G.vertex list -> pre:(G.V.t -> unit) -> child:(G.V.t -> unit) -> post:(G.V.t -> unit) -> unit val map_reduce: int -> G.t -> map:(G.V.t -> 'a) -> merge:('a -> 'a -> 'a) -> init:'a -> 'a val map_reduce_l: int -> G.vertex list -> map:(G.V.t -> 'a) -> merge:('a -> 'a -> 'a) -> init:'a -> 'a val create: G.V.t list -> G.t exception Errors of (G.V.t * error) list * G.V.t list exception Cyclic of G.V.t list list end module Make (G : G) = struct module G = G module V = struct include G.V let compare = compare end module M = Map.Make (V) module S = Set.Make (V) type t = { graph : G.t ; (* The original graph *) visited: S.t ; (* The visited nodes *) roots : S.t ; (* The current roots *) degree : int M.t ; (* Node degrees *) } let init graph = let degree = ref M.empty in let add_degree v d = degree := M.add v d !degree in let roots = G.fold_vertex (fun v todo -> let d = G.in_degree graph v in if d = 0 then S.add v todo else ( add_degree v d; todo ) ) graph S.empty in { graph ; roots ; degree = !degree ; visited = S.empty } let visit t x = if S.mem x t.visited then invalid_arg "This node has already been visited."; if not (S.mem x t.roots) then invalid_arg "This node is not a root node"; (* Add the node to the list of visited nodes *) let t = { t with visited = S.add x t.visited } in (* Remove the node from the list of root nodes *) let roots = S.remove x t.roots in let degree = ref t.degree in let remove_degree x = degree := M.remove x !degree in let replace_degree x d = degree := M.add x d (M.remove x !degree) in (* Update the children of the node by decreasing by 1 their in-degree *) let roots = G.fold_succ (fun x l -> let d = M.find x t.degree in if d = 1 then ( remove_degree x; S.add x l ) else ( replace_degree x (d-1); l ) ) t.graph x roots in { t with roots; degree = !degree } (* the [Unix.wait] might return a processus which has not been created by [Unix.fork]. [wait pids] waits until a process in [pids] terminates. *) (* XXX: this will not work under windows *) let string_of_pids pids = Printf.sprintf "{%s}" (String.concat "," (OpamMisc.IntMap.fold (fun e _ l -> string_of_int e :: l) pids [])) let string_of_status st = let st, n = match st with | Unix.WEXITED n -> "exit", n | Unix.WSIGNALED n -> "signal", n | Unix.WSTOPPED n -> "stop", n in Printf.sprintf "%s %d" st n let wait pids = let rec aux () = let pid, status = Unix.wait () in if OpamMisc.IntMap.mem pid pids then ( log "%d is dead (%s)" pid (string_of_status status); pid, status ) else ( log "%d: unknown child (pids=%s)!" pid (string_of_pids pids); aux () ) in try aux () with Sys.Break as e -> OpamGlobals.msg " Interrupted!\n"; ignore (aux ()); raise e exception Errors of (G.V.t * error) list * G.V.t list exception Cyclic of G.V.t list list let (--) = S.diff let (++) = S.union let (=|=) s1 s2 = S.cardinal s1 = S.cardinal s2 (* write and close the output channel *) let write_error oc r = log "write_error"; Marshal.to_channel oc r []; close_out oc (* read and close the input channel *) let read_error ic = log "read_error"; let r : error = try Marshal.from_channel ic with _ -> Internal_error "Cannot read the error file" in close_in ic; r let iter n g ~pre ~child ~post = let t = ref (init g) in (* pid -> node * (fd to read the error code) *) let pids = ref OpamMisc.IntMap.empty in (* The nodes to process *) let todo = ref (!t.roots) in (* node -> error *) let errors = ref M.empty in (* All the node with a current worker currently doing some processing. *) let worker_nodes () = OpamMisc.IntMap.fold (fun _ (n, _) accu -> S.add n accu) !pids S.empty in (* All the error nodes. *) let error_nodes () = M.fold (fun n _ accu -> S.add n accu) !errors S.empty in (* All the node not successfully proceeded. This include error worker and error nodes. *) log "Iterate over %d task(s) with %d process(es)" (G.nb_vertex g) n; if G.has_cycle !t.graph then ( let sccs = G.scc_list !t.graph in let sccs = List.filter (fun l -> List.length l > 1) sccs in raise (Cyclic sccs) ); (* nslots is the number of free slots *) let rec loop nslots = if OpamMisc.IntMap.is_empty !pids && (S.is_empty !t.roots || not (M.is_empty !errors) && !t.roots =|= error_nodes ()) then (* Nothing more to do *) if M.is_empty !errors then log "loop completed (without errors)" else (* Generate the remaining nodes in topological order *) let error_nodes = error_nodes () in let remaining = G.fold_vertex (fun v l -> if S.mem v !t.visited || S.mem v error_nodes then l else v::l) !t.graph [] in let remaining = List.rev remaining in raise (Errors (M.bindings !errors, remaining)) else if nslots <= 0 || (worker_nodes () ++ error_nodes ()) =|= !t.roots then ( (* if either 1/ no slots are available or 2/ no action can be performed, then wait for a child process to finish its work *) log "waiting for a child process to finish"; let pid, status = wait !pids in let n, from_child = OpamMisc.IntMap.find pid !pids in pids := OpamMisc.IntMap.remove pid !pids; begin match status with | Unix.WEXITED 0 -> t := visit !t n; (* we execute the 'post' function of the parent process *) post n | _ -> let from_child = from_child () in let error = read_error from_child in errors := M.add n error !errors end; loop (nslots + 1) ) else ( (* otherwise, if the todo list is empty, then refill it *) if S.is_empty !todo then ( log "refilling the TODO list"; todo := !t.roots -- worker_nodes () -- error_nodes (); ); (* finally, if the todo list contains at least a node action, then simply process it *) let n = S.choose !todo in todo := S.remove n !todo; (* Set-up a channel from the child to the parent *) let error_file = OpamSystem.temp_file "error" in (* We execute the 'pre' function before the fork *) pre n; match Unix.fork () with | -1 -> OpamGlobals.error_and_exit "Cannot fork a new process" | 0 -> log "Spawning a new process"; Sys.set_signal Sys.sigint (Sys.Signal_handle (fun _ -> OpamGlobals.error "Interrupted"; exit 1) ); Sys.catch_break true; let return p = let to_parent = open_out_bin error_file in write_error to_parent p; exit 1 in begin (* the 'child' function is executed on the child *) try child n; log "OK"; exit 0 with | OpamSystem.Process_error p -> return (Process_error p) | OpamSystem.Internal_error s -> return (Internal_error s) | OpamGlobals.Package_error s -> return (Package_error s) | e -> let b = OpamMisc.pretty_backtrace () in let e = Printexc.to_string e in let error = if b = "" then e else e ^ "\n" ^ b in return (Internal_error error) end | pid -> log "Creating process %d" pid; let from_child () = open_in_bin error_file in pids := OpamMisc.IntMap.add pid (n, from_child) !pids; loop (nslots - 1) ) in loop n let map_reduce jobs g ~map ~merge ~init = let files = ref [] in let file repo = List.assoc repo !files in let pre repo = let tmpfile = OpamSystem.temp_file "map-reduce" in log "pre %S (%s)"(G.string_of_vertex repo) tmpfile; files := (repo, tmpfile) :: !files in let child repo = log "child %S" (G.string_of_vertex repo); let file = file repo in let result = map repo in let oc = open_out file in Marshal.to_channel oc result [] in let acc = ref init in let post repo = log "post %S" (G.string_of_vertex repo); let file = file repo in let ic = open_in_bin file in let result = try Marshal.from_channel ic with _ -> OpamSystem.internal_error "Cannot read the result file" in close_in ic; Unix.unlink file; files := List.filter (fun (_,f) -> f<>file) !files; acc := merge result !acc in try iter jobs g ~pre ~child ~post; !acc with | Errors (errors,_) -> let string_of_error = function | Process_error r -> OpamProcess.string_of_result r | Package_error s -> s | Internal_error s -> s in List.iter (fun (v, e) -> OpamGlobals.error "While processing %s:\n%s" (G.string_of_vertex v) (string_of_error e); ) errors; OpamGlobals.exit 2 let create l = let g = G.create () in List.iter (G.add_vertex g) l; g let map_reduce_l jobs list ~map ~merge ~init = match list with | [] -> init | [elt] -> merge (map elt) init | _ -> if jobs = 1 then List.fold_left (fun acc repo -> merge (map repo) acc) init list else let g = create list in map_reduce jobs g ~map ~merge ~init let iter_l jobs list ~pre ~child ~post = match list with | [] -> () | [elt] -> pre elt; child elt; post elt | list -> if jobs = 1 then List.iter (fun elt -> pre elt; child elt; post elt) list else let g = create list in iter jobs g ~pre ~post ~child end opam-1.1.1/src/core/core.ocp0000644000175000017500000000127112272210733014064 0ustar i33173i33173comp += [ "-warn-error" "A" ] begin library "opam-core" files = [ "opamScript.ml" "opamJson.ml" "opamMisc.ml" "opamGlobals.ml" "opamGitVersion.ml" "opamVersion.ml" "opamProcess.ml" "opamSystem.ml" "opamParallel.ml" "opamFilename.ml" "opamSwitch.ml" "opamPackage.ml" "opamFormula.ml" "opamCompiler.ml" "opamVariable.ml" "opamRepositoryName.ml" "opamTypes.ml" "opamFormat.ml" "opamParser.mly" "opamLexer.mll" "opamLineLexer.mll" "opamPath.ml" "opamFile.ml" "opamRepository.ml" "opamFilter.ml" ] requires = [ "cudf" "dose" "unix" "graph" "re_glob" "re_str" ] end opam-1.1.1/src/core/opamPath.ml0000644000175000017500000001524312272210733014540 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) open OpamTypes open OpamFilename.OP type t = dirname let root () = OpamFilename.Dir.of_string !OpamGlobals.root_dir let config t = t // "config" let state_cache t = t // "state.cache" let update_cache t = t // "update.cache" let lock t = t // "lock" let aliases t = t // "aliases" let packages_dir t = t / "packages" let packages t nv = packages_dir t / OpamPackage.Name.to_string (OpamPackage.name nv) / OpamPackage.to_string nv let opam t nv = packages t nv // "opam" let url t nv = packages t nv // "url" let descr t nv = packages t nv // "descr" let archives_dir t = t / "archives" let archive t nv = archives_dir t // (OpamPackage.to_string nv ^ "+opam.tar.gz") let files t nv = packages t nv / "files" let compilers_dir t = t / "compilers" let compilers t c = compilers_dir t / OpamCompiler.Version.to_string (OpamCompiler.version c) / OpamCompiler.to_string c let compiler_comp t c = compilers t c // (OpamCompiler.to_string c ^ ".comp") let compiler_descr t c = compilers t c // (OpamCompiler.to_string c ^ ".descr") let package_index t = t / "repo" // "package-index" let compiler_index t = t / "repo" // "compiler-index" let init t = t / "opam-init" let log t = t / "log" let dev_packages_dir t = t / "packages.dev" let dev_package t nv = dev_packages_dir t / OpamPackage.to_string nv let backup_file () = Unix.( let tm = gmtime OpamGlobals.global_start_time in Printf.sprintf "state-%04d%02d%02d%02d%02d%02d.export" (tm.tm_year+1900) tm.tm_mon tm.tm_mday tm.tm_hour tm.tm_min tm.tm_sec ) let backup_dir t = t / "backup" let backup t = backup_dir t // backup_file () module Switch = struct let root t a = t / OpamSwitch.to_string a let lock t a = root t a // "lock" let backup_dir t a = root t a / "backup" let backup t a = backup_dir t a // backup_file () let lib_dir t a = root t a / "lib" let lib t a n = lib_dir t a / OpamPackage.Name.to_string n let stublibs t a = lib_dir t a / "stublibs" let toplevel t a = lib_dir t a / "toplevel" let doc_dir t a = root t a / "doc" let man_dir ?num t a = match num with | None -> root t a / "man" | Some n -> root t a / "man" / ("man" ^ n) let share_dir t a = root t a / "share" let share t a n = share_dir t a / OpamPackage.Name.to_string n let etc_dir t a = root t a / "etc" let etc t a n = etc_dir t a / OpamPackage.Name.to_string n let doc t a n = doc_dir t a / OpamPackage.Name.to_string n let bin t a = root t a / "bin" let sbin t a = root t a / "sbin" let installed t a = root t a // "installed" let installed_roots t a = root t a // "installed.roots" let build_dir t a = root t a / "build" let build t a nv = build_dir t a / OpamPackage.to_string nv let build_ocaml t a = build_dir t a / "ocaml" let build_install t a nv = build t a nv // (OpamPackage.Name.to_string (OpamPackage.name nv) ^ ".install") let build_config t a nv = build t a nv // (OpamPackage.Name.to_string (OpamPackage.name nv) ^ ".config") let install_dir t a = root t a / "install" let install t a n = install_dir t a // (OpamPackage.Name.to_string n ^ ".install") let reinstall t a = root t a // "reinstall" let config_dir t a = root t a / "config" let config t a n = config_dir t a // (OpamPackage.Name.to_string n ^ ".config") let pinned t a = root t a // "pinned" let dev_packages_dir t a = root t a / "packages.dev" let dev_package t a nv = dev_packages_dir t a / OpamPackage.to_string nv module Overlay = struct let dir t a = root t a / "overlay" let package t a nv = dir t a / OpamPackage.to_string nv let opam t a nv = package t a nv // "opam" let url t a nv = package t a nv // "url" let descr t a nv = package t a nv // "descr" let files t a nv = package t a nv / "files" end end module Repository = struct let root t = t.repo_root let update_cache t = root t // "update.cache" let create root name = root / "repo" / OpamRepositoryName.to_string name let repo t = root t // "repo" let remote_repo t = OpamFilename.raw_dir (fst t.repo_address) // "repo" let raw_config root name = root / "repo" / OpamRepositoryName.to_string name // "config" let config t = root t // "config" let packages_dir t = root t / "packages" let remote_packages_dir t = OpamFilename.raw_dir (fst t.repo_address) / "packages" let packages t prefix nv = match prefix with | None -> packages_dir t / OpamPackage.to_string nv | Some p -> packages_dir t / p / OpamPackage.to_string nv let opam t prefix nv = packages t prefix nv // "opam" let descr t prefix nv = packages t prefix nv // "descr" let url t prefix nv = packages t prefix nv // "url" let files t prefix nv = packages t prefix nv / "files" let archives_dir t = root t / "archives" let archive t nv = archives_dir t // (OpamPackage.to_string nv ^ "+opam.tar.gz") let remote_archive t nv = OpamFilename.raw_dir (fst t.repo_address) / "archives" // (OpamPackage.to_string nv ^ "+opam.tar.gz") let upload_dir t = root t / "upload" let compilers_dir t = root t / "compilers" let remote_compilers_dir t = OpamFilename.raw_dir (fst t.repo_address) / "compilers" let compiler_comp t prefix c = match prefix with | None -> compilers_dir t // (OpamCompiler.to_string c ^ ".comp") | Some p -> compilers_dir t / p // (OpamCompiler.to_string c ^ ".comp") let compiler_descr t prefix c = match prefix with | None -> compilers_dir t // (OpamCompiler.to_string c ^ ".descr") | Some p -> compilers_dir t / p // (OpamCompiler.to_string c ^ ".descr") end opam-1.1.1/src/core/opamTypes.mli0000644000175000017500000003213612272210733015121 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) (** Common types used by other modules *) (** {2 Exceptions} *) exception Lexer_error of string (** {2 Filenames} *) (** Basenames *) type basename = OpamFilename.Base.t (** Directory names *) type dirname = OpamFilename.Dir.t (** Filenames *) type filename = OpamFilename.t (** Set of files *) type filename_set = OpamFilename.Set.t (** Map of files *) type 'a filename_map = 'a OpamFilename.Map.t (** Generalized file type *) type generic_file = OpamFilename.generic_file = | D of dirname | F of filename (** Download result *) type 'a download = | Up_to_date of 'a | Not_available of string | Result of 'a (** Upcast a downloaded directory. *) val download_dir: dirname download -> generic_file download (** Upcast a downloaded file. *) val download_file: filename download -> generic_file download (** {2 Packages} *) (** Packages are ([name] * [version]) tuple *) type package = OpamPackage.t (** Set of packages *) type package_set = OpamPackage.Set.t (** Map of packages *) type 'a package_map = 'a OpamPackage.Map.t (** Package names *) type name = OpamPackage.Name.t (** Set of package names *) type name_set = OpamPackage.Name.Set.t (** Map of package names *) type 'a name_map = 'a OpamPackage.Name.Map.t (** Package versions *) type version = OpamPackage.Version.t (** Set of package versions *) type version_set = OpamPackage.Version.Set.t (** {2 Compilers} *) (** Compiler names *) type compiler = OpamCompiler.t (** Set of compiler names *) type compiler_set = OpamCompiler.Set.t (** Maps of compiler names *) type 'a compiler_map = 'a OpamCompiler.Map.t (** Compiler versions *) type compiler_version = OpamCompiler.Version.t (** OPAM versions *) type opam_version = OpamVersion.t (** Compiler constraints *) type compiler_constraint = OpamCompiler.Version.constr (** {2 Variables} *) (** Variables *) type variable = OpamVariable.t (** Fully qualified variables (ie. with the name of sections/sub-sections they appear in) *) type full_variable = OpamVariable.Full.t (** Section names *) type section = OpamVariable.Section.t (** Fully qualified section names *) type full_section = OpamVariable.Section.Full.t (** Content of user-defined variables *) type variable_contents = OpamVariable.variable_contents = | B of bool | S of string (** A map from variables to their contents (i.e an environment) *) type variable_map = OpamVariable.variable_contents OpamVariable.Map.t (** Content of [pp] variables *) type ppflag = | Camlp4 of string list | Cmd of string list (** {2 Formulas} *) (** A generic formula *) type 'a generic_formula = 'a OpamFormula.formula = | Empty | Atom of 'a | Block of 'a generic_formula | And of 'a generic_formula * 'a generic_formula | Or of 'a generic_formula * 'a generic_formula (** Formula atoms *) type atom = OpamFormula.atom (** Formula over versionned packages *) type formula = OpamFormula.t (** AND formulat *) type 'a conjunction = 'a OpamFormula.conjunction (** OR formulat *) type 'a disjunction = 'a OpamFormula.disjunction (** {2 Repositories} *) (** Repository names *) type repository_name = OpamRepositoryName.t (** Maps of repository names *) type 'a repository_name_map = 'a OpamRepositoryName.Map.t (** Repository kind *) type repository_kind = [`http|`local|`git|`darcs|`hg] (** Repository address *) type address = string * string option (** Print an address *) val string_of_address: address -> string (** Parse an address *) val address_of_string: string -> address (** Guess the repository kind *) val guess_repository_kind: repository_kind option -> address -> repository_kind (** Pretty-print repository kinds. *) val string_of_repository_kind: [`http|`local|`git|`darcs|`hg] -> string (** Parser of repository kinds. Raise an error if the kind is not valid. *) val repository_kind_of_string: string -> [`http|`local|`git|`darcs|`hg] (** Repository root *) type repository_root = dirname (** Repositories *) type repository = { repo_root : repository_root; repo_name : repository_name; repo_kind : repository_kind; repo_address : address; repo_priority: int; } (** {2 Solver} *) (** The solver answers a list of actions to perform *) type 'a action = (** The package must be installed. The package could have been present or not, but if present, it is another version than the proposed solution. *) | To_change of 'a option * 'a (** The package must be deleted. *) | To_delete of 'a (** The package is already installed, but it must be recompiled. *) | To_recompile of 'a (** The possible causes of an action. *) type 'a cause = | Use of 'a list | Required_by of 'a list | Upstream_changes | Unknown (** Extract a package from a package action. *) val action_contents: 'a action -> 'a (** Graph of package actions *) module type ACTION_GRAPH = sig type package include Graph.Sig.I with type V.t = package action include Graph.Oper.S with type g = t (** Parallel iterator *) module Parallel: OpamParallel.SIG with type G.t = t and type G.V.t = V.t (** Topological traversal *) module Topological: sig val iter: (package action -> unit) -> t -> unit val fold: (package action -> 'a -> 'a) -> t -> 'a -> 'a end (** Solver solution *) type solution = { to_remove : package list; to_process: t; root_causes: (package * package cause) list; } (** Dump a solution graph *) val dump_solution: solution -> unit end (** Signature of packages *) module type PKG = sig include Graph.Sig.COMPARABLE (** Pretty printing of packages *) val to_string: t -> string (** Pretty-printing of package actions *) val string_of_action: ?causes:(t -> t cause) -> t action -> string end (** Functor to create a graph af actions *) module MakeActionGraph (Pkg:PKG): ACTION_GRAPH with type package = Pkg.t (** Package actions *) module PackageAction: PKG with type t = package (** Graph of OPAM packages *) module PackageActionGraph: ACTION_GRAPH with type package = package (** The type for solutions *) type solution = PackageActionGraph.solution (** Solver result *) type solver_result = | Nothing_to_do | OK of package action list (** List of successful actions *) | Aborted | No_solution | Error of package action list * package action list * package action list (** List of successful actions, list of actions with errors, list of remaining undone actions *) (** Solver result *) type ('a, 'b) result = | Success of 'a | Conflicts of (unit -> 'b) (** Solver request *) type 'a request = { wish_install: 'a conjunction; wish_remove : 'a conjunction; wish_upgrade: 'a conjunction; } (** user request action *) type user_action = | Install of name_set (** The 'root' packages to be installed *) | Upgrade of package_set (** The subset of packages to upgrade *) | Reinstall | Depends | Init of name_set (** The 'root' packages to be installed *) | Remove | Switch of name_set (** The 'root' packages to be installed *) | Import of name_set (** The 'root' packages to be installed *) (** Solver universe *) type universe = { u_packages : package_set; u_installed: package_set; u_available: package_set; u_depends : formula package_map; u_depopts : formula package_map; u_conflicts: formula package_map; u_action : user_action; u_installed_roots: package_set; u_pinned : OpamPackage.Version.t Lazy.t name_map; } (** {2 Command line arguments} *) (** Upload arguments *) type upload = { upl_opam : filename; upl_descr : filename; upl_archive: filename; } (** Pretty-print *) val string_of_upload: upload -> string (** Pinned packages options *) type pin_option = | Version of version | Local of dirname | Git of address | Darcs of address | Hg of address | Unpin | Edit (** Pinned packages *) type pin = { pin_package: name; pin_option : pin_option; } (** Pretty-printing of pinned packages *) val string_of_pin: pin -> string (** Pin kind *) type pin_kind = [`version|`git|`darcs|`hg|`local] (** Convert a pin kind to a repository kind *) val repository_kind_of_pin_kind: pin_kind -> repository_kind option (** Pretty-printing of pin kinds. *) val pin_kind_of_string: string -> pin_kind (** Parsing of pin kinds. Raise an error if it is not a valid value. *) val string_of_pin_kind: pin_kind -> string (** Read pin options args *) val pin_option_of_string: ?kind:pin_kind -> string -> pin_option (** Convert a pin option to a string *) val string_of_pin_option: pin_option -> string (** Get the pin kind from a pin option *) val kind_of_pin_option: pin_option -> pin_kind option (** Configuration requests *) type config = { conf_is_rec : bool; conf_is_byte: bool; conf_is_link: bool; conf_options: OpamVariable.Section.Full.t list; } (** Shell compatibility modes *) type shell = [`fish|`csh|`zsh|`sh|`bash] (** Pretty-print *) val string_of_shell: shell -> string (** Global configuration option *) type global_config = { complete : bool; switch_eval: bool; } (** User configuration option *) type user_config = { shell : shell; ocamlinit : bool; dot_profile: filename option; } (** {2 Filtered commands} *) (** Symbols *) type symbol = | Eq | Neq | Le | Ge | Lt | Gt (** Pretty print *) val string_of_symbol: symbol -> string (** Filter *) type filter = | FBool of bool | FString of string | FIdent of string | FOp of filter * symbol * filter | FAnd of filter * filter | FOr of filter * filter | FNot of filter (** Pretty print *) val string_of_filter: filter -> string (** A command argument *) type simple_arg = | CString of string | CIdent of string (** Command argument *) type arg = simple_arg * filter option (** Command *) type command = arg list * filter option (** {2 Untyped generic file format} *) (** Base values *) type value = | Bool of bool | Int of int | String of string | Symbol of string | Ident of string | List of value list | Group of value list | Option of value * value list (** A file section *) type file_section = { section_kind : string; section_name : string; section_items : file_item list; } (** A file is composed of sections and variable definitions *) and file_item = | Section of file_section | Variable of string * value (** A file is a list of items and the filename *) type file = { file_contents: file_item list; file_name : string; file_format : opam_version; } (** {2 Switches} *) (** Compiler switches *) type switch = OpamSwitch.t (** Set of compiler switches *) type switch_set = OpamSwitch.Set.t (** Map of compile switches *) type 'a switch_map = 'a OpamSwitch.Map.t (** {2 Misc} *) (** The different kinds of locks *) type lock = (** The function does not modify anything, but it needs the state not to change while it is running. *) | Read_lock of (unit -> unit) (** Take the global lock, all subsequent calls to OPAM are blocked. *) | Global_lock of (unit -> unit) (** Take the lock only for [OpamGlobals.current_switch] if it not [None], otherwise for the current lock. We do not pass the switch directly as argument as we might need to read some configuration file and we thus need to take the global loock for a short time. *) | Switch_lock of (unit -> unit) (** A line in {i urls.tx} *) type file_attribute = OpamFilename.Attribute.t (** All the lines in {i urls.txt} *) type file_attribute_set = OpamFilename.Attribute.Set.t (** Optional contents *) type 'a optional = { c : 'a; (** Contents *) optional: bool; (** Is the contents optional *) } (** Upgrade statistics *) type stats = { s_install : int; s_reinstall: int; s_upgrade : int; s_downgrade: int; s_remove : int; } (** Environement variables *) type env = (string * string) list (** Environment updates *) type env_updates = (string * string * string) list (** Tags *) type tags = OpamMisc.StringSet.t OpamMisc.StringSetMap.t (** {2 Repository and global states} *) (** Checksums *) type checksums = string list (** {2 JSON} *) type json = OpamJson.t (** {2 Updates} *) type 'a updates = { created: 'a; updated: 'a; deleted: 'a; changed: 'a; } opam-1.1.1/src/core/opamProcess.mli0000644000175000017500000000726312272210733015436 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) (** Process handling *) (** The type for processes *) type t = { p_name : string; (** Command name *) p_args : string list; (** Command args *) p_pid : int; (** Process PID *) p_cwd : string; (** Process initial working directory *) p_time : float; (** Process start time *) p_stdout : string option; (** stdout dump file *) p_stderr : string option; (** stderr dump file *) p_env : string option; (** dump environment variables *) p_info : string option; (** dump process info *) p_metadata: (string * string) list (** Metadata associated to the process *) } (** [create cmd args] create a new process to execute the command [cmd] with arguments [args]. If [stdout_file] or [stderr_file] are set, the channels are redirected to the corresponding files. The outputs are discarded is [verbose] is set to false. The current environment can also be overriden if [env] is set. The environment which is used to run the process is recorded into [env_file] (if set). *) val create : ?info_file:string -> ?env_file:string -> ?stdout_file:string -> ?stderr_file:string -> ?env:string array -> ?metadata:(string*string) list -> verbose:bool -> string -> string list -> t (** Process results *) type result = { r_code : int; (** Process exit code *) r_duration : float; (** Process duration *) r_info : (string * string) list; (** Process info *) r_stdout : string list; (** Content of stdout dump file *) r_stderr : string list; (** Content of stderr dump file *) r_cleanup : string list; (** List of files to clean-up *) } (** [wait p] waits for the processus [p] to end and returns its results. *) val wait: t -> result (** [run ~name cmd args] synchronously call the command [cmd] with arguments [args]. It waits until the process is finished. The file [name.info], [name.env], [name.out] and [name.err] and are created, and contains the process main description, the environment variables, the standard output and the standard error. *) val run : ?env:string array -> ?verbose:bool -> ?name:string -> ?metadata:(string*string) list -> string -> string list -> result (** Is the process result a success ? *) val is_success : result -> bool (** Is the process result a failure ? *) val is_failure : result -> bool (** Clean-up process result files *) val clean_files : result -> unit (** {2 Misc} *) val read_lines: string -> string list (** Pretty printing of process. *) val string_of_result: ?color:OpamGlobals.text_style -> result -> string opam-1.1.1/src/core/opamJson.mli0000644000175000017500000005171712272210733014734 0ustar i33173i33173(*--------------------------------------------------------------------------- Copyright (c) 2012 Daniel C. Bünzli. All rights reserved. Distributed under the BSD3 license, see license at the end of the file. jsonm release 0.9.1 ---------------------------------------------------------------------------*) (** Non-blocking streaming JSON codec. [Jsonm] is a non-blocking streaming codec to {{!section:decode}decode} and {{!section:encode}encode} the {{:http://tools.ietf.org/html/rfc4627}JSON} data format. It can process JSON text without blocking on IO and without a complete in-memory representation of the data. The {{!Uncut}uncut codec} also processes whitespace and (non-standard) JSON with JavaScript comments. Consult the {{!datamodel}data model}, {{!limitations}limitations} and {{!examples}examples} of use. {e Version 0.9.1 - Daniel Bünzli } {3 References} {ul {- D. Crockford {e {{:http://tools.ietf.org/html/rfc4627}JSON The application/json Media Type for JavaScript Object Notation (JSON)}}, 2006.}} *) (** {1:datamodel JSON data model} *) type lexeme = [ | `Null | `Bool of bool | `String of string | `Float of float | `Name of string | `As | `Ae | `Os | `Oe ] (** The type for JSON lexemes. [`As] and [`Ae] start and end arrays and [`Os] and [`Oe] start and end objects. [`Name] is for the member names of objects. A {e well-formed} sequence of lexemes belongs to the language of the [json] grammar: {[ json = object / array object = `Os *member `Oe member = (`Name s) value array = `As *value `Ae value = `Null / `Bool b / `Float f / `String s / object / array ]} A {{!section:decode}decoder} returns only well-formed sequences of lexemes or [`Error]s are returned. The {{:http://tools.ietf.org/html/rfc3629}UTF-8}, {{:http://tools.ietf.org/html/rfc2781}UTF-16}, UTF-16LE and UTF-16BE encoding schemes are supported. The strings of decoded [`Name] and [`String] lexemes are however always UTF-8 encoded. In these strings, characters originally escaped in the input are in their unescaped representation. An {{!section:encode}encoder} accepts only well-formed sequences of lexemes or [Invalid_argument] is raised. Only the UTF-8 encoding scheme is supported. The strings of encoded [`Name] and [`String] lexemes are assumed to be immutable and must be UTF-8 encoded, this is {b not} checked by the module. In these strings, the delimiter characters [U+0022] and [U+005C] (['"'], ['\']) aswell as the control characters [U+0000-U+001F] are automatically escaped by the encoders, as mandated by the standard. *) val pp_lexeme : Format.formatter -> [< lexeme] -> unit (** [pp_lexeme ppf l] prints a unspecified non-JSON representation of [l] on [ppf]. *) (** {1:decode Decode} *) type error = [ | `Illegal_BOM | `Illegal_escape of [ `Not_hex_uchar of int | `Not_esc_uchar of int | `Not_lo_surrogate of int | `Lone_lo_surrogate of int | `Lone_hi_surrogate of int ] | `Illegal_string_uchar of int | `Illegal_bytes of string | `Illegal_literal of string | `Illegal_number of string | `Unclosed of [ `As | `Os | `String | `Comment ] | `Expected of [ `Comment | `Value | `Name | `Name_sep | `Json | `Eoi | `Aval of bool (* [true] if first array value *) | `Omem of bool (* [true] if first object member *) ]] (** The type for decoding errors. *) val pp_error : Format.formatter -> [< error] -> unit (** [pp_error e] prints an unspecified UTF-8 representation of [e] on [ppf]. *) type encoding = [ `UTF_8 | `UTF_16 | `UTF_16BE | `UTF_16LE ] (** The type for Unicode encoding schemes. *) type src = [ `Channel of in_channel | `String of string | `Manual ] (** The type for input sources. With a [`Manual] source the client must provide input with {!Manual.src}. *) type decoder (** The type for JSON decoders. *) val decoder :?encoding:[< encoding] -> [< src] -> decoder (** [decoder encoding src] is a JSON decoder that inputs from [src]. [encoding] specifies the character encoding of the data. If unspecified the encoding is guessed as {{:http://tools.ietf.org/html/rfc4627#section-3}suggested} by the standard. *) val decode : decoder -> [> `Await | `Lexeme of lexeme | `End | `Error of error ] (** [decode d] is: {ul {- [`Await] if [d] has a [`Manual] source and awaits for more input. The client must use {!Manual.src} to provide it.} {- [`Lexeme l] if a lexeme [l] was decoded.} {- [`End] if the end of input was reached.} {- [`Error e] if a decoding error occured. If the client is interested in a best-effort decoding it can still continue to decode after an error (see {!errorrecovery}) although the resulting sequence of [`Lexeme]s is undefined and may not be well-formed.}} The {!Uncut.pp_decode} function can be used to inspect decode results. {b Note.} Repeated invocation always eventually returns [`End], even in case of errors. *) val decoded_range : decoder -> (int * int) * (int * int) (** [decoded_range d] is the range of characters spanning the last [`Lexeme] or [`Error] (or [`White] or [`Comment] for an {!Uncut.decode}) decoded by [d]. A pair of line and column numbers respectively one and zero based. *) val decoder_encoding : decoder -> encoding (** [decoder_encoding d] is [d]'s encoding. {b Warning.} If the decoder guesses the encoding, rely on this value only after the first [`Lexeme] was decoded. *) val decoder_src : decoder -> src (** [decoder_src d] is [d]'s input source. *) (** {1:encode Encode} *) type dst = [ `Channel of out_channel | `Buffer of Buffer.t | `Manual ] (** The type for output destinations. With a [`Manual] destination the client must provide output storage with {!Manual.dst}. *) type encoder (** The type for JSON encoders. *) val encoder : ?minify:bool -> [< dst] -> encoder (** [encoder minify dst] is an encoder that outputs to [dst]. If [minify] is [true] (default) the output is made as compact as possible, otherwise the output is indented. If you want better control on whitespace use [minify = true] and {!Uncut.encode}. *) val encode : encoder -> [< `Await | `End | `Lexeme of lexeme ] -> [`Ok | `Partial] (** [encode e v] is: {ul {- [`Partial] iff [e] has a [`Manual] destination and needs more output storage. The client must use {!Manual.dst} to provide a new buffer and then call {!encode} with [`Await] until [`Ok] is returned.} {- [`Ok] when the encoder is ready to encode a new [`Lexeme] or [`End].}} For [`Manual] destinations, encoding [`End] always returns [`Partial], the client should as usual use {!Manual.dst} and continue with [`Await] until [`Ok] is returned at which point {!Manual.dst_rem} [e] is guaranteed to be the size of the last provided buffer (i.e. nothing was written). {b Raises.} [Invalid_argument] if a non {{!datamodel}well-formed} sequence of lexemes is encoded or if [`Lexeme] or [`End] is encoded after a [`Partial] encode. *) val encoder_dst : encoder -> dst (** [encoder_dst e] is [e]'s output destination. *) val encoder_minify : encoder -> bool (** [encoder_minify e] is [true] if [e]'s output is minified. *) (** {1:manual Manual sources and destinations} *) (** Manual input sources and output destinations. {b Warning.} Use only with [`Manual] decoders and encoders. *) module Manual : sig val src : decoder -> string -> int -> int -> unit (** [src d s j l] provides [d] with [l] bytes to read, starting at [j] in [s]. This byte range is read by calls to {!decode} until [`Await] is returned. To signal the end of input call the function with [l = 0]. *) val dst : encoder -> string -> int -> int -> unit (** [dst e s j l] provides [e] with [l] bytes to write, starting at [j] in [s]. This byte rang is written by calls to {!encode} with [e] until [`Partial] is returned. Use {!dst_rem} to know the remaining number of non-written free bytes in [s]. *) val dst_rem : encoder -> int (** [dst_rem e] is the remaining number of non-written, free bytes in the last buffer provided with {!dst}. *) end (** {1:uncut Uncut codec} *) (** Codec with comments and whitespace. The uncut codec also processes whitespace and JavaScript comments. The latter is non-standard JSON, fail on [`Comment] decoding if you want to process whitespace but stick to the standard. The uncut codec preserves as much of the original input as possible. Perfect round-trip with [Jsonm] is however impossible for the following reasons: {ul {- Escapes unescaped by the decoder may not be escaped or escaped differently by the encoder.} {- The encoder automatically inserts name separator [':'] and value separators [","]. If you just reencode the sequence of decodes, whitespace and comments may (harmlessly, but significantly) commute with these separators.} {- Internally the encoder uses [U+000A] (['\n']) for newlines.} {- [`Float] lexemes may be rewritten differently by the encoder.}} *) module Uncut : sig (** {1:uncutdatamodel Uncut data model} The uncut data model is the same as the regular {{!datamodel}data model}, except that before or after any lexeme you may decode/encode one or more: {ul {- [`White w], representing JSON whitespace [w]. On input the sequence CR ([U+000D]) and CRLF (<[U+000A], [U+000A]>) are normalized to [U+000A]. The string [w] must be a sequence of [U+0020], [U+0009], [U+000A] or [U+000D] characters ([' '], ['\t'], ['\n'], ['\r']).} {- [`Comment (`S, c)], representing a JavaScript single line comment [c]. [c] is the comment's content without the starting [//] and the ending newline. The string [c] must not contain any newline. } {- [`Comment (`M, c)], representing a JavaScript multi-line comment [c]. [c] is the comment's content without the starting [/*] and the ending [*/]. The string [c] must not contain the sequence [*/]. }} {b Warning.} {!Uncut.encode} does not check the above constraints on [w] and [c]. *) (** {1 Decode} *) val decode : decoder -> [ `Await | `Lexeme of lexeme | `White of string | `Comment of [ `S | `M ] * string | `End | `Error of error ] (** [decode d] is like {!Jsonm.decode} but for the {{!uncutdatamodel}uncut data model}. *) val pp_decode : Format.formatter -> [< `Await | `Lexeme of lexeme | `White of string | `Comment of [ `S | `M ] * string | `End | `Error of error ] -> unit (** [pp_decode ppf v] prints an unspecified representation of [v] on [ppf]. *) (** {1 Encode} *) val encode : encoder -> [< `Await | `Lexeme of lexeme | `White of string | `Comment of [`S | `M] * string | `End ] -> [`Ok | `Partial] (** [encode] is like {!Jsonm.encode} but for the {{!uncutdatamodel} uncut data model}. {b IMPORTANT.} Never encode [`Comment] for the web, it is non-standard and breaks interoperability. *) end (** {1:limitations Limitations} {2 Decode} Decoders parse valid JSON with the following limitations: {ul {- JSON numbers are represented with OCaml [float] values. This means that it can only represent integers exactly in the in the interval \[-2{^53};2{^53}\]. This is equivalent to the contraints JavaScript has.} {- A superset of JSON numbers is parsed. After having seen a minus or a digit, including zero, {!Pervasives.float_of_string}, is used. In particular this parses number with leading zeros, which are specifically prohibited by the standard.} {- Strings returned by [`String], [`Name], [`White] and [`Comment] are limited by {!Sys.max_string_length}. There is no built-in protection against the fact that the internal OCaml [Buffer.t] value may raise [Failure] on {!Jsonm.decode}. This should however only be a problem on 32-bits platforms if your strings are greater than 16Mo.}} Position tracking assumes that each decoded Unicode scalar value has a column width of 1. The same assumption may not be made by the display program (e.g. for [emacs]' compilation mode you need to set [compilation-error-screen-columns] to [nil]). The newlines LF ([U+000A]), CR ([U+000D]), and CRLF are all normalized to LF internally. This may have an impact in some corner [`Error] cases. For example the invalid escape sequence [] in a string will be reported as being [`Illegal_escape (`Not_esc_uchar 0x000A)]. {2 Encode} Encoders produce valid JSON provided the {e client} ensures that the following holds. {ul {- All the strings given to the encoder must be valid UTF-8 and immutable. Characters that need to be escaped are automatically escaped by [Jsonm].} {- [`Float] lexemes must not be, {!Pervasives.nan}, {!Pervasives.infinity} or {!Pervasives.neg_infinity}. They are encoded with the format string ["%.16g"], this allows to roundtrip all the integers that can be precisely represented in OCaml [float] values, i.e. the integers in the interval \[-2{^53};2{^53}\]. This is equivalent to the constraints JavaScript has.} {- If the {{!Uncut}uncut} codec is used [`White] must be made of {{!Uncut.uncutdatamodel}JSON whitespace} and [`Comment] must never be encoded.}} *) (** {1:errorrecovery Error recovery} After a decoding error, if best-effort decoding is performed. The following happens before continuing: {ul {- [`Illegal_BOM], the initial {{:http://unicode.org/glossary/#byte_order_mark}BOM} is skipped.} {- [`Illegal_bytes], [`Illegal_escape], [`Illegal_string_uchar], a Unicode {{:http://unicode.org/glossary/#replacement_character}replacement character} ([U+FFFD]) is substituted to the illegal sequence.} {- [`Illegal_literal], [`Illegal_number] the corresponding [`Lexeme] is skipped.} {- [`Expected r], input is discarded until a synchronyzing lexeme that depends on [r] is found.} {- [`Unclosed], the end of input is reached, further decodes will be [`End]}} *) (** {1:examples Examples} {2:filter Trip} The result of [trip src dst] has the JSON from [src] written on [dst]. {[ let trip ?encoding ?minify (src : [`Channel of in_channel | `String of string]) (dst : [`Channel of out_channel | `Buffer of Buffer.t]) = let rec loop d e = match Jsonm.decode d with | `Lexeme _ as v -> ignore (Jsonm.encode e v); loop d e | `End -> ignore (Jsonm.encode e `End); `Ok | `Error err -> `Error (Jsonm.decoded_range d, err) | `Await -> assert false in let d = Jsonm.decoder ?encoding src in let e = Jsonm.encoder ?minify dst in loop d e ]} Using the [`Manual] interface, [trip_fd] does the same but between Unix file descriptors. {[ let trip_fd ?encoding ?minify (fdi : Unix.file_descr) (fdo : Unix.file_descr) = let rec encode fd s e v = match Jsonm.encode e v with `Ok -> () | `Partial -> let rec unix_write fd s j l = let rec write fd s j l = try Unix.single_write fd s j l with | Unix.Unix_error (Unix.EINTR, _, _) -> write fd s j l in let wc = write fd s j l in if wc < l then unix_write fd s (j + wc) (l - wc) else () in unix_write fd s 0 (String.length s - Jsonm.Manual.dst_rem e); Jsonm.Manual.dst e s 0 (String.length s); encode fd s e `Await in let rec loop fdi fdo ds es d e = match Jsonm.decode d with | `Lexeme _ as v -> encode fdo es e v; loop fdi fdo ds es d e | `End -> encode fdo es e `End; `Ok | `Error err -> `Error (Jsonm.decoded_range d, err) | `Await -> let rec unix_read fd s j l = try Unix.read fd s j l with | Unix.Unix_error (Unix.EINTR, _, _) -> unix_read fd s j l in let rc = unix_read fdi ds 0 (String.length ds) in Jsonm.Manual.src d ds 0 rc; loop fdi fdo ds es d e in let ds = String.create 65536 (* UNIX_BUFFER_SIZE in 4.0.0 *) in let es = String.create 65536 (* UNIX_BUFFER_SIZE in 4.0.0 *) in let d = Jsonm.decoder ?encoding `Manual in let e = Jsonm.encoder ?minify `Manual in Jsonm.Manual.dst e es 0 (String.length es); loop fdi fdo ds es d e ]} {2:memsel Member selection} The result of [memsel names src] is the list of string values of members of [src] that have their name in [names]. In this example, decoding errors are silently ignored. {[ let memsel ?encoding names (src : [`Channel of in_channel | `String of string]) = let rec loop acc names d = match Jsonm.decode d with | `Lexeme (`Name n) when List.mem n names -> begin match Jsonm.decode d with | `Lexeme (`String s) -> loop (s :: acc) names d | _ -> loop acc names d end | `Lexeme _ | `Error _ -> loop acc names d | `End -> List.rev acc | `Await -> assert false in loop [] names (Jsonm.decoder ?encoding src) ]} {2:tree Generic JSON representation} A generic OCaml representation of JSON text is the following one. {[ type json = [ `Null | `Bool of bool | `Float of float| `String of string | `A of json list | `O of (string * json) list ] ]} The result of [json_of_src src] is the JSON text from [src] in this representation. The function is tail recursive. {[ exception Escape of ((int * int) * (int * int)) * Jsonm.error let json_of_src ?encoding (src : [`Channel of in_channel | `String of string]) = let dec d = match Jsonm.decode d with | `Lexeme l -> l | `Error e -> raise (Escape (Jsonm.decoded_range d, e)) | `End | `Await -> assert false in let rec value v k d = match v with | `Os -> obj [] k d | `As -> arr [] k d | `Null | `Bool _ | `String _ | `Float _ as v -> k v d | _ -> assert false and arr vs k d = match dec d with | `Ae -> k (`A (List.rev vs)) d | v -> value v (fun v -> arr (v :: vs) k) d and obj ms k d = match dec d with | `Oe -> k (`O (List.rev ms)) d | `Name n -> value (dec d) (fun v -> obj ((n, v) :: ms) k) d | _ -> assert false in let d = Jsonm.decoder ?encoding src in try `JSON (value (dec d) (fun v _ -> v) d) with | Escape (r, e) -> `Error (r, e) ]} The result of [json_to_dst dst json] has the JSON text [json] written on [dst]. The function is tail recursive. {[ let json_to_dst ~minify (dst : [`Channel of out_channel | `Buffer of Buffer.t ]) (json : json) = let enc e l = ignore (Jsonm.encode e (`Lexeme l)) in let rec value v k e = match v with | `A vs -> arr vs k e | `O ms -> obj ms k e | `Null | `Bool _ | `Float _ | `String _ as v -> enc e v; k e and arr vs k e = enc e `As; arr_vs vs k e and arr_vs vs k e = match vs with | v :: vs' -> value v (arr_vs vs' k) e | [] -> enc e `Ae; k e and obj ms k e = enc e `Os; obj_ms ms k e and obj_ms ms k e = match ms with | (n, v) :: ms -> enc e (`Name n); value v (obj_ms ms k) e | [] -> enc e `Oe; k e in let e = Jsonm.encoder ~minify dst in let finish e = ignore (Jsonm.encode e `End) in match json with `A _ | `O _ as json -> value json finish e | _ -> invalid_arg "invalid json text" ]} *) type t = [ `Null | `Bool of bool | `Float of float| `String of string | `A of t list | `O of (string * t) list ] val to_string: t -> string val add: t -> unit val output: unit -> unit val set_output: (string -> unit) -> unit val verbose: unit -> bool (*--------------------------------------------------------------------------- Copyright (c) 2012 Daniel C. Bünzli All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of Daniel C. Bünzli nor the names of contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ---------------------------------------------------------------------------*) opam-1.1.1/src/core/opamCompiler.ml0000644000175000017500000000764612272210733015426 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) open OpamMisc.OP let log fmt = OpamGlobals.log "COMPILER" fmt module Version = struct include OpamMisc.Base let of_string str = match OpamMisc.cut_at str '+' with | None -> of_string str | Some (s,_) -> of_string s type constr = (OpamFormula.relop * t) OpamFormula.formula let current () = match Lazy.force OpamSystem.ocaml_version with | None -> None | Some o -> Some (of_string o) let system () = match Lazy.force OpamSystem.system_ocamlc_version with | None -> None | Some v -> Some (of_string v) let compare v1 v2 = Debian.Version.compare (to_string v1) (to_string v2) let eval_relop relop v1 v2 = OpamFormula.check_relop relop (compare v1 v2) end module O = struct type t = { version: Version.t; name : string; } let compare t1 t2 = String.compare t1.name t2.name let to_string t = t.name let of_string str = let version = Version.of_string str in { version; name = str } let to_json t = `String (to_string t) end include O module Set = OpamMisc.Set.Make(O) module Map = OpamMisc.Map.Make(O) let version t = t.version (* DIR/$NAME.comp *) let of_filename f = if OpamFilename.check_suffix f ".comp" then f |> OpamFilename.chop_extension |> OpamFilename.basename |> OpamFilename.Base.to_string |> of_string |> fun x -> Some x else None let list dir = log "list %s" (OpamFilename.Dir.to_string dir); if OpamFilename.exists_dir dir then ( let files = OpamFilename.rec_files dir in List.fold_left (fun set f -> match of_filename f with | None -> set | Some c -> Set.add c set ) Set.empty files ) else Set.empty let prefixes dir = log "prefixes %s" (OpamFilename.Dir.to_string dir); if OpamFilename.exists_dir dir then ( let files = OpamFilename.rec_files dir in List.fold_left (fun map f -> match of_filename f with | None -> map | Some c -> let suffix = OpamFilename.Dir.to_string (OpamFilename.dirname f) in let prefix = match OpamMisc.remove_prefix ~prefix:(OpamFilename.Dir.to_string dir) suffix with | "" -> None | p -> Some p in Map.add c prefix map ) Map.empty files ) else Map.empty let system = of_string OpamGlobals.system let unknown compiler = if compiler = system then ( let root = if !OpamGlobals.root_dir = OpamGlobals.default_opam_dir then "" else Printf.sprintf " --root=%s" !OpamGlobals.root_dir in OpamGlobals.error_and_exit "No OCaml compiler found in path. You should use:\n\ \n\ \ opam init%s --comp=VERSION\n" root ) else OpamGlobals.error_and_exit "%S is not a valid compiler." (to_string compiler) opam-1.1.1/src/core/opamFile.ml0000644000175000017500000017756412272210733014542 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) open OpamTypes open OpamMisc.OP module Lines = struct (* Lines of space separated words *) type t = string list list let of_channel ic = OpamLineLexer.main (Lexing.from_channel ic) let escape_spaces str = let rec aux i str = if i < 0 then str else match str.[i] with | ' ' | '\t' | '\n' | '\\' -> let s = String.create (String.length str + 1) in String.blit str 0 s 0 i; s.[i] <- '\\'; String.blit str i s (i+1) (String.length str - i); aux (i-1) s | _ -> aux (i-1) str in aux (String.length str - 1) str let to_string (lines: t) = let buf = Buffer.create 1024 in List.iter (fun l -> Buffer.add_string buf (String.concat " " (List.map escape_spaces l)); Buffer.add_string buf "\n" ) lines; Buffer.contents buf end module Syntax = struct type t = file let of_channel (filename:filename) (ic:in_channel) = let lexbuf = Lexing.from_channel ic in let filename = OpamFilename.to_string filename in lexbuf.Lexing.lex_curr_p <- { lexbuf.Lexing.lex_curr_p with Lexing.pos_fname = filename }; OpamParser.main OpamLexer.token lexbuf filename let to_string ignore (t: t) = OpamFormat.string_of_file ~simplify:true ~indent:true ~ignore t let s_opam_version = "opam-version" let check ?(versioned=true) = let not_already_warned = ref true in fun f fields -> if List.mem s_opam_version fields then begin match OpamFormat.assoc_option f.file_contents s_opam_version (OpamFormat.parse_string ++ OpamVersion.of_string) with | Some opam_version -> if OpamVersion.compare opam_version OpamVersion.current > 0 then ( OpamGlobals.error "Your version of OPAM (%s) is not recent enough to read \ %s. Upgrade OPAM to a more recent version (at least %s) \ to read this file correctly." (OpamVersion.to_string OpamVersion.current) (OpamMisc.prettify_path f.file_name) (OpamVersion.to_string opam_version); OpamFormat.bad_format "opam-version" ) | None -> if versioned then ( OpamGlobals.error "%s is missing the opam-version field: syntax check failed." (OpamMisc.prettify_path f.file_name); OpamFormat.bad_format "opam-version" ) end; if not (OpamFormat.is_valid f.file_contents fields) then let invalids = OpamFormat.invalid_fields f.file_contents fields in let too_many, invalids = List.partition (fun x -> List.mem x fields) invalids in if too_many <> [] then OpamGlobals.warning "duplicated fields in %s: %s" f.file_name (OpamMisc.string_of_list (fun x -> x) too_many); if !OpamGlobals.strict then ( if invalids <> [] then (let are,s = match invalids with [_] -> "is an","" | _ -> "are","s" in OpamGlobals.error "%s %s invalid field name%s in %s. Valid fields: %s\n\ Either there is an error in the package, or your \ OPAM is not up-to-date." (OpamMisc.string_of_list (fun x -> x) invalids) are s f.file_name (OpamMisc.string_of_list (fun x -> x) fields)); OpamGlobals.exit 5 ) else if !not_already_warned then ( not_already_warned := false; let is_, s_ = if List.length invalids <= 1 then "is an", "" else "are", "s" in if invalids <> [] then OpamGlobals.warning "%s %s unknown field%s in %s: is your OPAM up-to-date ?" (OpamMisc.pretty_list invalids) is_ s_ f.file_name ) let to_1_0 file = let file_contents = List.map (function | Variable (v, _) as c -> if v = s_opam_version then Variable(s_opam_version, String "1") else c | c -> c ) file.file_contents in { file with file_contents; file_format = OpamVersion.of_string "1" } end module X = struct module Prefix = struct let internal = "prefix" type t = string name_map let empty = OpamPackage.Name.Map.empty let of_channel _ ic = let lines = Lines.of_channel ic in List.fold_left (fun map -> function | [] -> map | [nv;prefix] -> OpamPackage.Name.Map.add (OpamPackage.Name.of_string nv) prefix map | s -> OpamGlobals.error_and_exit "%S is not a valid prefix line" (String.concat " " s) ) OpamPackage.Name.Map.empty lines let to_string _ s = let lines = OpamPackage.Name.Map.fold (fun nv prefix l -> [OpamPackage.Name.to_string nv; prefix] :: l ) s [] in Lines.to_string lines end module Filenames = struct let internal = "filenames" type t = filename_set let empty = OpamFilename.Set.empty let of_channel _ ic = let lines = Lines.of_channel ic in let lines = OpamMisc.filter_map (function | [] -> None | [f] -> Some (OpamFilename.of_string f) | s -> OpamGlobals.error_and_exit "%S is not a valid filename" (String.concat " " s) ) lines in OpamFilename.Set.of_list lines let to_string _ s = let lines = List.rev_map (fun f -> [OpamFilename.to_string f]) (OpamFilename.Set.elements s) in Lines.to_string lines end module File_attributes = struct let internal = "file_attributes" type t = file_attribute_set let empty = OpamFilename.Attribute.Set.empty let of_channel _ ic = let lines = Lines.of_channel ic in let rs = OpamMisc.filter_map (function | [] -> None | l -> Some (OpamFilename.Attribute.of_string (String.concat " " l)) ) lines in OpamFilename.Attribute.Set.of_list rs let to_string _ t = let lines = List.rev_map (fun r -> [OpamFilename.Attribute.to_string r]) (OpamFilename.Attribute.Set.elements t) in Lines.to_string lines end module URL = struct let internal = "url" type t = { url : address; kind : repository_kind option; checksum: string option; } let create kind url = { url; kind; checksum = None; } let empty = { url = ("", None); kind = None; checksum= None; } let s_archive = "archive" let s_src = "src" let s_http = "http" let s_checksum = "checksum" let s_git = "git" let s_darcs = "darcs" let s_hg = "hg" let s_local = "local" let valid_fields = [ s_archive; s_src; s_http; s_git; s_darcs; s_hg; s_local; s_checksum; ] let url_and_kind ~src ~archive ~http ~git ~darcs ~hg ~local = match src, archive, http, git, darcs, hg, local with | None , None , None , None , None , None , None -> None , None | Some x, None , None , None , None , None , None | None , Some x, None , None , None , None , None -> Some x, None | None , None , Some x, None , None , None , None -> Some x, Some `http | None , None , None , Some x, None , None , None -> Some x, Some `git | None , None , None , None , Some x, None , None -> Some x, Some `darcs | None , None , None , None , None , Some x, None -> Some x, Some `hg | None , None , None , None , None , None , Some x -> Some x, Some `local | _ -> OpamGlobals.error_and_exit "Too many URLS" let of_channel filename ic = let s = Syntax.of_channel filename ic in Syntax.check s valid_fields; let get f = OpamFormat.assoc_option s.file_contents f (OpamFormat.parse_string ++ address_of_string) in let archive = get s_archive in let http = get s_http in let src = get s_src in let git = get s_git in let darcs = get s_darcs in let hg = get s_hg in let local = get s_local in let checksum = OpamFormat.assoc_option s.file_contents s_checksum OpamFormat.parse_string in let url, kind = url_and_kind ~src ~archive ~http ~git ~darcs ~hg ~local in let url = match url with | None -> OpamGlobals.error_and_exit "Missing URL" | Some u -> u in { url; kind; checksum } let to_string filename t = let url_name = match t.kind with | None -> "archive" | Some k -> string_of_repository_kind k in let s = { file_format = OpamVersion.current; file_name = OpamFilename.to_string filename; file_contents = [ Variable (url_name , OpamFormat.make_string (string_of_address t.url)); ] @ match t.checksum with | None -> [] | Some c -> [Variable (s_checksum, OpamFormat.make_string c)] } in Syntax.to_string [] s let url t = t.url let kind t = t.kind let checksum t = t.checksum let with_checksum t checksum = { t with checksum = Some checksum } end module Export = struct let internal = "export" type t = package_set * package_set let empty = (OpamPackage.Set.empty, OpamPackage.Set.empty) let of_channel _ ic = let lines = Lines.of_channel ic in let installed = ref OpamPackage.Set.empty in let roots = ref OpamPackage.Set.empty in let add n v r = let nv = OpamPackage.create (OpamPackage.Name.of_string n) (OpamPackage.Version.of_string v) in installed := OpamPackage.Set.add nv !installed; if r then roots := OpamPackage.Set.add nv !roots; in List.iter (function | [] -> () | [n; v] -> add n v true | [n; v; r] -> add n v (r = "root") | l -> OpamGlobals.error_and_exit " Invalid line: %s\nThis is not a valid file to import." (String.concat " " l) ) lines; (!installed, !roots) let to_string _ (installed, roots) = let buf = Buffer.create 1024 in OpamPackage.Set.iter (fun nv -> Printf.bprintf buf "%s %s %s\n" (OpamPackage.Name.to_string (OpamPackage.name nv)) (OpamPackage.Version.to_string (OpamPackage.version nv)) (if OpamPackage.Set.mem nv roots then "root" else "noroot") ) installed; Buffer.contents buf end module Installed = struct let internal = "installed" type t = package_set let empty = OpamPackage.Set.empty let check t = let map = OpamPackage.to_map t in OpamPackage.Name.Map.iter (fun n vs -> if OpamPackage.Version.Set.cardinal vs <> 1 then OpamGlobals.error_and_exit "Multiple versions installed for package %s: %s" (OpamPackage.Name.to_string n) (OpamPackage.Version.Set.to_string vs) ) map let of_channel name ic = let lines = Lines.of_channel ic in let map = ref empty in let add n v = map := OpamPackage.Set.add (OpamPackage.create n v) !map in List.iter (function | [] -> () | [name; version] -> add (OpamPackage.Name.of_string name) (OpamPackage.Version.of_string version) | s -> OpamGlobals.error_and_exit "Bad line in %s: %S" (OpamFilename.to_string name) (String.concat " " s) ) lines; !map let to_string _ t = check t; let buf = Buffer.create 1024 in OpamPackage.Set.iter (fun nv -> Printf.bprintf buf "%s %s\n" (OpamPackage.Name.to_string (OpamPackage.name nv)) (OpamPackage.Version.to_string (OpamPackage.version nv))) t; Buffer.contents buf end module Installed_roots = struct include Installed let internal = "installed.roots" end module Reinstall = struct include Installed let internal = "reinstall" end module Repo_index (A : OpamMisc.ABSTRACT) = struct let internal = "repo-index" type t = (repository_name * string option) A.Map.t let empty = A.Map.empty let of_channel _ ic = let lines = Lines.of_channel ic in List.fold_left (fun map -> function | [] | [_] -> map | a_s :: repos_s :: prefix -> let a = A.of_string a_s in if A.Map.mem a map then OpamGlobals.error_and_exit "multiple lines for %s" a_s else let repo_name = OpamRepositoryName.of_string repos_s in let prefix = match prefix with | [] -> None | [p] -> Some p | _ -> OpamGlobals.error_and_exit "Too many prefixes" in A.Map.add a (repo_name, prefix) map ) A.Map.empty lines let to_string _ map = let lines = A.Map.fold (fun nv (repo_name, prefix) lines -> let repo_s = OpamRepositoryName.to_string repo_name in let prefix_s = match prefix with | None -> [] | Some p -> [p] in (A.to_string nv :: repo_s :: prefix_s) :: lines ) map [] in Lines.to_string (List.rev lines) end module Package_index = Repo_index(OpamPackage) module Compiler_index = Repo_index(OpamCompiler) module Pinned = struct let internal = "pinned" type t = pin_option OpamPackage.Name.Map.t let empty = OpamPackage.Name.Map.empty let of_channel _ ic = let lines = Lines.of_channel ic in let add name_s pin map = let name = OpamPackage.Name.of_string name_s in if OpamPackage.Name.Map.mem name map then OpamGlobals.error_and_exit "multiple lines for package %s" name_s else OpamPackage.Name.Map.add name pin map in List.fold_left (fun map -> function | [] -> map | [name_s; x] -> add name_s (pin_option_of_string x) map | [name_s;k;x] -> let kind = Some (pin_kind_of_string k) in add name_s (pin_option_of_string ?kind x) map | _ -> OpamGlobals.error_and_exit "too many pinning options" ) OpamPackage.Name.Map.empty lines let to_string _ map = let lines = OpamPackage.Name.Map.fold (fun name pin lines -> match kind_of_pin_option pin with | None -> lines | Some kind -> let l = [ OpamPackage.Name.to_string name; string_of_pin_kind kind; string_of_pin_option pin ] in l :: lines ) map [] in Lines.to_string (List.rev lines) end module Repo_config = struct let internal = "repo-config" type t = repository let empty = { repo_name = OpamRepositoryName.of_string ""; repo_address = ("", None); repo_root = OpamFilename.raw_dir ""; repo_kind = `local; repo_priority = 0; } let s_name = "name" let s_kind = "kind" let s_address = "address" let s_priority = "priority" let s_root = "root" let of_channel filename ic = let s = Syntax.of_channel filename ic in let repo_name = OpamFormat.assoc s.file_contents s_name (OpamFormat.parse_string ++ OpamRepositoryName.of_string) in let repo_address = OpamFormat.assoc s.file_contents s_address (OpamFormat.parse_string ++ address_of_string) in let repo_kind = OpamFormat.assoc s.file_contents s_kind (OpamFormat.parse_string ++ repository_kind_of_string) in let repo_priority = OpamFormat.assoc_default 0 s.file_contents s_priority OpamFormat.parse_int in let repo_root = match OpamFormat.assoc_option s.file_contents s_root (OpamFormat.parse_string ++ OpamFilename.raw_dir) with None -> OpamPath.Repository.create (OpamPath.root ()) repo_name | Some f -> f in { repo_name; repo_address; repo_kind; repo_priority; repo_root } let to_string filename t = let s = { file_format = OpamVersion.current; file_name = OpamFilename.to_string filename; file_contents = [ Variable (s_name , OpamFormat.make_string (OpamRepositoryName.to_string t.repo_name)); Variable (s_address , OpamFormat.make_string (string_of_address t.repo_address)); Variable (s_kind , OpamFormat.make_string (string_of_repository_kind t.repo_kind)); Variable (s_priority, OpamFormat.make_int t.repo_priority); Variable (s_root, OpamFormat.make_string (OpamFilename.Dir.to_string t.repo_root)); ] } in Syntax.to_string [] s end module Descr = struct let internal = "descr" type t = string * string let empty = "", "" let synopsis = fst let body = snd let full (x,y) = x ^ "\n" ^ y let of_channel _ ic = let x = try input_line ic with _ -> "" in let y = try OpamSystem.string_of_channel ic with _ -> "" in x, y let of_string str = let head, tail = match OpamMisc.cut_at str '\n' with | None -> str, "" | Some (h,t) -> h, t in head, tail let to_string _ = full end module Aliases = struct let internal = "aliases" type t = compiler switch_map let empty = OpamSwitch.Map.empty let to_string _ t = let l = OpamSwitch.Map.fold (fun switch compiler lines -> [OpamSwitch.to_string switch; OpamCompiler.to_string compiler] :: lines ) t [] in Lines.to_string l let of_channel _ ic = let l = Lines.of_channel ic in List.fold_left (fun map -> function | [] -> map | [switch; comp] -> OpamSwitch.Map.add (OpamSwitch.of_string switch) (OpamCompiler.of_string comp) map | _ -> failwith "switches" ) OpamSwitch.Map.empty l end module Config = struct let internal = "config" type t = { opam_version : opam_version; repositories : repository_name list ; switch : switch; jobs : int; } let with_repositories t repositories = { t with repositories } let with_switch t switch = { t with switch } let with_current_opam_version t = { t with opam_version = OpamVersion.current } let opam_version t = t.opam_version let repositories t = t.repositories let switch t = t.switch let jobs t = t.jobs let create switch repositories jobs = { opam_version = OpamVersion.current; repositories ; switch ; jobs } let empty = { opam_version = OpamVersion.current; repositories = []; switch = OpamSwitch.of_string ""; jobs = OpamGlobals.default_jobs; } let s_opam_version = "opam-version" let s_repositories = "repositories" let s_switch = "switch" let s_switch1 = "alias" let s_switch2 = "ocaml-version" let s_jobs = "jobs" let s_cores = "cores" let s_system_version1 = "system_ocaml-version" let s_system_version2 = "system-ocaml-version" let valid_fields = [ s_opam_version; s_repositories; s_switch; s_jobs; (* this fields are no longer useful, but we keep it for backward compatibility *) s_switch1; s_switch2; s_system_version1; s_system_version2; s_cores; ] let of_channel filename ic = let s = Syntax.of_channel filename ic in Syntax.check s valid_fields; let opam_version = OpamFormat.assoc s.file_contents s_opam_version (OpamFormat.parse_string ++ OpamVersion.of_string) in let repositories = OpamFormat.assoc_list s.file_contents s_repositories (OpamFormat.parse_list (OpamFormat.parse_string ++ OpamRepositoryName.of_string)) in let mk_switch str = OpamFormat.assoc_option s.file_contents str (OpamFormat.parse_string ++ OpamSwitch.of_string) in let switch = mk_switch s_switch in let switch1 = mk_switch s_switch1 in let switch2 = mk_switch s_switch2 in let switch = match switch, switch1, switch2 with | Some v, _ , _ | _ , Some v, _ | _ , _ , Some v -> v | None , None , None -> OpamGlobals.error_and_exit "No current switch defined." in let jobs = let mk str = OpamFormat.assoc_option s.file_contents str OpamFormat.parse_int in match mk s_jobs, mk s_cores with | Some i, _ -> i | _ , Some i -> i | _ -> 1 in { opam_version; repositories; switch; jobs } let to_string filename t = let s = { file_format = OpamVersion.current; file_name = OpamFilename.to_string filename; file_contents = [ Variable (s_opam_version, OpamFormat.make_string (OpamVersion.to_string t.opam_version)); Variable (s_repositories, OpamFormat.make_list (OpamRepositoryName.to_string ++ OpamFormat.make_string) t.repositories); Variable (s_jobs , OpamFormat.make_int t.jobs); Variable (s_switch, OpamFormat.make_string (OpamSwitch.to_string t.switch)) ] } in Syntax.to_string [] s end module OPAM = struct let internal = "opam" type t = { opam_version: opam_version; name : OpamPackage.Name.t option; version : OpamPackage.Version.t option; maintainer : string list; substs : basename list; build_env : (string * string * string) list; build : command list; remove : command list; depends : formula; depopts : formula; conflicts : formula; libraries : section list; syntax : section list; patches : (basename * filter option) list; ocaml_version: compiler_constraint option; os : (bool * string) generic_formula; available : filter; homepage : string list; author : string list; license : string list; doc : string list; tags : string list; build_test : command list; build_doc : command list; depexts : tags option; messages : (string * filter option) list; bug_reports : string list; post_messages: (string * filter option) list; } let empty = { opam_version = OpamVersion.current; name = None; version = None; maintainer = []; substs = []; build_env = []; build = []; remove = []; depends = OpamFormula.Empty; depopts = OpamFormula.Empty; conflicts = OpamFormula.Empty; libraries = []; syntax = []; patches = []; ocaml_version = None; os = Empty; available = FBool true; homepage = []; author = []; license = []; doc = []; tags = []; build_test = []; build_doc = []; depexts = None; messages = []; post_messages = []; bug_reports = []; } let create nv = let name = Some (OpamPackage.name nv) in let version = Some (OpamPackage.version nv) in { empty with name; version } let s_opam_version = "opam-version" let s_version = "version" let s_name = "name" let s_maintainer = "maintainer" let s_substs = "substs" let s_build = "build" let s_build_env = "build-env" let s_remove = "remove" let s_depends = "depends" let s_depopts = "depopts" let s_conflicts = "conflicts" let s_libraries = "libraries" let s_syntax = "syntax" let s_ocaml_version = "ocaml-version" let s_patches = "patches" let s_configure_style = "configure-style" let s_os = "os" let s_available = "available" let s_homepage = "homepage" let s_author = "author" let s_authors = "authors" let s_license = "license" let s_doc = "doc" let s_tags = "tags" let s_build_test = "build-test" let s_build_doc = "build-doc" let s_depexts = "depexts" let s_messages = "messages" let s_post_messages = "post-messages" let s_bug_reports = "bug-reports" let opam_1_0_fields = [ s_opam_version; s_maintainer; s_substs; s_build; s_remove; s_depends; s_depopts; s_conflicts; s_libraries; s_syntax; s_ocaml_version; s_build_env; s_patches; s_os; s_license; s_authors; s_homepage; s_doc; s_build_test; s_build_doc; s_depexts; s_tags; s_version; s_name; s_configure_style; ] let opam_1_1_fields = [ s_author; s_available; s_messages; s_post_messages; s_bug_reports; ] let to_1_0_fields k v = if List.mem k opam_1_1_fields then if k = s_author then Some (s_authors, v) else None else if k = s_maintainer || k = s_homepage || k = s_license then match v with | List (v::_) -> Some (k, v) | v -> Some (k, v) else Some (k, v) let to_1_0 file = let file = OpamFormat.map to_1_0_fields file in Syntax.to_1_0 file let valid_fields = opam_1_0_fields @ opam_1_1_fields let check name = function | None -> OpamGlobals.error_and_exit "Invalid OPAM file (%s)" name | Some n -> n let name t = check "name" t.name let version t = check "version" t.version let maintainer t = t.maintainer let substs t = t.substs let build t = t.build let remove t = t.remove let depends t = t.depends let depopts t = t.depopts let conflicts t = t.conflicts let libraries t = t.libraries let syntax t = t.syntax let ocaml_version t = t.ocaml_version let build_env t = t.build_env let patches t = t.patches let os t = t.os let available t = t.available let homepage t = t.homepage let author t = t.author let license t = t.license let doc t = t.doc let tags t = t.tags let build_doc t = t.build_doc let build_test t = t.build_test let depexts t = t.depexts let messages t = t.messages let post_messages t = t.post_messages let opam_version t = t.opam_version let bug_reports t = t.bug_reports let with_name t name = { t with name = Some name } let with_version t version = { t with version = Some version } let with_depends t depends = { t with depends } let with_depopts t depopts = { t with depopts } let with_build t build = { t with build } let with_remove t remove = { t with remove } let with_libraries t libraries = { t with libraries } let with_substs t substs = { t with substs } let with_ocaml_version t ocaml_version = { t with ocaml_version } let with_maintainer t maintainer = { t with maintainer } let with_patches t patches = { t with patches } let with_bug_reports t bug_reports = { t with bug_reports } let with_depexts t depexts = { t with depexts } let to_string filename t = let make_file = OpamFormat.make_option (OpamFilename.Base.to_string ++ OpamFormat.make_string) OpamFormat.make_filter in let name_and_version = match OpamPackage.of_filename filename with | Some nv when not (OpamPackage.is_pinned nv) -> [] | _ -> let name n = OpamFormat.make_string (OpamPackage.Name.to_string n) in let version v = OpamFormat.make_string (OpamPackage.Version.to_string v) in [ Variable (s_name, name (check "name" t.name)); Variable (s_version, version (check "version" t.version)) ] in let option c s f = match c with | None -> [] | Some v -> [ Variable (s, f v) ] in let list c s f = match c with | [] -> [] | l -> [ Variable (s, f l) ] in let listm c s f = match c with | [] -> [] | l -> [ Variable (s, OpamFormat.make_list f l) ] in let formula c s f = match c with | Empty -> [] | x -> [ Variable (s, f x) ] in let filter c s f = match c with | FBool true -> [] | x -> [ Variable (s, f x) ] in let s = { file_format = t.opam_version; file_name = OpamFilename.to_string filename; file_contents = [ Variable (s_opam_version, (OpamVersion.to_string ++ OpamFormat.make_string) t.opam_version); ] @ list t.maintainer s_maintainer OpamFormat.make_string_list @ list t.author s_author OpamFormat.make_string_list @ name_and_version @ list t.homepage s_homepage OpamFormat.make_string_list @ list t.bug_reports s_bug_reports OpamFormat.make_string_list @ list t.license s_license OpamFormat.make_string_list @ list t.doc s_doc OpamFormat.make_string_list @ list t.tags s_tags OpamFormat.make_string_list @ listm t.substs s_substs (OpamFilename.Base.to_string ++ OpamFormat.make_string) @ listm t.build_env s_build_env OpamFormat.make_env_variable @ listm t.build s_build OpamFormat.make_command @ listm t.build_test s_build_test OpamFormat.make_command @ listm t.build_doc s_build_doc OpamFormat.make_command @ listm t.remove s_remove OpamFormat.make_command @ formula t.depends s_depends OpamFormat.make_formula @ formula t.depopts s_depopts OpamFormat.make_opt_formula @ option t.depexts s_depexts OpamFormat.make_tags @ formula t.conflicts s_conflicts OpamFormat.make_formula @ listm t.libraries s_libraries (OpamVariable.Section.to_string ++ OpamFormat.make_string) @ listm t.syntax s_syntax (OpamVariable.Section.to_string ++ OpamFormat.make_string) @ list t.patches s_patches (OpamFormat.make_list make_file) @ option t.ocaml_version s_ocaml_version OpamFormat.make_compiler_constraint @ formula t.os s_os OpamFormat.make_os_constraint @ filter t.available s_available (fun f -> List (OpamFormat.make_filter f)) @ list t.messages s_messages OpamFormat.(make_list (make_option make_string make_filter)) @ list t.post_messages s_post_messages OpamFormat.(make_list (make_option make_string make_filter)); } in let s = if !OpamGlobals.compat_mode_1_0 then to_1_0 s else s in Syntax.to_string [s_os; s_ocaml_version; s_available] s let of_channel filename ic = let nv = OpamPackage.of_filename filename in let f = Syntax.of_channel filename ic in Syntax.check f valid_fields; let s = f.file_contents in let opam_version = OpamFormat.assoc s s_opam_version (OpamFormat.parse_string ++ OpamVersion.of_string) in let name_f = OpamFormat.assoc_option s s_name (OpamFormat.parse_string ++ OpamPackage.Name.of_string) in let name = match name_f, nv with | None , None -> None | Some n, None -> Some n | None , Some nv -> Some (OpamPackage.name nv) | Some n, Some nv -> if OpamPackage.name nv <> n then OpamGlobals.error_and_exit "Inconsistent naming scheme in %s" (OpamFilename.to_string filename) else Some n in let version_f = OpamFormat.assoc_option s s_version (OpamFormat.parse_string ++ OpamPackage.Version.of_string) in let version = match version_f, nv with | None , None -> None | Some v, None -> Some v | None , Some nv -> Some (OpamPackage.version nv) | Some v, Some nv -> if OpamPackage.is_pinned nv then Some v else if OpamPackage.version nv <> v then OpamGlobals.error_and_exit "Inconsistent versioning scheme in %s" (OpamFilename.to_string filename) else Some v in let maintainer = OpamFormat.assoc_list s s_maintainer OpamFormat.parse_string_list in let substs = OpamFormat.assoc_list s s_substs (OpamFormat.parse_list (OpamFormat.parse_string ++ OpamFilename.Base.of_string)) in let build_env = OpamFormat.assoc_list s s_build_env (OpamFormat.parse_list OpamFormat.parse_env_variable) in let build = OpamFormat.assoc_list s s_build OpamFormat.parse_commands in let remove = OpamFormat.assoc_list s s_remove OpamFormat.parse_commands in let depends = OpamFormat.assoc_default OpamFormula.Empty s s_depends OpamFormat.parse_formula in let depopts = OpamFormat.assoc_default OpamFormula.Empty s s_depopts OpamFormat.parse_opt_formula in let conflicts = OpamFormat.assoc_default OpamFormula.Empty s s_conflicts OpamFormat.parse_formula in let libraries = OpamFormat.assoc_list s s_libraries (OpamFormat.parse_list (OpamFormat.parse_string ++ OpamVariable.Section.of_string)) in let syntax = OpamFormat.assoc_list s s_syntax (OpamFormat.parse_list (OpamFormat.parse_string ++ OpamVariable.Section.of_string)) in let ocaml_version = OpamFormat.assoc_option s s_ocaml_version OpamFormat.parse_compiler_constraint in let os = OpamFormat.assoc_default OpamFormula.Empty s s_os OpamFormat.parse_os_constraint in let available = OpamFormat.assoc_default (FBool true) s s_available (function List l -> OpamFormat.parse_filter l | _ -> raise (OpamFormat.Bad_format "available: expecting a list")) in let parse_file = OpamFormat.parse_option (OpamFormat.parse_string ++ OpamFilename.Base.of_string) OpamFormat.parse_filter in let patches = OpamFormat.assoc_list s s_patches (OpamFormat.parse_list parse_file) in let homepage = OpamFormat.assoc_list s s_homepage OpamFormat.parse_string_list in let author = let x = OpamFormat.assoc_list s s_authors OpamFormat.parse_string_list in let y = OpamFormat.assoc_list s s_author OpamFormat.parse_string_list in x @ y in let license = OpamFormat.assoc_list s s_license OpamFormat.parse_string_list in let doc = OpamFormat.assoc_list s s_doc OpamFormat.parse_string_list in let tags = OpamFormat.assoc_list s s_tags OpamFormat.parse_string_list in let build_test = OpamFormat.assoc_list s s_build_test OpamFormat.parse_commands in let build_doc = OpamFormat.assoc_list s s_build_doc OpamFormat.parse_commands in let depexts = OpamFormat.assoc_option s s_depexts OpamFormat.parse_tags in let messages = OpamFormat.assoc_list s s_messages OpamFormat.parse_messages in let bug_reports = OpamFormat.assoc_list s s_bug_reports OpamFormat.parse_string_list in let post_messages = OpamFormat.assoc_list s s_post_messages OpamFormat.parse_messages in { opam_version; name; version; maintainer; substs; build; remove; depends; depopts; conflicts; libraries; syntax; patches; ocaml_version; os; available; build_env; homepage; author; license; doc; tags; build_test; build_doc; depexts; messages; post_messages; bug_reports; } end module Dot_install = struct let internal = ".install" type t = { bin : (basename optional * basename option) list; sbin : (basename optional * basename option) list; lib : (basename optional * basename option) list; toplevel: (basename optional * basename option) list; stublibs: (basename optional * basename option) list; share : (basename optional * basename option) list; etc : (basename optional * basename option) list; doc : (basename optional * basename option) list; man : (basename optional * basename option) list; misc : (basename optional * filename) list; } let empty = { lib = []; bin = []; sbin = []; toplevel = []; stublibs = []; misc = []; share = []; etc = []; man = []; doc = []; } let bin t = t.bin let sbin t = t.sbin let lib t = t.lib let toplevel t = t.toplevel let stublibs t = t.stublibs let misc t = t.misc let share t = t.share let etc t = t.etc let doc t = t.doc let man t = List.map (fun (src, dst) -> src, match dst with | None -> let base = Filename.basename (OpamFilename.Base.to_string src.c) in Some (OpamFilename.Base.of_string (Filename.concat "man3" base)) | _ -> dst ) t.man let s_lib = "lib" let s_bin = "bin" let s_sbin = "sbin" let s_misc = "misc" let s_toplevel = "toplevel" let s_stublibs = "stublibs" let s_share = "share" let s_etc = "etc" let s_doc = "doc" let s_man = "man" let valid_fields = [ s_lib; s_bin; s_sbin; s_toplevel; s_stublibs; s_misc; s_share; s_etc; s_doc; s_man; ] (* Filenames starting by ? are not always present. *) let optional_of_string str = let mk = OpamFilename.Base.of_string in if String.length str > 0 && str.[0] = '?' then { optional = true; c = mk (String.sub str 1 (String.length str - 1)) } else { optional = false; c = mk str } let string_of_optional t = let o = if t.optional then "?" else "" in Printf.sprintf "%s%s" o (OpamFilename.Base.to_string t.c) let to_string filename t = let mk = let aux (src, opt) = let src = String (string_of_optional src) in match opt with | None -> src | Some dst -> Option (src, [String (OpamFilename.Base.to_string dst)]) in OpamFormat.make_list aux in let mk_misc = let aux (src, dst) = let src = String (string_of_optional src) in let dst = String (OpamFilename.to_string dst) in Option (src, [dst]) in OpamFormat.make_list aux in let s = { file_format = OpamVersion.current; file_name = OpamFilename.to_string filename; file_contents = [ Variable (s_bin , mk t.bin); Variable (s_sbin , mk t.sbin); Variable (s_lib , mk t.lib); Variable (s_toplevel, mk t.toplevel); Variable (s_stublibs, mk t.stublibs); Variable (s_share , mk t.share); Variable (s_etc , mk t.etc); Variable (s_doc , mk t.doc); Variable (s_man , mk t.man); Variable (s_misc , mk_misc t.misc); ] } in Syntax.to_string [] s let of_channel filename ic = let s = Syntax.of_channel filename ic in Syntax.check s valid_fields; let src = OpamFormat.parse_string ++ optional_of_string in let mk field = let dst = OpamFormat.parse_string ++ OpamFilename.Base.of_string in let fn = OpamFormat.parse_single_option src dst in OpamFormat.assoc_list s.file_contents field (OpamFormat.parse_list fn) in let misc = let absolute_filename s = if not (Filename.is_relative s) then OpamFilename.of_string s else OpamSystem.internal_error "%s is not an absolute filename." s in let dst = OpamFormat.parse_string ++ absolute_filename in let fn = OpamFormat.parse_pair src dst in OpamFormat.assoc_list s.file_contents s_misc (OpamFormat.parse_list fn) in let bin = mk s_bin in let sbin = mk s_sbin in let lib = mk s_lib in let toplevel = mk s_toplevel in let stublibs = mk s_stublibs in let share = mk s_share in let etc = mk s_etc in let doc = mk s_doc in let man = mk s_man in { lib; bin; sbin; misc; toplevel; stublibs; share; etc; doc; man } end module Dot_config = struct let internal = ".config" let s str = S str let b bool = B bool type s = { name : section; kind : string ; bytecomp : string list ; asmcomp : string list ; bytelink : string list ; asmlink : string list ; requires : section list; lvariables: (variable * variable_contents) list; } type t = { sections : s list; variables: (variable * variable_contents) list; } let create variables = { variables; sections = [] } let empty = { sections = []; variables = []; } let s_bytecomp = "bytecomp" let s_asmcomp = "asmcomp" let s_bytelink = "bytelink" let s_asmlink = "asmlink" let s_requires = "requires" let valid_fields = [ s_bytecomp; s_asmcomp; s_bytelink; s_asmlink; s_requires; ] let of_channel filename ic = let file = Syntax.of_channel filename ic in let parse_value = OpamFormat.parse_or [ "string", (OpamFormat.parse_string ++ s); "bool" , (OpamFormat.parse_bool ++ b); ] in let parse_variables items = let l = List.filter (fun (x,_) -> not (List.mem x valid_fields) ) (OpamFormat.variables items) in List.rev_map (fun (k,v) -> OpamVariable.of_string k, parse_value v) l in let parse_requires = OpamFormat.parse_list (OpamFormat.parse_string ++ OpamVariable.Section.of_string) in let parse_section kind s = let name = OpamVariable.Section.of_string s.section_name in let bytecomp = OpamFormat.assoc_string_list s.section_items s_bytecomp in let asmcomp = OpamFormat.assoc_string_list s.section_items s_asmcomp in let bytelink = OpamFormat.assoc_string_list s.section_items s_bytecomp in let asmlink = OpamFormat.assoc_string_list s.section_items s_asmlink in let requires = OpamFormat.assoc_list s.section_items s_requires parse_requires in let lvariables = parse_variables s.section_items in { name; kind; bytecomp; asmcomp; bytelink; asmlink; lvariables; requires } in let libraries = OpamFormat.assoc_sections file.file_contents "library" (parse_section "library") in let syntax = OpamFormat.assoc_sections file.file_contents "syntax" (parse_section "syntax") in let sections = libraries @ syntax in let variables = parse_variables file.file_contents in { sections; variables } let to_string filename t = let of_value = function | B b -> Bool b | S s -> String s in let of_variables l = List.rev_map (fun (k,v) -> Variable (OpamVariable.to_string k, of_value v)) l in let make_require = OpamVariable.Section.to_string ++ OpamFormat.make_string in let of_section s = Section { section_name = OpamVariable.Section.to_string s.name; section_kind = s.kind; section_items = [ Variable (s_bytecomp, OpamFormat.make_string_list s.bytecomp); Variable (s_asmcomp , OpamFormat.make_string_list s.asmcomp); Variable (s_bytelink, OpamFormat.make_string_list s.bytelink); Variable (s_asmlink , OpamFormat.make_string_list s.asmlink); Variable (s_requires, OpamFormat.make_list make_require s.requires); ] @ of_variables s.lvariables } in Syntax.to_string [] { file_format = OpamVersion.current; file_name = OpamFilename.to_string filename; file_contents = of_variables t.variables @ List.rev (List.rev_map of_section t.sections) } let variables t = List.rev_map fst t.variables let variable t s = try Some (List.assoc s t.variables) with Not_found -> None module type SECTION = sig val available: t -> section list val kind : t -> section -> string val asmcomp : t -> section -> string list val bytecomp : t -> section -> string list val asmlink : t -> section -> string list val bytelink : t -> section -> string list val requires : t -> section -> section list val variable : t -> section -> variable -> variable_contents option val variables: t -> section -> variable list end module MK (M : sig val get : t -> s list end) : SECTION = struct let find t name = List.find (fun s -> s.name = name) (M.get t) let available t = List.rev_map (fun s -> s.name) (M.get t) let kind t s = (find t s).kind let bytecomp t s = (find t s).bytecomp let asmcomp t s = (find t s).asmcomp let bytelink t s = (find t s).bytelink let asmlink t s = (find t s).asmlink let requires t s = (find t s).requires let variable t n s = try Some (List.assoc s (find t n).lvariables) with Not_found -> None let variables t n = List.rev_map fst (find t n).lvariables end let filter t n = List.filter (fun s -> s.kind = n) t.sections module Library = MK (struct let get t = filter t "library" end) module Syntax = MK (struct let get t = filter t "syntax" end) module Section = MK (struct let get t = t.sections end) end module Comp = struct let internal = "comp" type t = { opam_version : opam_version ; name : compiler ; version : compiler_version ; preinstalled : bool; src : address option ; kind : repository_kind option ; patches : filename list ; configure : string list ; make : string list ; build : command list ; bytecomp : string list ; asmcomp : string list ; bytelink : string list ; asmlink : string list ; packages : formula ; requires : section list; pp : ppflag option; env : (string * string * string) list; tags : string list; } let empty = { opam_version = OpamVersion.current; name = OpamCompiler.of_string ""; version = OpamCompiler.Version.of_string ""; src = None; kind = None; preinstalled = false; patches = []; configure = []; make = []; build = []; bytecomp = []; asmcomp = []; bytelink = []; asmlink = []; packages = OpamFormula.Empty; requires = []; pp = None; env = []; tags = []; } let create_preinstalled name version packages env = let mk n = Atom (n, Empty) in let aux accu t = match accu, t with | Empty, x -> mk x | _ , x -> And(accu, mk x) in let packages = List.fold_left aux OpamFormula.Empty packages in { empty with name; version; preinstalled = true; packages; env } let s_opam_version = "opam-version" let s_name = "name" let s_version = "version" let s_patches = "patches" let s_configure = "configure" let s_make = "make" let s_build = "build" let s_bytecomp = "bytecomp" let s_asmcomp = "asmcomp" let s_bytelink = "bytelink" let s_asmlink = "asmlink" let s_packages = "packages" let s_requires = "requires" let s_pp = "pp" let s_env = "env" let s_preinstalled = "preinstalled" let s_tags = "tags" let s_src = "src" let s_http = "http" let s_archive = "archive" let s_git = "git" let s_darcs = "darcs" let s_hg = "hg" let s_local = "local" let opam_1_0_fields = [ s_opam_version; s_name; s_version; s_src; s_patches; s_configure; s_make; s_build; s_bytecomp; s_asmcomp; s_bytelink; s_asmlink; s_packages; s_requires; s_pp; s_env; s_preinstalled; s_tags; ] let opam_1_1_fields = [ s_archive; s_http; s_git; s_darcs; s_hg; s_local; ] let to_1_0_fields k v = if List.mem k opam_1_1_fields then if k = s_archive || k = s_http || k = s_git || k = s_darcs || k = s_hg || k = s_local then Some (s_src, v) else None else Some (k, v) let to_1_0 file = let file = OpamFormat.map to_1_0_fields file in Syntax.to_1_0 file let valid_fields = opam_1_0_fields @ opam_1_1_fields let name t = t.name let version t = t.version let patches t = t.patches let configure t = t.configure let make t = t.make let build t = t.build let src t = t.src let kind t = t.kind let opam_version t = t.opam_version let packages t = t.packages let asmlink t = t.asmlink let asmcomp t = t.asmcomp let bytelink t = t.bytelink let bytecomp t = t.bytecomp let requires t = t.requires let pp t = t.pp let preinstalled t = t.preinstalled let env t = t.env let tags t = t.tags let of_channel filename ic = let file = Syntax.of_channel filename ic in Syntax.check file valid_fields; let s = file.file_contents in let opam_version = OpamFormat.assoc s s_opam_version (OpamFormat.parse_string ++ OpamVersion.of_string) in let parse_camlp4 = function | List ( Ident "CAMLP4" :: l ) -> Some (Camlp4 (OpamFormat.parse_string_list (List l))) | _ -> raise (OpamFormat.Bad_format "camlp4") in let parse_ppflags = OpamFormat.parse_or [ ("camlp4" , parse_camlp4); ("string-list", OpamFormat.parse_string_list ++ fun x -> Some (Cmd x)); ] in let name_d, version_d = match OpamCompiler.of_filename filename with | None -> OpamSystem.internal_error "%s is not a valid compiler description file." (OpamFilename.to_string filename) | Some c -> c, OpamCompiler.version c in let name = OpamFormat.assoc_default name_d s s_name (OpamFormat.parse_string ++ OpamCompiler.of_string) in if name_d <> name then OpamGlobals.warning "The file %s contains a bad 'name' field: %s instead of %s" (OpamFilename.to_string filename) (OpamCompiler.to_string name) (OpamCompiler.to_string name_d); let version = OpamFormat.assoc_default version_d s s_version (OpamFormat.parse_string ++ OpamCompiler.Version.of_string) in if name <> OpamCompiler.system && version_d <> version then OpamGlobals.warning "The file %s contains a bad 'version' field: %s instead of %s" (OpamFilename.to_string filename) (OpamCompiler.Version.to_string version) (OpamCompiler.Version.to_string version_d); let address field = OpamFormat.assoc_option s field (OpamFormat.parse_string ++ address_of_string) in let src = address s_src in let archive = address s_archive in let http = address s_http in let git = address s_git in let darcs = address s_darcs in let hg = address s_hg in let local = address s_local in let src, kind = URL.url_and_kind ~src ~archive ~http ~git ~darcs ~hg ~local in let patches = OpamFormat.assoc_list s s_patches (OpamFormat.parse_list (OpamFormat.parse_string ++ OpamFilename.raw)) in let configure = OpamFormat.assoc_string_list s s_configure in let make = OpamFormat.assoc_string_list s s_make in let build = OpamFormat.assoc_list s s_build OpamFormat.parse_commands in let env = OpamFormat.assoc_list s s_env (OpamFormat.parse_list_list OpamFormat.parse_env_variable) in let bytecomp = OpamFormat.assoc_string_list s s_bytecomp in let asmcomp = OpamFormat.assoc_string_list s s_asmcomp in let bytelink = OpamFormat.assoc_string_list s s_bytecomp in let asmlink = OpamFormat.assoc_string_list s s_asmlink in let packages = OpamFormat.assoc_default OpamFormula.Empty s s_packages OpamFormat.parse_formula in let requires = OpamFormat.assoc_list s s_requires (OpamFormat.parse_list (OpamFormat.parse_string ++ OpamVariable.Section.of_string)) in let pp = OpamFormat.assoc_default None s s_pp parse_ppflags in let preinstalled = OpamFormat.assoc_default false s s_preinstalled OpamFormat.parse_bool in let tags = OpamFormat.assoc_string_list s s_tags in if build <> [] && (configure @ make) <> [] then OpamGlobals.error_and_exit "You cannot use 'build' and 'make'/'configure' fields at the same time."; if not preinstalled && src = None then OpamGlobals.error_and_exit "You should either specify an url (with 'sources') or use 'preinstalled: \ true' to pick the already installed compiler version."; { opam_version; name; version; src; kind; patches; configure; make; build; bytecomp; asmcomp; bytelink; asmlink; packages; requires; pp; preinstalled; env; tags; } let to_string filename s = let make_ppflag = function | Cmd l -> OpamFormat.make_string_list l | Camlp4 l -> List (Symbol "CAMLP4" :: List.rev (List.rev_map OpamFormat.make_string l)) in let src = match s.kind, s.src with | _ , None -> None | Some kind , Some x -> Some (string_of_repository_kind kind, x) | None , Some x -> Some ("archive", x) in let s = { file_format = s.opam_version; file_name = OpamFilename.to_string filename; file_contents = [ Variable (s_opam_version, OpamFormat.make_string (OpamVersion.to_string s.opam_version)) ] @ ( match OpamCompiler.of_filename filename with | None -> [Variable (s_name, OpamFormat.make_string (OpamCompiler.to_string s.name))] | Some _ -> [] ) @ [ Variable (s_version, OpamFormat.make_string (OpamCompiler.Version.to_string s.version)) ] @ ( match src with | None -> [] | Some (s,c) -> [Variable (s, OpamFormat.make_string (string_of_address c))] ) @ [ Variable (s_patches, OpamFormat.make_list (OpamFilename.to_string ++ OpamFormat.make_string) s.patches); Variable (s_configure, OpamFormat.make_string_list s.configure); Variable (s_make, OpamFormat.make_string_list s.make); Variable (s_build, OpamFormat.make_commands s.build); Variable (s_bytecomp, OpamFormat.make_string_list s.bytecomp); Variable (s_asmcomp, OpamFormat.make_string_list s.asmcomp); Variable (s_bytelink, OpamFormat.make_string_list s.bytelink); Variable (s_asmlink, OpamFormat.make_string_list s.asmlink); Variable (s_packages, OpamFormat.make_formula s.packages); Variable (s_requires, OpamFormat.make_list (OpamVariable.Section.to_string ++ OpamFormat.make_string) s.requires); Variable (s_env, OpamFormat.make_list OpamFormat.make_env_variable s.env); Variable (s_tags, OpamFormat.make_string_list s.tags); ] @ (match s.pp with | None -> [] | Some pp -> [ Variable (s_pp, make_ppflag pp) ] ) @ ( if not s.preinstalled then [] else [ Variable (s_preinstalled, OpamFormat.make_bool s.preinstalled) ]) } in let s = if !OpamGlobals.compat_mode_1_0 then to_1_0 s else s in Syntax.to_string [] s end module Comp_descr = Descr module Subst = struct let internal = "subst" type t = string let empty = "" let of_channel _ ic = OpamSystem.string_of_channel ic let to_string _ t = t let replace t f = let subst str = let str = String.sub str 2 (String.length str - 4) in let v = OpamVariable.Full.of_string str in OpamVariable.string_of_variable_contents (f v) in let rex = Re_perl.compile_pat "%\\{[^%]+\\}%" in Re_pcre.substitute ~rex ~subst t let replace_string = replace end module Repo = struct let internal = "repo" type t = { opam_version : OpamVersion.t; browse : string option; upstream : string option; redirect : (string * filter option) list; } let version_of_maybe_string vs = OpamVersion.of_string begin match vs with | None -> "0.7.5" | Some v -> v end let create ?browse ?upstream ?opam_version ?(redirect=[]) () = { opam_version = version_of_maybe_string opam_version; browse; upstream; redirect; } let empty = create () let s_opam_version = "opam-version" let s_browse = "browse" let s_upstream = "upstream" let s_redirect = "redirect" let valid_fields = [ s_opam_version; s_browse; s_upstream; s_redirect; ] let of_channel filename ic = let s = Syntax.of_channel filename ic in Syntax.check ~versioned:false s valid_fields; let get f = OpamFormat.assoc_option s.file_contents f OpamFormat.parse_string in let opam_version = version_of_maybe_string (get s_opam_version) in let browse = get s_browse in let upstream = get s_upstream in let redirect = OpamFormat.assoc_list s.file_contents s_redirect (OpamFormat.parse_list (OpamFormat.parse_option OpamFormat.parse_string OpamFormat.parse_filter)) in { opam_version; browse; upstream; redirect } let to_string filename t = let opam_version = OpamVersion.to_string t.opam_version in let s = { file_format = t.opam_version; file_name = OpamFilename.to_string filename; file_contents = (Variable (s_opam_version, OpamFormat.make_string opam_version)) :: ( match t.upstream with | None -> [] | Some url -> [Variable (s_upstream , OpamFormat.make_string url)] ) @ ( match t.browse with | None -> [] | Some url -> [Variable (s_browse , OpamFormat.make_string url)] ) @ ( match t.redirect with | [] -> [] | l -> let value = OpamFormat.make_list (OpamFormat.make_option OpamFormat.make_string OpamFormat.make_filter) l in [Variable(s_redirect, value)] ); } in Syntax.to_string [] s let opam_version t = t.opam_version let browse t = t.browse let upstream t = t.upstream let redirect t = t.redirect end end module type F = sig val internal : string type t val empty : t val of_channel : filename -> in_channel -> t val to_string : filename -> t -> string end let read_files = ref [] let write_files = ref [] let print_stats () = let aux kind = function | [] -> () | l -> OpamGlobals.msg "%d files %s:\n %s\n%!" (List.length !read_files) kind (String.concat "\n " l) in aux "read" !read_files; aux "write" !write_files module Make (F : F) = struct let log fmt = OpamGlobals.log (Printf.sprintf "FILE(%s)" F.internal) fmt let write f v = let filename = OpamFilename.prettify f in let chrono = OpamGlobals.timer () in OpamFilename.write f (F.to_string f v); write_files := filename :: !write_files; log "Wrote %s in %.3fs" filename (chrono ()) let read f = let filename = OpamFilename.prettify f in read_files := filename :: !read_files; let chrono = OpamGlobals.timer () in if OpamFilename.exists f then try let ic = OpamFilename.open_in f in let r = F.of_channel f ic in close_in ic; log "Read %s in %.3fs" filename (chrono ()); r with OpamFormat.Bad_format msg -> OpamSystem.internal_error "File %s: %s" (OpamFilename.to_string f) msg else OpamSystem.internal_error "File %s does not exist" (OpamFilename.to_string f) let safe_read f = if OpamFilename.exists f then read f else ( log "Cannot find %s" (OpamFilename.to_string f); F.empty ) let dummy_file = OpamFilename.raw "" let read_from_channel ic = try F.of_channel dummy_file ic with OpamFormat.Bad_format msg -> OpamSystem.internal_error "%s" msg let write_to_channel oc str = output_string oc (F.to_string dummy_file str) end open X module type IO_FILE = sig type t val empty: t val write: filename -> t -> unit val read : filename -> t val safe_read: filename -> t val read_from_channel: in_channel -> t val write_to_channel: out_channel -> t -> unit end module Config = struct include Config include Make (Config) end module Package_index = struct include Package_index include Make (Package_index) end module Compiler_index = struct include Compiler_index include Make (Compiler_index) end module Pinned = struct include Pinned include Make (Pinned) end module Repo = struct include Repo include Make(Repo) end module Repo_config = struct include Repo_config include Make (Repo_config) end module Descr = struct include Descr include Make (Descr) end module Aliases = struct include Aliases include Make (Aliases) end module Reinstall = struct include Reinstall include Make (Reinstall) end module OPAM = struct include OPAM include Make (OPAM) end module Dot_install = struct include Dot_install include Make (Dot_install) end module Dot_config = struct include Dot_config include Make (Dot_config) end module Export = struct include Export include Make(Export) end module Installed = struct include Installed include Make (Installed) end module Installed_roots = struct include Installed_roots include Make (Installed_roots) end module Subst = struct include Subst include Make (Subst) end module Comp = struct include Comp include Make (Comp) end module URL = struct include URL include Make (URL) end module File_attributes = struct include File_attributes include Make(File_attributes) end module Filenames = struct include Filenames include Make(Filenames) end module Prefix = struct include Prefix include Make(Prefix) end opam-1.1.1/src/scripts/0000755000175000017500000000000012272210733013167 5ustar i33173i33173opam-1.1.1/src/scripts/opam_mk_repo.mli0000644000175000017500000000230712272210733016344 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) type args val args: args Cmdliner.Term.t val process: args -> unit opam-1.1.1/src/scripts/opam_depexts_change.ml0000644000175000017500000000535312272210733017524 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) (* Script to check that a given repository is well-typed (or well-parsed) *) open OpamTypes type args = { pkg: name; os: string list; deps: string list; } let args = let open Cmdliner in let os = let doc = "Operating system tag" in Arg.(value & opt_all string [] & info ["os"] ~doc) in let deps = let doc = "Extdep tag" in Arg.(value & opt_all string [] & info ["dep"] ~doc) in let pkg = let doc = "OPAM package name" in Arg.(required & pos 1 (some OpamArg.package_name) None & info [] ~doc) in Term.(pure (fun os deps pkg -> { os; deps; pkg }) $ os $ deps $ pkg) let process args = let repo = OpamRepository.local (OpamFilename.cwd ()) in let packages = OpamRepository.packages_with_prefixes repo in (** packages *) OpamPackage.Map.iter (fun package prefix -> OpamGlobals.msg "Processing (package) %s\n" (OpamPackage.to_string package); (** OPAM *) let opam_f = OpamPath.Repository.opam repo prefix package in let opam = OpamFile.OPAM.read opam_f in let pkgname = OpamFile.OPAM.name opam in if pkgname = args.pkg then begin let depexts = let os = OpamMisc.StringSet.of_list args.os in let deps = OpamMisc.StringSet.of_list args.deps in match OpamFile.OPAM.depexts opam with | None -> OpamMisc.StringSetMap.of_list [ os, deps ] | Some depexts' -> (* TODO: Replace existing entry? *) OpamMisc.StringSetMap.add os deps depexts' in let opam = OpamFile.OPAM.with_depexts opam (Some depexts) in OpamFile.OPAM.write opam_f opam; end; ) packages opam-1.1.1/src/scripts/opam_mk_repo.ml0000644000175000017500000003046312272210733016177 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) open OpamTypes open OpamFilename.OP let log fmt = OpamGlobals.log "OPAM-MK-REPO" fmt type args = { index: bool; names: string list; gener_digest: bool; dryrun: bool; recurse: bool; resolve: bool; debug: bool; } let args = let open Cmdliner in (*{[ let all = let doc = "Build all package archives (this is the default unless -i)" in Arg.(value & flag & info ["a";"all"] ~doc) in ]}*) let index = let doc = "Only build indexes, not package archives." in Arg.(value & flag & info ["i";"index"] ~doc) in let gener_digest = let doc = "Automatically correct the wrong archive checksums." in Arg.(value & flag & info ["g";"generate-checksums"] ~doc) in let dryrun = let doc = "Simply display the possible actions instead of executing them." in Arg.(value & flag & info ["d";"dryrun"] ~doc) in let recurse = let doc = "Recurse among the transitive dependencies." in Arg.(value & flag & info ["r";"recursive"] ~doc) in let resolve = let doc = "A more advanced version of `--recursive': will attempt to resolve \ your installation with all dependencies in the best way \ possible and build the archives accordingly." in Arg.(value & flag & info ["resolve"] ~doc) in let names = let doc = "Names of the packages to include in the repo." in Arg.(value & pos_all string [] & info [] ~docv:"PKG" ~doc) in let debug = let doc = "Display debug messages." in Arg.(value & flag & info ["debug"] ~doc) in Term.( pure (fun index gener_digest dryrun recurse names debug resolve -> {index; gener_digest; dryrun; recurse; names; debug; resolve}) $index $gener_digest $dryrun $recurse $names $debug $resolve ) let resolve_deps index names = let atoms = List.map (fun str -> match OpamPackage.of_string_opt str with | Some nv -> OpamSolution.eq_atom (OpamPackage.name nv) (OpamPackage.version nv) | None -> OpamPackage.Name.of_string str, None) names in let opams = List.fold_left (fun opams r -> let f = OpamFilename.create (OpamFilename.cwd ()) (OpamFilename.Attribute.base r) in if OpamFilename.basename f = OpamFilename.Base.of_string "opam" then match OpamPackage.of_dirname (OpamFilename.dirname f) with | Some nv -> OpamPackage.Map.add nv (OpamFile.OPAM.read f) opams | None -> opams else opams) OpamPackage.Map.empty (OpamFilename.Attribute.Set.elements index) in let packages = OpamPackage.Set.of_list (OpamPackage.Map.keys opams) in let universe = { OpamSolver.empty_universe with u_packages = packages; u_available = packages; (* XXX add a compiler/OS option ? *) u_depends = OpamPackage.Map.map OpamFile.OPAM.depends opams; u_conflicts = OpamPackage.Map.map OpamFile.OPAM.conflicts opams; u_action = Install (OpamPackage.Name.Set.of_list (List.map fst atoms)); } in let request = { wish_install = atoms; wish_remove = []; wish_upgrade = [] } in match OpamSolver.resolve ~verbose:true universe request with | Success solution -> PackageActionGraph.fold_vertex (fun act acc -> match act with | To_change (_, p) -> OpamPackage.Set.add p acc | _ -> acc) solution.PackageActionGraph.to_process OpamPackage.Set.empty | Conflicts cs -> OpamGlobals.error_and_exit "%s\n" (cs()) let process {index; gener_digest; dryrun; recurse; names; debug; resolve} = let () = OpamHTTP.register (); OpamGit.register (); OpamDarcs.register (); OpamLocal.register (); OpamHg.register () in OpamGlobals.debug := !OpamGlobals.debug || debug; let tmp_dirs = [ "tmp"; "log" ] in List.iter (fun dir -> if Sys.file_exists dir then ( OpamGlobals.error "The subdirectory '%s' already exists in the current directory. \n\ Please remove or rename it or run %s in a different folder.\n" dir Sys.argv.(0); exit 1; ) ) tmp_dirs; let () = let checkdir dir = Sys.file_exists dir && Sys.is_directory dir in if not (checkdir "packages" || checkdir "compilers") then OpamGlobals.error_and_exit "No repository found in current directory.\n\ Please make sure there is a \"packages\" or \"compilers\" directory" in let repo = OpamRepository.local (OpamFilename.cwd ()) in let prefixes = OpamRepository.packages_with_prefixes repo in let packages = OpamRepository.packages repo in let mk_packages str = match OpamPackage.of_string_opt str with | Some nv -> OpamPackage.Set.singleton nv | None -> let n = OpamPackage.Name.of_string str in match OpamPackage.Version.Set.elements (OpamPackage.versions_of_name packages n) with | [] -> OpamGlobals.msg "Skipping unknown package %s.\n" str; OpamPackage.Set.empty | versions -> OpamPackage.Set.of_list (List.map (OpamPackage.create n) versions) in let new_packages = List.fold_left (fun accu str -> OpamPackage.Set.union accu (mk_packages str)) OpamPackage.Set.empty names in if names <> [] && OpamPackage.Set.is_empty new_packages then ( OpamGlobals.msg "No package to process.\n"; exit 0 ); (* Read urls.txt *) log "Reading urls.txt"; let local_index_file = OpamFilename.of_string "urls.txt" in let old_index = OpamFile.File_attributes.safe_read local_index_file in let new_index = OpamHTTP.make_urls_txt ~write:(not dryrun) repo.repo_root in let to_remove = OpamFilename.Attribute.Set.diff old_index new_index in let to_add = OpamFilename.Attribute.Set.diff new_index old_index in (* Compute the transitive closure of packages *) let get_dependencies nv = let prefix = OpamPackage.Map.find nv prefixes in let opam_f = OpamPath.Repository.opam repo prefix nv in if OpamFilename.exists opam_f then ( let opam = OpamFile.OPAM.read opam_f in let deps = OpamFile.OPAM.depends opam in let depopts = OpamFile.OPAM.depopts opam in OpamFormula.fold_left (fun accu (n,_) -> OpamPackage.Set.union (mk_packages (OpamPackage.Name.to_string n)) accu ) OpamPackage.Set.empty (OpamFormula.And (deps, depopts)) ) else OpamPackage.Set.empty in let get_transitive_dependencies packages = let rec get_transitive_dependencies_aux visited to_visit = match to_visit with | [] -> visited | nv :: tl -> if OpamPackage.Set.mem nv visited then begin get_transitive_dependencies_aux visited tl end else begin let deps = OpamPackage.Set.elements (get_dependencies nv) in get_transitive_dependencies_aux (* Mark the node as visited. *) (OpamPackage.Set.add nv visited) (* Plan to explore all deps. *) (List.rev_append deps tl) end in get_transitive_dependencies_aux OpamPackage.Set.empty (OpamPackage.Set.elements packages) in let packages = if resolve then resolve_deps new_index names else if recurse then get_transitive_dependencies new_packages else new_packages in let nv_set_of_remotes remotes = let aux r = OpamFilename.create (OpamFilename.cwd ()) (OpamFilename.Attribute.base r) in let list = List.map aux (OpamFilename.Attribute.Set.elements remotes) in OpamPackage.Set.of_list (OpamMisc.filter_map OpamPackage.of_filename list) in let packages_of_attrs attrs = OpamFilename.Attribute.Set.fold (fun attr nvs -> let f = OpamFilename.raw_dir (OpamFilename.Base.to_string (OpamFilename.Attribute.base attr)) in let path = OpamFilename.to_list_dir f in let rec get_nv = function | [_] | [] -> nvs | pkgdir::(f::_ as subpath)-> match OpamPackage.of_dirname pkgdir with | None -> get_nv subpath | Some nv -> match OpamFilename.Dir.to_string f with | "url" | "files" -> OpamPackage.Set.add nv nvs | _ -> nvs in get_nv path) attrs OpamPackage.Set.empty in let new_index = nv_set_of_remotes new_index in let missing_archive = OpamPackage.Set.filter (fun nv -> let archive = OpamPath.Repository.archive repo nv in not (OpamFilename.exists archive) ) new_index in let to_add = let added_changed = packages_of_attrs to_add in let files_removed = OpamPackage.Set.inter new_index (packages_of_attrs to_remove) in let (++) = OpamPackage.Set.union in missing_archive ++ added_changed ++ files_removed in let to_remove = nv_set_of_remotes to_remove in let to_add = if OpamPackage.Set.is_empty packages then to_add else OpamPackage.Set.inter packages to_add in let to_remove = OpamPackage.Set.diff to_remove to_add in let errors = ref [] in if not index then ( (* Remove the old archive files *) if not (OpamPackage.Set.is_empty to_remove) then OpamGlobals.msg "Packages to remove: %s\n" (OpamPackage.Set.to_string to_remove); OpamPackage.Set.iter (fun nv -> let archive = OpamPath.Repository.archive repo nv in OpamGlobals.msg "Removing %s ...\n" (OpamFilename.to_string archive); if not dryrun then OpamFilename.remove archive ) to_remove; (* build the new archives *) if not (OpamPackage.Set.is_empty to_add) then OpamGlobals.msg "Packages to build: %s\n" (OpamPackage.Set.to_string to_add); OpamPackage.Set.iter (fun nv -> let prefix = OpamPackage.Map.find nv prefixes in let local_archive = OpamPath.Repository.archive repo nv in try OpamGlobals.msg "Building %s\n" (OpamFilename.to_string local_archive); if not dryrun then ( OpamFilename.remove local_archive; OpamRepository.make_archive ~gener_digest repo prefix nv; ) with e -> OpamFilename.remove local_archive; errors := (nv, e) :: !errors; ) to_add; ); (* Create index.tar.gz *) if not (OpamFilename.exists (repo.repo_root // "index.tar.gz")) || not (OpamPackage.Set.is_empty to_add) || not (OpamPackage.Set.is_empty to_remove) then ( OpamGlobals.msg "Rebuilding index.tar.gz ...\n"; if not dryrun then ( OpamHTTP.make_index_tar_gz repo.repo_root; ) ) else OpamGlobals.msg "OPAM Repository already up-to-date.\n"; if not dryrun then List.iter OpamSystem.remove tmp_dirs; (* Rebuild urls.txt now the archives have been updated *) OpamGlobals.msg "Rebuilding urls.txt\n"; let _index = OpamHTTP.make_urls_txt ~write:(not dryrun) repo.repo_root in if !errors <> [] then ( let display_error (nv, error) = let disp = OpamGlobals.header_error "%s" (OpamPackage.to_string nv) in match error with | OpamSystem.Process_error r -> disp "%s" (OpamProcess.string_of_result ~color:`red r) | OpamSystem.Internal_error s -> OpamGlobals.error " %s" s | _ -> disp "%s" (Printexc.to_string error) in let all_errors = List.map fst !errors in OpamGlobals.error "Got some errors while processing: %s" (String.concat ", " (List.map OpamPackage.to_string all_errors)); List.iter display_error !errors ) opam-1.1.1/src/scripts/opam_admin.ml0000644000175000017500000000414512272210733015631 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) open Cmdliner let default_cmd = let doc = "Administration tool for local repositories." in Term.(ret (pure (`Help (`Pager, None)))), Term.info "opam-admin" ~version:OpamVersion.(to_string current) ~doc let make_repo_cmd = let doc = "Initialize a repo for serving files." in Term.(Opam_mk_repo.(pure process $ args)), Term.info "make" ~doc let check_repo_cmd = let doc = "Check a local repo for errors." in Term.(Opam_repo_check.(pure process $ args)), Term.info "check" ~doc let stats_cmd = let doc = "Compute statistics." in Term.(Opam_stats.(pure process $ pure ())), Term.info "stats" ~doc let depexts_cmd = let doc = "Add external dependencies." in Term.(Opam_depexts_change.(pure process $ args)), Term.info "depexts" ~doc let () = try match Term.eval_choice ~catch:false default_cmd [make_repo_cmd; check_repo_cmd; stats_cmd; depexts_cmd] with | `Error _ -> exit 2 | _ -> exit 0 with | OpamGlobals.Exit i -> exit i opam-1.1.1/src/scripts/opam_installer.ml0000644000175000017500000002346412272210733016543 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2013 OCamlPro *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) open OpamTypes open Cmdliner type options = { file: OpamFilename.t; pkgname: OpamPackage.Name.t; prefix: OpamFilename.Dir.t; script: bool; } (* A wrapper on top of commands to either proceed, or output a script *) type commands = { mkdir: OpamFilename.Dir.t -> unit; rmdir: opt:bool -> OpamFilename.Dir.t -> unit; cp: opt:bool -> src:OpamFilename.t -> dst:OpamFilename.t -> unit; rm: opt:bool -> OpamFilename.t -> unit; confirm: string -> (unit -> unit) -> unit; } let do_commands project_root = let mkdir d = if not (OpamFilename.exists_dir d) then (OpamGlobals.msg "Creating directory %s\n%!" (OpamFilename.Dir.to_string d); OpamFilename.mkdir d) in let rec rmdir ~opt d = if not (OpamFilename.exists_dir d) then () else if Sys.readdir (OpamFilename.Dir.to_string d) = [||] then (OpamGlobals.msg "Removing empty dir %S\n" (OpamFilename.Dir.to_string d); OpamFilename.rmdir d; let parent = OpamFilename.dirname_dir d in if parent <> d then rmdir ~opt:true parent) else if not opt then OpamGlobals.warning "Directory %S is not empty\n" (OpamFilename.Dir.to_string d) in let cp ~opt ~src ~dst = if OpamFilename.exists src then (OpamGlobals.msg "%-32s => %s\n" (OpamFilename.remove_prefix project_root src) (OpamFilename.to_string dst); mkdir (OpamFilename.dirname dst); OpamFilename.copy ~src ~dst) else if not opt then OpamGlobals.error "Could not find %S" (OpamFilename.to_string src) in let rm ~opt f = if OpamFilename.exists f then (OpamGlobals.msg "Removing %s\n" (OpamFilename.to_string f); OpamFilename.remove f) else if not opt then OpamGlobals.warning "%S doesn't exist" (OpamFilename.to_string f) in let confirm s f = if OpamState.confirm "%s" s then f () in { mkdir; rmdir; cp; rm; confirm } let script_commands project_root ochan = let made_dirs = ref [] in Printf.fprintf ochan "#!/bin/bash\n"; let mkdir d = if not (List.mem d !made_dirs) then ( Printf.fprintf ochan "mkdir -p %S\n" (OpamFilename.Dir.to_string d); made_dirs := d :: !made_dirs ) in let rmdir ~opt d = let f = OpamFilename.Dir.to_string d in Printf.fprintf ochan "if [ -d %S ]\n" f; Printf.fprintf ochan "then rmdir -p %S 2>/dev/null" f; if not opt then Printf.fprintf ochan " ||\n echo \"Warning: could not remove directory %s\"" f; Printf.fprintf ochan "\nfi\n" in let cp ~opt ~src ~dst = mkdir (OpamFilename.dirname dst); (* use 'install' to set permissions ? *) let src = OpamFilename.remove_prefix project_root src in let dst = OpamFilename.to_string dst in Printf.fprintf ochan "if [ -e %S ]\n" src; Printf.fprintf ochan "then cp -f %S %S\n" src dst; if not opt then Printf.fprintf ochan "else echo \"Error: %s doesn't exist\"\n" src; Printf.fprintf ochan "fi\n" in let rm ~opt file = let f = OpamFilename.to_string file in Printf.fprintf ochan "if [ -e %S ]; then rm -f %S\n" f f; if not opt then Printf.fprintf ochan "else echo \"Warning: %s doesn't exist\"\n" f; Printf.fprintf ochan "fi\n" in let confirm msg f = Printf.fprintf ochan "read -p %S' [y/n] ' -n 1 -r; echo; if [ \"$REPLY\" = 'y' ]; then\n" msg; f (); Printf.fprintf ochan "fi\n"; in { mkdir; rmdir; cp; rm; confirm } let iter_install f instfile options = let module D = OpamPath.Switch in let module S = OpamFile.Dot_install in let instdir f = f options.prefix (OpamSwitch.of_string "") in let instf f = f instfile in List.iter f [ instdir D.bin, instf S.bin; instdir D.sbin, instf S.sbin; instdir D.lib options.pkgname, instf S.lib; instdir D.toplevel, instf S.toplevel; instdir D.stublibs, instf S.stublibs; instdir D.man_dir, instf S.man; instdir D.share options.pkgname, instf S.share; instdir D.etc options.pkgname, instf S.etc; instdir D.doc options.pkgname, instf S.doc; ] let install options = let instfile = OpamFile.Dot_install.safe_read options.file in let project_root = OpamFilename.cwd () in let cmd = if options.script then script_commands project_root stdout else do_commands project_root in let install_files (dst_dir, files) = List.iter (fun (base, dst) -> let src_file = OpamFilename.create project_root base.c in let dst_file = match dst with | None -> OpamFilename.create dst_dir (OpamFilename.basename src_file) | Some d -> OpamFilename.create dst_dir d in cmd.cp ~opt:base.optional ~src:src_file ~dst:dst_file) files in iter_install install_files instfile options; List.iter (fun (src, dst) -> let src_file = OpamFilename.create (OpamFilename.cwd ()) src.c in cmd.confirm (Printf.sprintf "Do you want to install %s to %s ?" (OpamFilename.Base.to_string src.c) (OpamFilename.to_string dst)) (fun () -> cmd.cp ~opt:false ~src:src_file ~dst) ) (OpamFile.Dot_install.misc instfile) let uninstall options = let instfile = OpamFile.Dot_install.safe_read options.file in let project_root = OpamFilename.cwd () in let cmd = if options.script then script_commands project_root stdout else do_commands project_root in let dirs_to_remove = ref OpamFilename.Dir.Set.empty in let remove_files (dst_dir, files) = List.iter (fun (base, dst) -> let src_file = OpamFilename.create project_root base.c in let dst_file = match dst with | None -> OpamFilename.create dst_dir (OpamFilename.basename src_file) | Some d -> OpamFilename.create dst_dir d in cmd.rm ~opt:base.optional dst_file; dirs_to_remove := OpamFilename.Dir.Set.add (OpamFilename.dirname dst_file) !dirs_to_remove) files in iter_install remove_files instfile options; List.iter (cmd.rmdir ~opt:true) (List.rev (OpamFilename.Dir.Set.elements !dirs_to_remove)); List.iter (fun df -> cmd.rmdir ~opt:false (df options.prefix (OpamSwitch.of_string "") options.pkgname)) OpamPath.Switch.([ lib; share; etc; doc ]); List.iter (fun (src, dst) -> cmd.confirm (Printf.sprintf "Remove %s ?" (OpamFilename.to_string dst)) (fun () -> cmd.rm ~opt:false dst)) (OpamFile.Dot_install.misc instfile) let options = let file = let doc = "The OPAM .install file to read for installation instructions" in Arg.(required & pos 0 (some string) None & info ~docv:"PKG.install" ~doc []) in let prefix = let doc = "The prefix to install to. You can use \ eg '$$$$PREFIX' to output a relocatable script" in Arg.(value & opt string "/usr/local" & info ~docv:"PREFIX" ~doc ["prefix"]) in let script = let doc = "Don't execute the commands, but output a shell-script (experimental)" in Arg.(value & flag & info ~doc ["script"]) in let pkgname = let doc = "Specify the package name. Used to set install directory under `share/', etc. \ By default, basename of the .install file" in Arg.(value & opt (some string) None & info ~docv:"NAME" ~doc ["name"]) in let make_options file prefix script name = let file = let f = OpamFilename.of_string (file ^ ".install") in if OpamFilename.exists f then f else let f = OpamFilename.of_string file in if OpamFilename.exists f then f else raise (Invalid_argument ("File not found: " ^ file)) in let prefix = OpamFilename.Dir.of_string prefix in let pkgname = match name with | Some n -> OpamPackage.Name.of_string n | None when OpamFilename.check_suffix file ".install" -> OpamPackage.Name.of_string (OpamFilename.Base.to_string (OpamFilename.basename (OpamFilename.chop_extension file))) | None -> raise (Invalid_argument "Could not guess the package name, please specify `--name'") in { file; prefix; script; pkgname } in Term.(pure make_options $ file $ prefix $ script $ pkgname) let command = let remove = Arg.(value & vflag false & [ false, Arg.info ["i";"install"] ~doc:"Install the package (the default)"; true, Arg.info ["u";"uninstall";"remove"] ~doc:"Remove the package"; ]) in Term.( pure (fun options remove -> if remove then uninstall options else install options) $ options $ remove) let info = let doc = "Handles (un)installation of package files following instructions from \ OPAM *.install files." in Term.info "opam-installer" ~version:OpamVersion.(to_string current) ~doc let () = try match Term.eval ~catch:false (command,info) with | `Error _ -> exit 2 | _ -> exit 0 with | Invalid_argument s -> prerr_string "ERROR: "; prerr_endline s; exit 2 | OpamGlobals.Exit i -> exit i opam-1.1.1/src/scripts/opam_stats.ml0000644000175000017500000001326212272210733015677 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) open OpamTypes module Git = struct let exec repo command = OpamFilename.in_dir repo (fun () -> OpamSystem.command command ) let return_one_line repo command = OpamFilename.in_dir repo (fun () -> List.hd (OpamSystem.read_command_output command) ) let return repo command = OpamFilename.in_dir repo (fun () -> (OpamSystem.read_command_output command) ) let commit repo fmt = Printf.kprintf (fun msg -> exec repo [ "git"; "commit"; "-a"; "-m"; msg; "--allow-empty" ] ) fmt let commit_file repo file fmt = Printf.kprintf (fun msg -> if OpamFilename.exists file then let file = OpamFilename.remove_prefix repo file in exec repo [ "git"; "add"; file ]; exec repo [ "git"; "commit"; "-m"; msg; file; "--allow-empty" ]; else OpamGlobals.error_and_exit "Cannot commit %s" (OpamFilename.to_string file); ) fmt let revision repo = return_one_line repo [ "git"; "rev-parse"; "HEAD" ] let commits repo = return repo ["git"; "log"; "master"; "--pretty=format:%H"] let init repo = exec repo ["git"; "init"] let test_tag = "test" let branch repo = exec repo ["git"; "checkout"; "-B"; test_tag] let add repo file = if OpamFilename.exists file then let file = OpamFilename.remove_prefix repo file in exec repo ["git"; "add"; file] let checkout repo hash = exec repo ["git"; "checkout"; hash]; exec repo ["git"; "clean"; "-fdx"] let msg repo commit package fmt = Printf.kprintf (fun str -> OpamGlobals.msg "%-25s %s %-10s %-30s\n" (OpamFilename.Dir.to_string repo) commit (OpamPackage.to_string package) str ) fmt let date repo commit = let r = return_one_line repo [ "git"; "show"; "-s"; "--format=\"%ct\""; commit ] in let r = OpamMisc.strip r in let r = String.sub r 1 (String.length r - 2) in float_of_string r let files repo commit dir = return repo [ "git"; "ls-tree"; commit; dir ^ "/"; "--name-only"; "-r" ] let authors repo commit = return repo ["git"; "shortlog"; "-sne"; "--no-merges"; commit ] end type stats = { commit : string; date : float; authors : string list; packages: package_set; names : name_set; } let compare_stats s1 s2 = int_of_float (s1.date -. s2.date) let stats repo = let commits = Git.commits repo in let n = List.length commits in Printf.printf "Commits: %d\n%!" n; let c = ref 0 in let stats = List.map (fun commit -> Printf.printf "\r%d / %d%!" !c n; incr c; let date = Git.date repo commit in let files = Git.files repo commit "packages" in let authors = Git.authors repo commit in let packages = List.fold_left (fun packages f -> if Filename.basename f <> "opam" then packages else match OpamPackage.of_string_opt (Filename.basename (Filename.dirname f)) with | None -> packages | Some nv -> OpamPackage.Set.add nv packages ) OpamPackage.Set.empty files in let names = OpamPackage.Set.fold (fun nv names -> OpamPackage.Name.Set.add (OpamPackage.name nv) names ) packages OpamPackage.Name.Set.empty in { commit; date; authors; packages; names } ) commits in Printf.printf "\n"; List.sort compare_stats stats let display stats fn ylabel output = let dotfile = output ^ ".dot" in let oc = open_out dotfile in Printf.fprintf oc "#!/usr/bin/gnuplot\n\ set xdata time\n\ set timefmt \"%%s\"\n\ set format x \"%%m/%%Y\"\n\ set term png size 800,400 font \"Arial,10\"\n\ set output '%s.png\n\ unset key\n\ set style data lines\n\ set style fill transparent solid 0.4\n\ set grid\n\ set xlabel 'Time'\n\ set ylabel '%s'\n\ set datafile separator \";\"\n\ plot '-' using 1:($2) with filledcurves below x1 lt rgb 'dark-blue' lw 3\n" output ylabel; List.iter (fun stats -> Printf.fprintf oc "%.0f;%d\n" stats.date (fn stats) ) stats; Printf.fprintf oc "e"; close_out oc; Printf.printf "Generating %s.png ...\n" output; OpamSystem.command ["gnuplot"; dotfile ] let process () = let stats = stats (OpamFilename.cwd ()) in List.iter (fun (fn, ylabel, output) -> display stats fn ylabel output ) [ ((fun s -> List.length s.authors), "Contributors", "contributors"); ((fun s -> OpamPackage.Set.cardinal s.packages), "Packages", "packages"); ((fun s -> OpamPackage.Name.Set.cardinal s.names), "Unique Packages", "unique-packages"); ] opam-1.1.1/src/scripts/opam_check.ml0000644000175000017500000000507612272210733015622 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) (* Utility helper to check if a given set of packages is installed *) let usage = "opam-check [--root root] [-l label] +" let label = ref "" let spec = Arg.align [ ("--root", Arg.Set_string OpamGlobals.root_dir, " Set opam path"); ("-l" , Arg.Set_string label , " Set a test label"); ("--version", Arg.Unit OpamVersion.message , " Display version information"); ] let packages = ref [] let ano x = packages := x :: !packages let () = Arg.parse spec ano usage let packages = OpamPackage.Set.of_list (List.map OpamPackage.of_string !packages) let installed () = let root = OpamPath.root () in let config = OpamFile.Config.read (OpamPath.config root) in let version = OpamFile.Config.switch config in let installed = OpamFile.Installed.safe_read (OpamPath.Switch.installed root version) in OpamPackage.Set.filter (fun nv -> OpamPackage.name nv <> OpamPackage.Name.global_config ) installed let () = let installed = installed () in let diff1 = OpamPackage.Set.diff packages installed in let diff2 = OpamPackage.Set.diff installed packages in let diff = OpamPackage.Set.union diff1 diff2 in let label = if !label = "" then "" else Printf.sprintf "[%s] " !label in if not (OpamPackage.Set.is_empty diff) then ( OpamGlobals.error "%swaiting for: %s" label (OpamPackage.Set.to_string diff1); OpamGlobals.error "%sgot: %s" label (OpamPackage.Set.to_string diff2); exit 1 ) opam-1.1.1/src/scripts/opam_repo_check.mli0000644000175000017500000000230712272210733017012 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) type args val args: args Cmdliner.Term.t val process: args -> unit opam-1.1.1/src/scripts/opam_repo_check.ml0000644000175000017500000000641612272210733016646 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) (* Script to check that a given repository is well-typed (or well-parsed) *) open OpamFilename.OP type args = { normalize: bool; } let args = let open Cmdliner in let normalize = let doc = "Normalize all files in the repository." in Arg.(value & flag & info ["n";"normalize"] ~doc) in Term.(pure (fun globals normalize -> OpamArg.apply_global_options globals; { normalize } ) $ OpamArg.global_options $ normalize) let process args = let write f_write fic st = if args.normalize then f_write fic st in let repo = OpamRepository.local (OpamFilename.cwd ()) in let packages = OpamRepository.packages_with_prefixes repo in (** packages *) OpamPackage.Map.iter (fun package prefix -> OpamGlobals.msg "Processing package %s\n" (OpamPackage.to_string package); (** OPAM *) let opam = OpamPath.Repository.opam repo prefix package in write OpamFile.OPAM.write opam (OpamFile.OPAM.read opam); (** Descr *) let descr = OpamPath.Repository.descr repo prefix package in if OpamFilename.exists descr then write OpamFile.Descr.write descr (OpamFile.Descr.read descr); (** URL *) let url = OpamPath.Repository.url repo prefix package in if OpamFilename.exists url then write OpamFile.URL.write url (OpamFile.URL.read url); (** Dot_install *) let dot_install = OpamPath.Repository.files repo prefix package // (OpamPackage.Name.to_string (OpamPackage.name package) ^ ".install") in if OpamFilename.exists dot_install then write OpamFile.Dot_install.write dot_install (OpamFile.Dot_install.read dot_install); ) packages; (** compilers *) let compilers = OpamRepository.compilers_with_prefixes repo in OpamCompiler.Map.iter (fun c prefix -> let comp = OpamPath.Repository.compiler_comp repo prefix c in let descr = OpamPath.Repository.compiler_descr repo prefix c in OpamGlobals.msg "Processing compiler %s\n" (OpamCompiler.to_string c); write OpamFile.Comp.write comp (OpamFile.Comp.read comp); if OpamFilename.exists descr then write OpamFile.Descr.write descr (OpamFile.Descr.read descr); ) compilers opam-1.1.1/src/scripts/opam_stats.mli0000644000175000017500000000223612272210733016047 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) val process: unit -> unit opam-1.1.1/src/scripts/scripts.ocp0000644000175000017500000000065112272210733015363 0ustar i33173i33173comp += [ "-warn-error" "A" ] begin program "opam-check" files = [ "opam_check.ml" ] requires = [ "opam-client" ] end begin program "opam-admin" files = [ "opam_mk_repo.ml" "opam_repo_check.ml" "opam_stats.ml" "opam_depexts_change.ml" "opam_admin.ml" ] requires = [ "opam-client" ] end begin program "opam-installer" files = [ "opam_installer.ml" ] requires = [ "opam-client" ] end opam-1.1.1/src/repositories/0000755000175000017500000000000012272210733014227 5ustar i33173i33173opam-1.1.1/src/repositories/opamHTTP.mli0000644000175000017500000000250712272210733016372 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) (** Curl repository backend *) open OpamTypes val make_index_tar_gz: repository_root -> unit val make_urls_txt: write:bool -> repository_root -> file_attribute_set val register: unit -> unit opam-1.1.1/src/repositories/opamVCS.ml0000644000175000017500000000646712272210733016106 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) let log fmt = OpamGlobals.log "VCS" fmt open OpamTypes module type VCS = sig val exists: repository -> bool val init: repository -> unit val fetch: repository -> unit val reset: repository -> unit val diff: repository -> bool val revision: repository -> string end module Make (VCS: VCS) = struct let init repo = VCS.init repo let pull repo = VCS.fetch repo; let diff = VCS.diff repo in VCS.reset repo; diff let check_updates repo = if VCS.exists repo then begin Some (pull repo) end else None let rec pull_repo repo = match check_updates repo with | None -> OpamFilename.mkdir repo.repo_root; OpamFilename.in_dir repo.repo_root (fun () -> VCS.init repo); pull_repo repo | Some updated -> if updated then Result repo.repo_root else Up_to_date repo.repo_root let repo dirname address = let repo = OpamRepository.default () in { repo with repo_root = dirname; repo_address = address; } let pull_url package dirname checksum remote_url = let () = match checksum with | None -> () | Some _ -> OpamGlobals.note "Skipping checksum for dev package %s" (OpamPackage.to_string package) in let repo = repo dirname remote_url in OpamGlobals.msg "%-10s Fetching %s\n" (OpamPackage.to_string package) (string_of_address remote_url); download_dir (pull_repo repo) let pull_repo repo = OpamGlobals.msg "%-10s Fetching %s\n" (OpamRepositoryName.to_string repo.repo_name) (string_of_address repo.repo_address); ignore (pull_repo repo) let pull_archive repo filename = let dirname = OpamPath.Repository.archives_dir repo in let basename = OpamFilename.basename filename in let local_file = OpamFilename.create dirname basename in if OpamFilename.exists local_file then ( OpamGlobals.msg "%-10s Using %s\n" (OpamRepositoryName.to_string repo.repo_name) (OpamFilename.prettify local_file); Up_to_date local_file ) else Not_available (OpamFilename.to_string filename) let revision repo = Some (OpamPackage.Version.of_string (VCS.revision repo)) end opam-1.1.1/src/repositories/opamLocal.ml0000644000175000017500000001333312272210733016473 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) open OpamTypes let log fmt = OpamGlobals.log "RSYNC" fmt let rsync_arg = "-rLptgoDrvc" let rsync src dst = log "rsync: src=%s dst=%s" src dst; if Sys.file_exists src then ( if src <> dst then ( OpamSystem.mkdir src; OpamSystem.mkdir dst; let lines = OpamSystem.read_command_output ( [ "rsync" ; rsync_arg; "--exclude"; ".git"; "--exclude"; "_darcs"; "--exclude"; ".hg"; "--exclude"; ".#*"; "--delete"; src; dst; ] ) in match OpamMisc.rsync_trim lines with | [] -> Up_to_date [] | lines -> Result lines ) else Up_to_date [] ) else Not_available src let rsync_dirs src dst = let src_s = Filename.concat (OpamFilename.Dir.to_string src) "" in let dst_s = OpamFilename.Dir.to_string dst in match rsync src_s dst_s with | Not_available s -> Not_available s | Result _ -> Result dst | Up_to_date _ -> Up_to_date dst let rsync_file src dst = log "rsync_file src=%s dst=%s" (OpamFilename.to_string src) (OpamFilename.to_string dst); if OpamFilename.exists src then ( let lines = OpamSystem.read_command_output [ "rsync"; rsync_arg; OpamFilename.to_string src; OpamFilename.to_string dst; ] in match OpamMisc.rsync_trim lines with | [] -> Up_to_date dst | [_] -> Result dst | l -> OpamSystem.internal_error "unknown rsync output: {%s}" (String.concat ", " l) ) else Not_available (OpamFilename.to_string src) module B = struct let pull_file_quiet local_dirname remote_filename = let local_filename = OpamFilename.create local_dirname (OpamFilename.basename remote_filename) in rsync_file remote_filename local_filename let pull_dir_quiet local_dirname remote_dirname = rsync_dirs remote_dirname local_dirname let pull_repo repo = log "pull-repo"; OpamGlobals.msg "%-10s Synchronizing with %s\n" (OpamRepositoryName.to_string repo.repo_name) (string_of_address repo.repo_address); ignore (pull_file_quiet repo.repo_root (OpamPath.Repository.remote_repo repo)); List.iter (fun (local, remote) -> ignore (pull_dir_quiet (local repo) (remote repo))) [ (OpamPath.Repository.packages_dir , OpamPath.Repository.remote_packages_dir); (OpamPath.Repository.compilers_dir, OpamPath.Repository.remote_compilers_dir); ]; let archives = OpamFilename.files (OpamPath.Repository.archives_dir repo) in log "archives: %s" (OpamMisc.string_of_list OpamFilename.to_string archives); List.iter (fun archive -> match OpamPackage.of_archive archive with | None -> OpamGlobals.msg "Removing %s\n." (OpamFilename.to_string archive); OpamFilename.remove archive | Some nv -> let remote_filename = OpamPath.Repository.remote_archive repo nv in match rsync_file remote_filename archive with | Not_available _ -> OpamFilename.remove archive | _ -> () ) archives let pull_file package local_dirname remote_filename = if OpamFilename.exists remote_filename then OpamGlobals.msg "%-10s Synchronizing with %s\n" (OpamPackage.to_string package) (OpamFilename.to_string remote_filename); pull_file_quiet local_dirname remote_filename let pull_dir package local_dirname remote_dirname = OpamGlobals.msg "%-10s Synchronizing with %s\n" (OpamPackage.to_string package) (OpamFilename.Dir.to_string remote_dirname); pull_dir_quiet local_dirname remote_dirname let pull_url package local_dirname checksum remote_url = let remote_url = string_of_address remote_url in OpamFilename.mkdir local_dirname; if Sys.file_exists remote_url && Sys.is_directory remote_url then download_dir (pull_dir package local_dirname (OpamFilename.Dir.of_string remote_url)) else if Sys.file_exists remote_url then ( let filename = OpamFilename.of_string remote_url in OpamRepository.check_digest filename checksum; download_file (pull_file package local_dirname filename) ) else Not_available remote_url let pull_archive repo filename = if OpamFilename.exists filename then OpamGlobals.msg "%-10s Synchronizing with %s\n" (OpamRepositoryName.to_string repo.repo_name) (OpamFilename.to_string filename); let local_dir = OpamPath.Repository.archives_dir repo in OpamFilename.mkdir local_dir; pull_file_quiet local_dir filename let revision _ = None end let register () = OpamRepository.register_backend `local (module B: OpamRepository.BACKEND) opam-1.1.1/src/repositories/opamGit.ml0000644000175000017500000000677412272210733016177 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) open OpamTypes open OpamFilename.OP let log fmt = OpamGlobals.log "GIT" fmt module Git = struct let exists repo = OpamFilename.exists_dir (repo.repo_root / ".git") let init repo = OpamFilename.in_dir repo.repo_root (fun () -> OpamSystem.commands [ [ "git" ; "init" ] ; [ "git" ; "remote" ; "add" ; "origin" ; fst repo.repo_address ] ; ] ) let fetch repo = OpamFilename.in_dir repo.repo_root (fun () -> OpamSystem.command [ "git" ; "remote" ; "set-url" ; "origin" ; fst repo.repo_address ]; OpamSystem.command [ "git" ; "fetch" ; "origin" ] ) let revision repo = OpamFilename.in_dir repo.repo_root (fun () -> match OpamSystem.read_command_output [ "git" ; "rev-parse" ; "HEAD" ] with | [] -> "" | full::_ -> if String.length full > 8 then String.sub full 0 8 else full ) let get_commits repo = match snd repo.repo_address with | None -> [ "refs/remotes/origin/master" ] | Some c -> [ "refs/remotes/origin/"^c; "refs/tags/"^c; c ] let reset repo = let merge commit = try OpamSystem.command [ "git" ; "reset" ; "--hard"; commit; "--" ]; true with _ -> false in OpamFilename.in_dir repo.repo_root (fun () -> let ok = List.fold_left (fun ok commit -> if ok then ok else merge commit) false (get_commits repo) in if not ok then OpamSystem.internal_error "Unknown revision: %s." (match snd repo.repo_address with Some a -> a | None -> "master") ) let diff repo = let diff commit = try Some ( OpamSystem.read_command_output ["git" ; "diff" ; "--name-only" ; commit ; "--" ]) with _ -> None in OpamFilename.in_dir repo.repo_root (fun () -> let diff = List.fold_left (fun r commit -> match r with | None -> diff commit | Some x -> Some x) None (get_commits repo) in match diff with | Some [] -> false | Some _ -> true | None -> OpamSystem.internal_error "Unknown revision: %s." (match snd repo.repo_address with Some a -> a | None -> "master") ) end module B = OpamVCS.Make(Git) let register () = OpamRepository.register_backend `git (module B: OpamRepository.BACKEND) opam-1.1.1/src/repositories/opamHTTP.ml0000644000175000017500000002433012272210733016217 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) open OpamTypes open OpamFilename.OP let log msg = OpamGlobals.log "CURL" msg type state = { remote_dir : dirname; local_dir : dirname; remote_index_archive: filename; local_index_archive : filename; local_files : filename_set; remote_local : filename filename_map; local_remote : filename filename_map; file_permissions : (filename * int) list; file_digests : (filename * string) list; } let state_cache = ref [] let index_file local_path = local_path // "urls.txt" let index_file_save local_path = local_path // "urls.txt.0" let index_archive local_path = local_path // "index.tar.gz" let local_files repo = let all = OpamPath.Repository.repo repo :: OpamFilename.rec_files (OpamPath.Repository.packages_dir repo) @ OpamFilename.rec_files (OpamPath.Repository.archives_dir repo) @ OpamFilename.rec_files (OpamPath.Repository.compilers_dir repo) in List.filter OpamFilename.exists all let make_state ~download_index repo = if List.mem_assoc repo.repo_address !state_cache then List.assoc repo.repo_address !state_cache else ( let repo_address = OpamFilename.raw_dir (fst repo.repo_address) in let remote_index_file = repo_address // "urls.txt" in let local_index_file = index_file repo.repo_root in let local_index_file_save = index_file_save repo.repo_root in let remote_index_archive = repo_address // "index.tar.gz" in let local_index_archive = repo.repo_root // "index.tar.gz" in let index = if download_index then ( if OpamFilename.exists local_index_file then OpamFilename.move ~src:local_index_file ~dst:local_index_file_save; try OpamGlobals.msg "%-10s Downloading %s\n" (OpamRepositoryName.to_string repo.repo_name) (OpamFilename.to_string remote_index_file); let file = OpamFilename.download ~overwrite:false remote_index_file repo.repo_root in OpamFilename.remove local_index_file_save; file; with e -> if OpamFilename.exists local_index_file_save then OpamFilename.move ~src:local_index_file_save ~dst:local_index_file; raise e ) else local_index_file in let remote_local, local_remote, local_files, file_permissions, file_digests = let urls = OpamFile.File_attributes.read index in let remote_local, local_remote, locals, perms, digests = OpamFilename.Attribute.Set.fold (fun r (rl, lr, locals, perms, digests) -> let base = OpamFilename.Attribute.base r in let perm = match OpamFilename.Attribute.perm r with | None -> 0o640 | Some p -> p in let digest = OpamFilename.Attribute.md5 r in let remote = repo_address // OpamFilename.Base.to_string base in let local = OpamFilename.create repo.repo_root base in OpamFilename.Map.add remote local rl, OpamFilename.Map.add local remote lr, OpamFilename.Set.add local locals, (local, perm) :: perms, (local, digest) :: digests ) urls (OpamFilename.Map.empty, OpamFilename.Map.empty, OpamFilename.Set.empty, [], []) in remote_local, local_remote, locals, perms, digests in let state = { remote_dir = repo_address; local_dir = repo.repo_root; remote_index_archive; local_index_archive; local_files; remote_local; local_remote; file_permissions; file_digests; } in state_cache := (repo.repo_address, state) :: !state_cache; state ) let is_up_to_date state local_file = List.mem_assoc local_file state.file_digests && OpamFilename.exists local_file && not (Sys.is_directory (OpamFilename.to_string local_file)) && List.assoc local_file state.file_digests = OpamFilename.digest local_file let get_checksum state local_file = if List.mem_assoc local_file state.file_digests && OpamFilename.exists local_file && not (Sys.is_directory (OpamFilename.to_string local_file)) then let expected = List.assoc local_file state.file_digests in let actual = OpamFilename.digest local_file in Some (actual, expected) else None module B = struct let repo repo_root repo_address = { repo_name = OpamRepositoryName.of_string "http"; repo_priority = 0; repo_kind = `http; repo_root; repo_address; } let init repo = log "init"; try (* Download urls.txt *) let state = make_state ~download_index:true repo in try (* Download index.tar.gz *) OpamGlobals.msg "%-10s Downloading %s\n" (OpamRepositoryName.to_string repo.repo_name) (OpamFilename.to_string state.remote_index_archive); let file = OpamFilename.download ~overwrite:true state.remote_index_archive state.local_dir in OpamFilename.extract_in file state.local_dir with _ -> OpamGlobals.msg "Cannot find index.tar.gz on the OPAM repository. \ Initialisation might take some time.\n" with _ -> OpamGlobals.error_and_exit "%s is unavailable." (string_of_address repo.repo_address) let curl ~remote_file ~local_file = log "curl"; log "dowloading %s" (OpamFilename.to_string remote_file); OpamGlobals.msg "Downloading %s\n" (OpamFilename.to_string remote_file); OpamFilename.download_as ~overwrite:true remote_file local_file let pull_repo repo = log "pull-repo"; let local_files = local_files repo in let state = make_state ~download_index:true repo in if state.local_dir <> state.remote_dir then ( let (--) = OpamFilename.Set.diff in let current = OpamFilename.Set.of_list local_files in let to_keep = OpamFilename.Set.filter (is_up_to_date state) state.local_files in let to_delete = current -- to_keep in let new_files = let archives_dir = OpamPath.Repository.archives_dir repo in (OpamFilename.Set.filter (fun f -> not (OpamFilename.starts_with archives_dir f)) state.local_files) -- to_keep in log "current: %d files" (OpamFilename.Set.cardinal current); log "to_keep: %d files" (OpamFilename.Set.cardinal to_keep); log "to_delete: %s" (OpamFilename.Set.to_string to_delete); log "new_files: %s" (OpamFilename.Set.to_string new_files); OpamFilename.Set.iter OpamFilename.remove to_delete; if OpamFilename.Set.cardinal new_files > 4 then init repo else OpamFilename.Set.iter (fun local_file -> let remote_file = OpamFilename.Map.find local_file state.local_remote in curl ~remote_file ~local_file ) new_files; ) let pull_url package dirname checksum remote_url = log "pull-file"; let remote_url = string_of_address remote_url in let filename = OpamFilename.of_string remote_url in let base = OpamFilename.basename filename in let local_file = OpamFilename.create dirname base in if OpamFilename.exists local_file && match checksum with | None -> false | Some c -> OpamFilename.digest local_file = c then ( OpamGlobals.msg "%-10s %s is in the local cache, using it.\n" (OpamPackage.to_string package) (OpamFilename.Base.to_string base); Result (F local_file) ) else ( OpamGlobals.msg "%-10s Downloading %s\n" (OpamPackage.to_string package) (OpamFilename.to_string filename); try let local_file = OpamFilename.download ~overwrite:true filename dirname in OpamRepository.check_digest local_file checksum; Result (F local_file) with _ -> Not_available remote_url ) let pull_archive repo filename = log "pull-archive"; let state = make_state ~download_index:false repo in if OpamFilename.Map.mem filename state.remote_local then ( let local_file = OpamFilename.Map.find filename state.remote_local in if is_up_to_date state local_file then Up_to_date local_file else ( OpamGlobals.msg "%-10s Downloading %s\n" (OpamRepositoryName.to_string repo.repo_name) (OpamFilename.prettify filename); curl ~remote_file:filename ~local_file; Result local_file ) ) else Not_available (OpamFilename.to_string filename) let revision _ = None end let make_urls_txt ~write repo_root = let repo = OpamRepository.local repo_root in let local_index_file = OpamFilename.of_string "urls.txt" in log "Scanning %s" (OpamFilename.Dir.to_string repo_root); let index = List.fold_left (fun set f -> if not (OpamFilename.exists f) then set else let attr = OpamFilename.to_attribute repo_root f in OpamFilename.Attribute.Set.add attr set ) OpamFilename.Attribute.Set.empty (local_files repo) in if write then OpamFile.File_attributes.write local_index_file index; index let make_index_tar_gz repo_root = OpamFilename.in_dir repo_root (fun () -> let dirs = [ "version"; "compilers"; "packages" ] in match List.filter Sys.file_exists dirs with | [] -> () | d -> OpamSystem.command ("tar" :: "czf" :: "index.tar.gz" :: d) ) let register () = OpamRepository.register_backend `http (module B : OpamRepository.BACKEND) opam-1.1.1/src/repositories/opamVCS.mli0000644000175000017500000000405112272210733016242 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) (** Generic backend for version-control systems. *) open OpamTypes (** Each backend should implement this signature. *) module type VCS = sig (** Test whether the given repository is correctly initialized. *) val exists: repository -> bool (** Init a repository. *) val init: repository -> unit (** Fetch changes from upstream. This is supposed to put the changes in a staging area. Be aware that the remote URL might have been changed, so make sure to update accordingly. *) val fetch: repository -> unit (** Reset the master branch of the repository to match the remote repository state. *) val reset: repository -> unit (** Check whether the staging area is empty. *) val diff: repository -> bool (** Return the HEAD revision. *) val revision: repository -> string end (** Create a backend from a [VCS] implementation. *) module Make(VCS: VCS): OpamRepository.BACKEND opam-1.1.1/src/repositories/opamHg.mli0000644000175000017500000000227612272210733016154 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) (** Git repository backend *) val register: unit -> unit opam-1.1.1/src/repositories/opamDarcs.mli0000644000175000017500000000230012272210733016636 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) (** Darcs repository backend *) val register: unit -> unit opam-1.1.1/src/repositories/repositories.ocp0000644000175000017500000000034712272210733017465 0ustar i33173i33173comp += [ "-warn-error" "A" ] begin library "opam-repositories" files = [ "opamHTTP.ml" "opamLocal.ml" "opamVCS.ml" "opamGit.ml" "opamDarcs.ml" "opamHg.ml" ] requires = [ "opam-core" ] end opam-1.1.1/src/repositories/opamGit.mli0000644000175000017500000000227612272210733016341 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) (** Git repository backend *) val register: unit -> unit opam-1.1.1/src/repositories/opamLocal.mli0000644000175000017500000000230012272210733016634 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) (** Rsync repository backend *) val register: unit -> unit opam-1.1.1/src/repositories/opamHg.ml0000644000175000017500000000635212272210733016002 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) open OpamTypes open OpamFilename.OP let log fmt = OpamGlobals.log "HG" fmt module Hg = struct let exists repo = OpamFilename.exists_dir (repo.repo_root / ".hg") let init repo = OpamFilename.in_dir repo.repo_root (fun () -> OpamSystem.command [ "hg" ; "init" ]; OpamFilename.write (OpamFilename.of_string ".hg/hgrc") (Printf.sprintf "[paths]\ndefault = %s\n" (fst repo.repo_address)) ) let fetch repo = OpamFilename.in_dir repo.repo_root (fun () -> let url = OpamSystem.read_command_output [ "hg" ; "showconfig" ; "paths.default" ] in if url <> [fst repo.repo_address] then ( OpamSystem.remove_dir ".hg"; init repo ); OpamSystem.command [ "hg" ; "pull" ] ) let revision repo = OpamFilename.in_dir repo.repo_root (fun () -> match OpamSystem.read_command_output [ "hg" ; "id" ; "-i" ] with | [] -> "" | full::_ -> if String.length full > 8 then String.sub full 0 8 else full ) let unknown_commit commit = OpamSystem.internal_error "Unknown mercurial revision/branch/bookmark: %s." commit let reset repo = let merge commit = try OpamSystem.command [ "hg" ; "update" ; "--clean"; commit ]; true with _ -> false in let commit = match snd repo.repo_address with | None -> "tip" | Some c -> c in OpamFilename.in_dir repo.repo_root (fun () -> if not (merge commit) then unknown_commit commit ) let diff repo = let diff commit = try Some ( OpamSystem.read_command_output ["hg" ; "diff" ; "--stat" ; "-r" ; commit ]) with _ -> None in let commit = match snd repo.repo_address with | None -> "tip" | Some c -> c in OpamFilename.in_dir repo.repo_root (fun () -> match diff commit with | Some [] -> false | Some _ -> true | None -> unknown_commit commit ) end module B = OpamVCS.Make(Hg) let register () = OpamRepository.register_backend `hg (module B: OpamRepository.BACKEND) opam-1.1.1/src/repositories/opamDarcs.ml0000644000175000017500000000461412272210733016477 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) open OpamTypes open OpamFilename.OP let log fmt = OpamGlobals.log "Darcs" fmt module Darcs = struct let exists repo = OpamFilename.exists_dir (repo.repo_root / "_darcs") let init repo = OpamFilename.in_dir repo.repo_root (fun () -> OpamSystem.commands [ [ "darcs" ; "init" ]; [ "darcs" ; "get" ; fst repo.repo_address; "--lazy" ]; ]; ) (* With darcs, it is apparently easier to compute a diff between remote and local, without fething at all. So we set fetch to be a no-op. *) let fetch _ = () (* Merge is actually a full pull *) let reset repo = OpamFilename.in_dir repo.repo_root (fun () -> OpamSystem.command [ "darcs" ; "pull"; fst repo.repo_address; "--all"; "--quiet" ]; ) (* Difference between remote and local is a 'pull --dry-run' *) let diff repo = OpamFilename.in_dir repo.repo_root (fun () -> let patches = OpamSystem.read_command_output [ "darcs" ; "pull" ; fst repo.repo_address; "--dry-run" ; "--quiet" ] in patches <> [] ) let revision _ = "" end module B = OpamVCS.Make(Darcs) let register () = OpamRepository.register_backend `darcs (module B: OpamRepository.BACKEND) opam-1.1.1/src/opam.ocp0000644000175000017500000000004212272210733013133 0ustar i33173i33173comp += [ "-g" ] link += [ "-g" ] opam-1.1.1/src/solver/0000755000175000017500000000000012272210733013012 5ustar i33173i33173opam-1.1.1/src/solver/opamSolver.ml0000644000175000017500000003757212272210733015511 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) open OpamTypes let log fmt = OpamGlobals.log "SOLVER" fmt (* see [Debcudf.add_inst] for more details about the format *) let s_status = "status" let s_installed = " installed" let empty_universe = { u_packages = OpamPackage.Set.empty; u_installed = OpamPackage.Set.empty; u_available = OpamPackage.Set.empty; u_depends = OpamPackage.Map.empty; u_depopts = OpamPackage.Map.empty; u_conflicts = OpamPackage.Map.empty; u_action = Install OpamPackage.Name.Set.empty; u_installed_roots = OpamPackage.Set.empty; u_pinned = OpamPackage.Name.Map.empty } (* Returns the package with its real version if it has been pinned *) let real_version universe pkg = if OpamPackage.is_pinned pkg then let n = OpamPackage.name pkg in let v = Lazy.force (OpamPackage.Name.Map.find n universe.u_pinned) in OpamPackage.create n v else pkg (* Convert an OPAM formula into a debian formula *) let atom2debian (n, v) = (OpamPackage.Name.to_string n, None), match v with | None -> None | Some (r,v) -> Some (OpamFormula.string_of_relop r, OpamPackage.Version.to_string v) (* Get the optional depencies of a package *) let depopts_of_package universe package = let opts = try OpamPackage.Map.find package universe.u_depopts with Not_found -> Empty in OpamFormula.to_dnf opts (* Convert an OPAM package to a debian package *) let opam2debian universe depopts package = let package = real_version universe package in let depends = try OpamPackage.Map.find package universe.u_depends with Not_found -> Empty in let depends = let opts = depopts_of_package universe package in if depopts then let opts = List.rev_map OpamFormula.of_conjunction opts in And (depends, Or(depends, OpamFormula.ors opts)) else if universe.u_action = Remove then depends else let mem_installed conj = let is_installed (name,_) = OpamPackage.Set.exists (fun pkg -> OpamPackage.name pkg = name) universe.u_installed in List.exists is_installed conj in let opts = List.filter mem_installed opts in let opts = List.rev_map OpamFormula.of_conjunction opts in And (depends, OpamFormula.ands opts) in let conflicts = try OpamPackage.Map.find package universe.u_conflicts with Not_found -> Empty in let installed = OpamPackage.Set.exists (fun pkg -> real_version universe pkg = package) universe.u_installed in let reinstall = match universe.u_action with | Upgrade reinstall -> OpamPackage.Set.exists (fun pkg -> package = real_version universe pkg) reinstall | _ -> false in let installed_root = OpamPackage.Set.mem package universe.u_installed_roots in let open Debian.Packages in { Debian.Packages.default_package with name = OpamPackage.Name.to_string (OpamPackage.name package) ; version = OpamPackage.Version.to_string (OpamPackage.version package); depends = List.rev_map (List.rev_map atom2debian) (OpamFormula.to_cnf depends); conflicts = List.rev_map atom2debian (OpamFormula.to_conjunction conflicts); extras = (if installed && reinstall then [OpamCudf.s_reinstall, "true"] else []) @ (if installed then [s_status, s_installed] else []) @ (if installed_root then [OpamCudf.s_installed_root, "true"] else []) @ Debian.Packages.default_package.extras } (* Convert an debian package to a CUDF package *) let debian2cudf tables package = let options = { Debian.Debcudf.default_options with Debian.Debcudf.extras_opt = [ OpamCudf.s_reinstall, (OpamCudf.s_reinstall, `Bool (Some false)); OpamCudf.s_installed_root, (OpamCudf.s_installed_root, `Bool (Some false)); ] } in Debian.Debcudf.tocudf ~options tables package let atom2cudf opam2cudf (n, v) : Cudf_types.vpkg = Common.CudfAdd.encode (OpamPackage.Name.to_string n), match v with | None -> None | Some (r,v) -> let pkg = try opam2cudf (OpamPackage.create n v) with Not_found -> OpamGlobals.error_and_exit "Package %s does not have a version %s" (OpamPackage.Name.to_string n) (OpamPackage.Version.to_string v) in Some (r, pkg.Cudf.version) (* load a cudf universe from an opam one *) let load_cudf_universe ?(depopts=false) universe = (* The package numbering can be different in the universe if we consider optional dependencies or not. To avoid that, we create a dumb package which depends on all the optional dependencies. This package should never appear to the user, so we make it non-installable by adding conflicting constraints. *) let universe = let dummy_pkg = OpamPackage.create (OpamPackage.Name.of_string "--depopts--") (OpamPackage.Version.of_string "--none--") in let dummy_atom = Atom (OpamPackage.Name.of_string "--depopts--", Atom (`Eq, OpamPackage.Version.of_string "--")) in if not depopts then ( let depopts = let all = OpamPackage.Set.fold (fun pkg acc -> depopts_of_package universe pkg @ acc ) universe.u_packages [] in let all = List.rev_map OpamFormula.of_conjunction all in And(dummy_atom, OpamFormula.ands all) in { universe with u_packages = OpamPackage.Set.add dummy_pkg universe.u_packages; u_depends = OpamPackage.Map.add dummy_pkg depopts universe.u_depends; } ) else { universe with u_packages = OpamPackage.Set.add dummy_pkg universe.u_packages; u_depends = OpamPackage.Map.add dummy_pkg dummy_atom universe.u_depends; } in let opam2cudf = let opam2debian = OpamPackage.Set.fold (fun pkg map -> OpamPackage.Map.add (real_version universe pkg) (opam2debian universe depopts pkg) map) universe.u_packages OpamPackage.Map.empty in let tables = Debian.Debcudf.init_tables (OpamPackage.Map.values opam2debian) in OpamPackage.Map.map (debian2cudf tables) opam2debian in let cudf2opam = let h = Hashtbl.create 1024 in OpamPackage.Map.iter (fun opam cudf -> let opam = try if Lazy.force (OpamPackage.Name.Map.find (OpamPackage.name opam) universe.u_pinned) = OpamPackage.version opam then OpamPackage.pinned (OpamPackage.name opam) else opam with Not_found -> opam in Hashtbl.add h (cudf.Cudf.package,cudf.Cudf.version) opam ) opam2cudf; h in let opam_universe = universe in let universe = let universe = OpamPackage.Set.fold (fun nv list -> try let nv = OpamPackage.Map.find (real_version universe nv) opam2cudf in nv :: list with Not_found -> OpamGlobals.error "The package %s (real-version: %s) cannot be found by the solver, \ skipping." (OpamPackage.to_string nv) (OpamPackage.to_string (real_version universe nv)); list) universe.u_available [] in try Cudf.load_universe universe with Cudf.Constraint_violation s -> OpamGlobals.error_and_exit "Malformed CUDF universe (%s)" s in (* We can trim the universe here to get faster results, but we choose to keep it bigger to get more precise conflict messages. *) (* let universe = Algo.Depsolver.trim universe in *) (fun opam -> let opam = real_version opam_universe opam in try OpamPackage.Map.find opam opam2cudf with Not_found -> OpamGlobals.error_and_exit "opam2cudf: Cannot find %s" (OpamPackage.to_string opam)), (fun cudf -> try Hashtbl.find cudf2opam (cudf.Cudf.package,cudf.Cudf.version) with Not_found -> (* This can happen if a dependency is not available *) try let lookup n = Cudf.lookup_package_property cudf n in let name = OpamPackage.Name.of_string (lookup "source") in let version = OpamPackage.Version.of_string (lookup "sourcenumber") in OpamPackage.unknown name (Some version) with Not_found -> OpamSystem.internal_error "cud2opam(%s,%d)" cudf.Cudf.package cudf.Cudf.version), universe let string_of_request r = let to_string = OpamFormula.string_of_conjunction OpamFormula.string_of_atom in Printf.sprintf "install:%s remove:%s upgrade:%s" (to_string r.wish_install) (to_string r.wish_remove) (to_string r.wish_upgrade) let map_action f = function | To_change (Some x, y) -> To_change (Some (f x), f y) | To_change (None, y) -> To_change (None, f y) | To_delete y -> To_delete (f y) | To_recompile y -> To_recompile (f y) let map_cause f = function | Upstream_changes -> Upstream_changes | Use l -> Use (List.rev_map f l) | Required_by l -> Required_by (List.rev_map f l) | Unknown -> Unknown let graph cudf2opam cudf_graph = let size = OpamCudf.ActionGraph.nb_vertex cudf_graph in let opam_graph = PackageActionGraph.create ~size () in OpamCudf.ActionGraph.iter_vertex (fun package -> PackageActionGraph.add_vertex opam_graph (map_action cudf2opam package) ) cudf_graph; OpamCudf.ActionGraph.iter_edges (fun p1 p2 -> PackageActionGraph.add_edge opam_graph (map_action cudf2opam p1) (map_action cudf2opam p2) ) cudf_graph; opam_graph let solution cudf2opam cudf_solution = let to_remove = List.rev (List.rev_map cudf2opam cudf_solution.OpamCudf.ActionGraph.to_remove) in let to_process = graph cudf2opam cudf_solution.OpamCudf.ActionGraph.to_process in let root_causes = List.rev_map (fun (p, c) -> cudf2opam p, map_cause cudf2opam c) cudf_solution.OpamCudf.ActionGraph.root_causes in { PackageActionGraph.to_remove ; to_process; root_causes } let map_request f r = let f = List.rev_map f in { wish_install = f r.wish_install; wish_remove = f r.wish_remove ; wish_upgrade = f r.wish_upgrade } (* Remove duplicate packages *) let cleanup_request req = let update_packages = List.rev_map (fun (n,_) -> n) req.wish_upgrade in let wish_install = List.filter (fun (n,_) -> not (List.mem n update_packages)) req.wish_install in { req with wish_install } let resolve ?(verbose=true) universe request = log "resolve request=%s" (string_of_request request); let opam2cudf, cudf2opam, simple_universe = load_cudf_universe universe in let request = cleanup_request request in let cudf_request = map_request (atom2cudf opam2cudf) request in let resolve u req = if OpamCudf.external_solver_available () then try OpamCudf.resolve u req with Failure "opamSolver" -> OpamGlobals.msg "Falling back to the internal heuristic.\n"; OpamHeuristic.resolve ~verbose u req else OpamHeuristic.resolve ~verbose u req in match resolve simple_universe cudf_request with | Conflicts c -> Conflicts (fun () -> OpamCudf.string_of_reasons cudf2opam universe (c ())) | Success actions -> let _, _, complete_universe = load_cudf_universe ~depopts:true universe in let cudf_solution = OpamCudf.solution_of_actions ~simple_universe ~complete_universe actions in Success (solution cudf2opam cudf_solution) let installable universe = log "trim"; let _, cudf2opam, simple_universe = load_cudf_universe universe in let trimed_universe = Algo.Depsolver.trim simple_universe in Cudf.fold_packages (fun universe pkg -> OpamPackage.Set.add (cudf2opam pkg) universe) OpamPackage.Set.empty trimed_universe let filter_dependencies f_direction ~depopts ~installed universe packages = let opam2cudf, cudf2opam, cudf_universe = load_cudf_universe ~depopts universe in let cudf_universe = if installed then Cudf.load_universe (List.filter (fun pkg -> pkg.Cudf.installed) (Cudf.get_packages cudf_universe)) else cudf_universe in let cudf_packages = List.rev_map opam2cudf (OpamPackage.Set.elements packages) in let topo_packages = f_direction cudf_universe cudf_packages in let result = List.rev_map cudf2opam topo_packages in log "filter_dependencies packages=%s result=%s" (OpamPackage.Set.to_string packages) (OpamMisc.string_of_list OpamPackage.to_string result); result let dependencies = filter_dependencies OpamCudf.dependencies let reverse_dependencies = filter_dependencies OpamCudf.reverse_dependencies let delete_or_update t = t.PackageActionGraph.to_remove <> [] || PackageActionGraph.fold_vertex (fun v acc -> acc || match v with To_change (Some _, _) -> true | _ -> false) t.PackageActionGraph.to_process false let new_packages sol = PackageActionGraph.fold_vertex (fun action packages -> OpamPackage.Set.add (action_contents action) packages ) sol.PackageActionGraph.to_process OpamPackage.Set.empty let stats sol = let s_install, s_reinstall, s_upgrade, s_downgrade = PackageActionGraph.fold_vertex (fun action (i,r,u,d) -> match action with | To_change (None, _) -> i+1, r, u, d | To_change (Some x, y) when x<>y -> if OpamPackage.Version.compare (OpamPackage.version x) (OpamPackage.version y) < 0 then i, r, u+1, d else i, r, u, d+1 | To_change (Some _, _) | To_recompile _ -> i, r+1, u, d | To_delete _ -> assert false) sol.PackageActionGraph.to_process (0, 0, 0, 0) in let s_remove = List.length sol.PackageActionGraph.to_remove in { s_install; s_reinstall; s_upgrade; s_downgrade; s_remove } let string_of_stats stats = Printf.sprintf "%d to install | %d to reinstall | %d to upgrade | %d to downgrade | %d to remove" stats.s_install stats.s_reinstall stats.s_upgrade stats.s_downgrade stats.s_remove let solution_is_empty t = t.PackageActionGraph.to_remove = [] && PackageActionGraph.is_empty t.PackageActionGraph.to_process let print_solution ~messages ~rewrite t = if not (solution_is_empty t) then let causes pkg = try List.assoc pkg t.PackageActionGraph.root_causes with Not_found -> Unknown in List.iter (fun p -> OpamGlobals.msg "%s\n" (PackageAction.string_of_action ~causes (To_delete (rewrite p))) ) t.PackageActionGraph.to_remove; PackageActionGraph.Topological.iter (function action -> let action = map_action rewrite action in OpamGlobals.msg "%s\n" (PackageAction.string_of_action ~causes action); match action with | To_change(_,p) | To_recompile p -> List.iter (OpamGlobals.msg " %s.\n") (messages p) | To_delete _ -> () ) t.PackageActionGraph.to_process let sequential_solution l = let g = PackageActionGraph.create () in List.iter (PackageActionGraph.add_vertex g) l; let rec aux = function | [] | [_] -> () | x::(y::_ as t) -> PackageActionGraph.add_edge g x y; aux t in aux l; { PackageActionGraph.to_remove = []; to_process = g; root_causes = [] } opam-1.1.1/src/solver/opamHeuristic.ml0000644000175000017500000004721212272210733016166 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) open OpamTypes let log fmt = OpamGlobals.log "HEURISTIC" fmt type 'a state = 'a list type 'a state_space = 'a array list (* Forget about the changes which are not related to the packages we are interested in. We don't have yet computed the transitive closure of dependencies: we are processing 'raw' actions which come directly from the solver. It shoud be safe to discard install/upgrade action outside of the interesting names; delete actions are using a different code-path, they should not appear here. *) let minimize_actions interesting_names actions = let interesting_names = OpamMisc.StringSet.of_list interesting_names in List.filter (function | To_change (_, p) | To_recompile p -> OpamMisc.StringSet.mem p.Cudf.package interesting_names | To_delete _ -> true ) actions (* A list of [n] zero. *) let zero n = let rec aux acc n = if n > 0 then aux (0 :: acc) (n-1) else acc in aux [] n (* Given a list of bounds, create the least tuple such that the sum of components is equal to n. For instance: init [1;2;1] 3 is [0;2;1] *) let init ~bounds n = let rec aux = function | 0, [] -> Some [] | 0, l -> Some (zero (List.length l)) | _, [] -> None | n, b::t -> if n <= b then Some (n :: zero (List.length t)) else match aux (n-b, t) with | None -> None | Some l -> Some (b::l) in match aux (n, List.rev bounds) with | None -> None | Some l -> Some (List.rev l) (* Given a list of bounds and a tuple, return the next tuple while keeping the sum of components of the tuple constant *) let rec cst_succ ~bounds k l = match l, bounds with | [] , [] -> None | [n], [b] -> if n+1 = k && n < b then Some [k] else None | n::nt, b::bt -> if n >= k then None else ( match cst_succ ~bounds:bt (k-n) nt with | Some s -> Some (n::s) | None -> if n < b then match init ~bounds:bt (k-n-1) with | None -> None | Some l -> Some (n+1 :: l) else None) | _ -> failwith "Bounds and tuple do not have the same size" (* Given a list of bounds and a tuple, return the next tuple *) let succ ~bounds l = let k = List.fold_left (+) 0 l in match cst_succ ~bounds k l with | Some t -> Some t | None -> let k = List.fold_left (+) 0 l in init ~bounds (k+1) let fallback_msg = "You might need to add explicit version constraints to your \ request to get a better answer.\n" (* Brute-force exploration of a given space-state: [is_consistent] is applied on each possible state of the system, where a state is where each pacakge has a fix version. We ensure that we apply [is_consistent] in increasing order regarding the difference between the maximum version and the current version for each package. That is, we apply [is_consistent] first on the state where all packages have the maximum version, then on all the states where all packages have their maximum version but one which has its second maximal version, etc... *) let brute_force ?(verbose=true) is_consistent state_space = log "brute-force"; let bounds = List.map (fun v -> Array.length v - 1) state_space in List.iter (fun v -> assert (v >= 0)) bounds; let mk_state t = List.map2 (fun vs i -> vs.(i)) state_space t in let t0 = Unix.time () in let count = ref 0 in let interval = 500 in let flush_output () = if verbose && !count >= interval then OpamGlobals.msg " an optimal solution has been found after exploring %d states.\n" !count in (* XXX: need to ensure this is properly transformed into a while-loop. *) let rec aux = function | None -> log "no better solution found"; flush_output (); None | Some t -> let state = mk_state t in incr count; let t1 = Unix.time () in if verbose && !count mod interval = interval - 1 then OpamGlobals.msg "."; if t1 -. t0 > OpamGlobals.solver_timeout then ( OpamGlobals.msg "The brute-force exploration algorithm timed-out [%d states, %.2gs].\n%s\n" !count OpamGlobals.solver_timeout fallback_msg; None ) else if is_consistent state then Some state else aux (succ ~bounds t) in aux (init ~bounds 0) (* Call the solver to check whether a set of packages is installable. *) let consistent_packages universe packages = let open Algo.Diagnostic in match Algo.Depsolver.edos_coinstall universe packages with | { result = Success _ } -> true | { result = Failure _ } -> false (* Explore a given [state_space] to find the optimal solution. Ideally the state space should be as small as possible, eg. we rely on previous heuristics to reduce its size. *) let explore ?(verbose=true) universe state_space = log "explore"; let packages_of_state state = let filter p = List.exists (fun s -> s.Cudf.package = p.Cudf.package && s.Cudf.version = p.Cudf.version ) state in Cudf.get_packages ~filter universe in let is_consistent state = let packages = packages_of_state state in consistent_packages universe packages in brute_force ~verbose is_consistent state_space (* Build a solution from a given space-state. If a package appears in the state, the solution has the package installed with the given version. If a package does not appear in the state, but is installed in the given universe, its version stays the same. Otherwise, if a package appears neither in the state nor is installed, it will not appear in the resulting solution. *) exception Not_reachable of (unit -> Algo.Diagnostic.reason list) let satisfy pkg constrs = List.exists (fun (n, v) -> n = pkg.Cudf.package && Cudf.version_matches pkg.Cudf.version v ) constrs let actions_of_state universe request state = log "actions_of_state %s" (OpamCudf.string_of_packages state); let installed = let filter p = p.Cudf.installed && List.for_all (fun s -> s.Cudf.package <> p.Cudf.package) state && not (satisfy p request.wish_remove) in let packages = Cudf.get_packages ~filter universe in List.rev_map (fun p -> p.Cudf.package, Some (`Eq, p.Cudf.version)) packages in let small_universe = let filter p = p.Cudf.installed || List.exists (fun s -> s.Cudf.package = p.Cudf.package) state in let packages = Cudf.get_packages ~filter universe in Cudf.load_universe packages in let state = List.map (fun p -> p.Cudf.package, Some (`Eq, p.Cudf.version)) state in let request = { request with wish_install = []; wish_upgrade = state @ installed } in match OpamCudf.get_final_universe small_universe request with | Conflicts c -> log "not reachable! universe=%s request=%s" (OpamCudf.string_of_universe small_universe) (OpamCudf.string_of_request request); raise (Not_reachable c) | Success u -> try let diff = OpamCudf.Diff.diff universe u in let actions = OpamCudf.actions_of_diff diff in let actions = minimize_actions (List.map fst state) actions in actions with Cudf.Constraint_violation s -> OpamGlobals.error_and_exit "constraint violations: %s" s (* Find dependencies and installed & reverse dependencies. *) let find_interesting_names universe request = let filter pkg = satisfy pkg request.wish_upgrade && not (satisfy pkg request.wish_remove) in let packages = Cudf.get_packages ~filter universe in let depends = OpamCudf.dependencies universe packages in let revdepends = let revdepends = OpamCudf.reverse_dependencies universe packages in let filter pkg = pkg.Cudf.installed && filter pkg in List.filter filter revdepends in let set = ref OpamMisc.StringSet.empty in let add p = set := OpamMisc.StringSet.add p.Cudf.package !set in List.iter add depends; List.iter add revdepends; OpamMisc.StringSet.elements !set (* Find: - all package dependencies; and - package reverse dependencies which are installed. *) let dependencies universe constrs = let filter pkg = List.exists (fun (n,v) -> n = pkg.Cudf.package && Cudf.version_matches pkg.Cudf.version v ) constrs in let packages = Cudf.get_packages ~filter universe in let packages = OpamCudf.dependencies universe packages in let universe = Cudf.load_universe packages in Algo.Depsolver.trim universe (* [state_space] returns the packages which will be tested by the brute-force state explorer. As we try to minimize the state to explore for each package, this means: - if the package has a version constraint in the request, that's the only we consider (eg. return only one element for this package name: the version in the constraint) - if the package has no version constraints in the request, or if the package does not appear in the initial request, then return only the versions greater or equals to the one appearing in the given universe. - if the package appears in the 'wish_remove' field we do not try to test it. *) let state_space ?(filters = fun _ -> None) universe wish_remove interesting_names = let universe_packages = Cudf.get_packages universe in (* Return the version associated to a given package in the universe. *) let installed_version_of_name = let tbl = Hashtbl.create 1024 in List.iter (fun p -> if p.Cudf.installed then Hashtbl.add tbl p.Cudf.package p.Cudf.version) universe_packages; function name -> try Some (Hashtbl.find tbl name) with Not_found -> None in let state_space = Hashtbl.create 1024 in let add_state name = if not (Hashtbl.mem state_space name) then let filter = filters name in let packages = Cudf.lookup_packages universe ~filter name in let packages = match installed_version_of_name name with | None -> packages | Some v -> List.filter (fun p -> p.Cudf.version >= v) packages in let packages = List.sort (fun p1 p2 -> compare p2.Cudf.version p1.Cudf.version) packages in let packages = List.filter (fun p -> not (satisfy p wish_remove)) packages in if List.length packages <> 0 then Hashtbl.add state_space name (Array.of_list packages) in List.iter add_state interesting_names; Hashtbl.fold (fun _ states acc -> states :: acc) state_space [] (* Find a possible good state which satisfies a request. The idea is call iteratively this function while refining the constraints of the request until reaching a fix-point. *) let state_of_request ?(verbose=true) current_universe request = log "state_of_request"; match OpamCudf.get_final_universe current_universe request with | Conflicts _ -> log "state-of-request: %s CONFLICT!" (OpamCudf.string_of_request request); None | Success result_universe -> (* This first [result_universe] is a consistent solution which contains only installed packages fulfilling the initial constraints. It is thus not a complete universe and it is not guaranteed to be optimal. So we extend the result with all the existing packages. *) let result_universe = let installed = Cudf.get_packages result_universe in let current_universe = OpamCudf.uninstall_all current_universe in List.fold_left OpamCudf.install current_universe installed in let all_wishes = request.wish_install @ request.wish_upgrade in (* We remove from the universe all the package versions which are not specified on the command-line. For instance: $ opam install core.109.13.00 will cause all versions of core != 109.13.00 to disapear from the universe. This is causing [Universe.trim] to remove *a lot* of uninstallable packages and will improve the brute-force state exploration results. Note: We don't want to trim the universe too early because we want to keep good error messages in case the solver does not find a solution. *) let trimed_universe = let universe = List.fold_left (fun universe (name, constr) -> OpamCudf.remove_all_uninstalled_versions_but universe name constr ) result_universe all_wishes in let universe = Algo.Depsolver.trim universe in dependencies universe all_wishes in let filters name = try List.assoc name all_wishes with Not_found -> log "state-of-request: %s NOT FOUND!" name; None in let state_space = let names = List.map (fun (n,_) -> n) request.wish_upgrade in state_space ~filters trimed_universe request.wish_remove names in explore ~verbose current_universe state_space let same_state s1 s2 = let sort l = let name p = p.Cudf.package, p.Cudf.version in let cmp p1 p2 = compare (name p1) (name p2) in List.sort cmp l in match s1 with | None -> false | Some s1 -> List.length s1 = List.length s2 && sort s1 = sort s2 (* Various heuristic to transform a solution checker into an optimized solver. *) let optimize ?(verbose=true) universe request = let refine state request = log "refine request:%s state:%s" (OpamCudf.string_of_request request) (OpamCudf.string_of_packages state); let wish_upgrade = List.rev_map (fun p -> (p.Cudf.package, Some (`Eq, p.Cudf.version))) state in let wish_install = let names = OpamMisc.StringSet.( union (of_list (List.rev_map fst request.wish_install)) (of_list (List.rev_map fst request.wish_upgrade)) ) in let set = OpamMisc.StringSet.filter (fun n -> not (List.mem_assoc n wish_upgrade)) names in List.map (fun n -> (n, None)) (OpamMisc.StringSet.elements set) in { request with wish_install; wish_upgrade } in let add_to_request state request name = let request = refine state request in { request with wish_upgrade = (name, None) :: request.wish_upgrade } in let interesting_names = find_interesting_names universe request in (* Compute the 'implicit' packages, ie. the ones which do not appear in the request but which are in the transitive closure of dependencies, and split them in two categories: already installed (which will be kept as much as possible with the same version) and not installed (which will be installed to the most recent valid version) *) let implicit_installed, implicit_not_installed = let implicit = let request_names = OpamMisc.StringSet.of_list (List.map fst request.wish_upgrade) in let all_names = OpamMisc.StringSet.of_list interesting_names in OpamMisc.StringSet.diff all_names request_names in let installed = let filter p = p.Cudf.installed && OpamMisc.StringSet.mem p.Cudf.package implicit in Cudf.get_packages ~filter universe in let not_installed = let filter n = List.for_all (fun p -> p.Cudf.package <> n) installed in let set = OpamMisc.StringSet.filter filter implicit in let list = OpamMisc.StringSet.elements set in (* Favor packages with higher version number to discard deprecated packages. *) let max_version name = let filter p = p.Cudf.package = name in let packages = Cudf.get_packages ~filter universe in List.fold_left (fun v p -> max v p.Cudf.version) min_int packages in let cmp n1 n2 = compare (max_version n1) (max_version n2) in List.sort cmp list in installed, not_installed in log "implicit-installed: %s" (OpamCudf.string_of_packages implicit_installed); log "implicit-not-installed: %s" (OpamMisc.pretty_list implicit_not_installed); (* Upgrade the explicit packages first *) match state_of_request ~verbose universe request with | None -> OpamCudf.resolve universe request | Some state -> log "STATE(0) %s" (OpamCudf.string_of_packages state); let request = refine state request in (* strategy where we try keep the installed version before trying an other one. *) let installed_first state p = log "installed-first %s" p.Cudf.package; if consistent_packages universe (p :: state) then ( log "keep %s with the same version" p.Cudf.package; (p :: state) ) else ( let request = add_to_request state request p.Cudf.package in match state_of_request ~verbose universe request with | None -> log "discard %s" p.Cudf.package; state | Some state -> let p = List.find (fun i -> i.Cudf.package = p.Cudf.package) state in log "pick an other version of %s (%d)" p.Cudf.package p.Cudf.version; log "request: %s" (OpamCudf.string_of_request request); log "state: %s" (OpamCudf.string_of_packages state); state ) in (* Try to keep the installed packages in the dependency cone *) let state = List.fold_left installed_first state implicit_installed in log "STATE(1) %s" (OpamCudf.string_of_packages state); (* Minimize the number of new packages to install *) (* XXX: if we want to add an interactive mode, we need to do something here *) (* XXX: if needed we can sort the packages in a more clever order (for instance the size of the dependency cone of packages which are not yet installed). *) let universe, state = List.fold_left (fun (universe, state) name -> let remove_universe = OpamCudf.remove universe name None in if consistent_packages remove_universe state then ( log "%s is not necessary (%s)" name (OpamCudf.string_of_packages state); (remove_universe, state) ) else ( log "adding %s to the request" name; let request = add_to_request state request name in match state_of_request ~verbose universe request with | None -> (universe, state) | Some state -> (universe, state) ) ) (universe, state) implicit_not_installed in (* Finally we check that the already installed packages can still be installed in the new universe. *) let state = let filter p = p.Cudf.installed && List.for_all (fun s -> s.Cudf.package <> p.Cudf.package) state && not (satisfy p request.wish_remove) in let packages = Cudf.get_packages ~filter universe in List.fold_left installed_first state packages in log "STATE(2) %s" (OpamCudf.string_of_packages state); Success (actions_of_state universe request state) let resolve ?(verbose=true) universe request = try if request.wish_upgrade <> [] then optimize ~verbose universe request else OpamCudf.resolve universe request with Not_reachable c -> Conflicts c opam-1.1.1/src/solver/opamHeuristic.mli0000644000175000017500000001514112272210733016333 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) (** Solver heuristics. *) (** This module tries to turn an efficient solution checker (such as the one provided by the dose3 library, writen by J. Vouillon) into a relatively good solution finder. The method we are using is the following: - We ultimately rely on a brute-force exploration loop, where we iterate over the state-space implicitely, using a monotonous successor function which encodes the optimization criteria we are interested in; - As brute-force exploration is costly, the goal is to provide the exploration function a state-space as small as possible. To do so, we use different kind of constraints that we deduce from the request; - We remove from the state-space every packages and versions that are not needed: we are only considering (i) the installed root packages (with no specific version constraint); (ii) the new packages that the user might have asking to install or upgrade (with some eventual version constraints); and (iii) the transitive closure of (i) and (ii) (with the corresponding version constraints); Finally, we run all this in a loop, until we reach a fix point. We use a timeout to interrupt too long explorations. *) open OpamTypes (** {2 High-level API} *) (** Optimized resolution *) val resolve: ?verbose:bool -> Cudf.universe -> Cudf_types.vpkg request -> (Cudf.package action list, Algo.Diagnostic.reason list) result (** {2 Internal API} *) (** These functions can be used independently of OPAM, so we document them here. It is not expected than any other file in OPAM use them, though. *) (** A state. In our case, it is a list package we would like to see installed. *) type 'a state = 'a list (** A state space. In our case, it is a collection of available packages: each cell contains all the versions available for one package, ordered by version. *) type 'a state_space = 'a array list (** {4 Integer space} *) (** The hearth of the brute-force algorithm lies here. Wwe want to iterate on the state-space (which can be hudge) and stop the first time we hit a consistant state. This means two things: (i) we don't want to build the full universe before iterating on it; (ii) we need to enumerate the states in a meaningful order, eg. an order which should reflect the optimization criteria we are intersted in. *) (** To overcome this difficulties, we use a monotonous successor function to compute the next state to test from a given valid non-consistent state, see [succ] for more details. *) (** [zero n] returns the tuple with [n] zeros, which is the first state to explore. *) val zero: int -> int state (** Given a list of bounds and a tuple, return the next tuple which satisfies the bounds (each component will be stricly lesser than the bounds). The enumeration respect the following invariant: - it is complete, eg. all the state are enumerated until [None] is returned. - it it monotonous: the sum of components always increase, eg. [|succ x| >= |x|], where [|None|] is [max_int], [|Some x| = |x|] and [|(x_1,...,x_n) = x_1 + ... + x_n|]. That enumeration encodes the heuristic we are trying to implement, which is: we first try to install the 'ideal' state, where all packages are installed with their most recent versions; if this does not work, we try to minimize the distance between the ideal state and the solution we are proposing. *) val succ: bounds:int list -> int state -> int state option (** {4 Polymorphic space} *) (** [explore is_constent state_space] explore a state space by implicitely enumerating all the state in a sensitive order. *) val brute_force: ?verbose:bool -> ('a state -> bool) -> 'a state_space -> 'a state option (** {4 Package space} *) (** Build a state space from a list of package names. The [filter] option helps to reduce the size of the state-space, which is useful to deal with both user-defined constraints (added on the command line for instance) and refined requests (see below). *) val state_space: ?filters:(Cudf_types.pkgname -> Cudf_types.constr) -> Cudf.universe -> Cudf_types.vpkglist -> Cudf_types.pkgname list -> Cudf.package state_space (** Explore the given package state-space using the [brute_force] strategy. We assume that all the packages belong to the given universe. *) val explore: ?verbose:bool -> Cudf.universe -> Cudf.package state_space -> Cudf.package state option (** Find a possible good state which satisfies a request. The idea is call iteratively this function while refining the constraints in the request until reaching a fix-point. This function tries to minimize the state to explore, based on the request constraints: the more constrained request you have, the smaller the state-space to explore is. Once the state-space is computed using [state_space], it calls [explore] (which will use [brute_force]) to get an approximate solution to the request. *) val state_of_request: ?verbose:bool -> Cudf.universe -> Cudf_types.vpkg request -> Cudf.package state option (** Convert a state into a series of action (withour the full closure of reinstallations). Raise [Not_reachable] is the state is not reachable. This function is called once we get a consistent state to build a solution than we can propose to the user. *) val actions_of_state: Cudf.universe -> Cudf_types.vpkg request -> Cudf.package state -> Cudf.package action list opam-1.1.1/src/solver/opamSolver.mli0000644000175000017500000000564712272210733015660 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) (** SAT-solver for package dependencies and conflicts *) open OpamTypes val empty_universe: universe (** {2 Solver} *) (** Convert a request to a string *) val string_of_request: atom request -> string (** Compute statistics about a solution *) val stats: solution -> stats (** Return the new packages in the solution *) val new_packages: solution -> package_set (** Pretty-printing of statistics *) val string_of_stats: stats -> string (** Is the solution empty ? *) val solution_is_empty: solution -> bool (** Does the solution implies deleting or updating a package *) val delete_or_update : solution -> bool (** Display a solution *) val print_solution: messages:(package -> string list) -> rewrite:(package -> package) -> solution -> unit (** Given a description of packages, return a solution preserving the consistency of the initial description. An empty [list] : No solution found. The last argument is the set of installed packages. Every element in the solution [list] satisfies the problem given. For the ordering, the first element in the list is obtained by upgrading from its next element. *) val resolve : ?verbose:bool -> universe -> atom request -> (solution, string) result (** Keep only the packages that are installable. *) val installable: universe -> package_set (** Return the topological sort of the transitive dependency closures of a collection of packages.*) val dependencies : depopts:bool -> installed:bool -> universe -> package_set -> package list (** Same as [dependencies] but for reverse dependencies *) val reverse_dependencies : depopts:bool -> installed:bool -> universe -> package_set -> package list (** Create a sequential solution from a list of actions *) val sequential_solution: package action list -> solution opam-1.1.1/src/solver/opamCudf.ml0000644000175000017500000005553312272210733015115 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) open OpamTypes let log fmt = OpamGlobals.log "CUDF" fmt let string_of_action a = let aux pkg = Printf.sprintf "%s.%d" pkg.Cudf.package pkg.Cudf.version in match a with | To_change (None, p) -> Printf.sprintf " - install %s" (aux p) | To_change (Some o, p) -> let f action = Printf.sprintf " - %s %s to %d" action (aux o) p.Cudf.version in if compare o.Cudf.version p.Cudf.version < 0 then f "upgrade" else f "downgrade" | To_recompile p -> Printf.sprintf " - recompile %s" (aux p) | To_delete p -> Printf.sprintf " - delete %s" (aux p) let string_of_actions l = OpamMisc.string_of_list string_of_action l let string_of_package p = let installed = if p.Cudf.installed then "installed" else "not-installed" in Printf.sprintf "%s.%d(%s)" p.Cudf.package p.Cudf.version installed let string_of_packages l = OpamMisc.string_of_list string_of_package l let to_json p = `O [ ("name", `String p.Cudf.package); ("version", `String (string_of_int p.Cudf.version)); ("installed", `String (string_of_bool p.Cudf.installed)); ] (* Graph of cudf packages *) module Pkg = struct type t = Cudf.package include Common.CudfAdd let to_string = string_of_package let string_of_action ?causes:_ = string_of_action let to_json = to_json end module ActionGraph = MakeActionGraph(Pkg) module Map = OpamMisc.Map.Make(Pkg) module Set = OpamMisc.Set.Make(Pkg) module Graph = struct module PG = struct include Algo.Defaultgraphs.PackageGraph.G let succ g v = try succ g v with _ -> [] end module PO = Algo.Defaultgraphs.GraphOper (PG) module Topo = Graph.Topological.Make (PG) let of_universe u = let g = Algo.Defaultgraphs.PackageGraph.dependency_graph u in PO.transitive_reduction g; g let output g filename = let fd = open_out (filename ^ ".dot") in Algo.Defaultgraphs.PackageGraph.DotPrinter.output_graph fd g; close_out fd let transitive_closure g = PO.O.add_transitive_closure g let close_and_linearize g pkgs = let _, l = Topo.fold (fun pkg (closure, topo) -> if Set.mem pkg closure then Set.union closure (Set.of_list (PG.succ g pkg)), pkg :: topo else closure, topo) g (pkgs, []) in l let mirror = PO.O.mirror include PG end let filter_dependencies f_direction universe packages = let graph = f_direction (Graph.of_universe universe) in let packages = Set.of_list packages in Graph.close_and_linearize graph packages let dependencies = filter_dependencies (fun x -> x) let reverse_dependencies = filter_dependencies Graph.mirror let string_of_atom (p, c) = let const = function | None -> "" | Some (r,v) -> Printf.sprintf " (%s %d)" (OpamFormula.string_of_relop r) v in Printf.sprintf "%s%s" p (const c) let string_of_vpkgs constr = let constr = List.sort (fun (a,_) (b,_) -> String.compare a b) constr in OpamFormula.string_of_conjunction string_of_atom constr let string_of_request r = Printf.sprintf "install:%s remove:%s upgrade:%s" (string_of_vpkgs r.wish_install) (string_of_vpkgs r.wish_remove) (string_of_vpkgs r.wish_upgrade) let string_of_universe u = string_of_packages (List.sort compare (Cudf.get_packages u)) let vpkg2opamstr cudf2opam (name, constr) = match constr with | None -> Common.CudfAdd.decode name | Some (r,v) -> let c = Cudf.({ package = name; version = v; depends = []; conflicts = []; provides = []; installed = false; was_installed = false; keep = `Keep_none; pkg_extra = []; }) in try let nv = cudf2opam c in let str r = let name = OpamPackage.name nv in let version = OpamPackage.version nv in Printf.sprintf "%s%s%s" (OpamPackage.Name.to_string name) r (OpamPackage.Version.to_string version) in match r with | `Eq -> OpamPackage.to_string nv | `Neq -> str "!=" | `Geq -> str ">=" | `Gt -> str ">" | `Leq -> str "<=" | `Lt -> str "<" with _ -> Common.CudfAdd.decode name let string_of_reason cudf2opam opam_universe r = let open Algo.Diagnostic in match r with | Conflict (i,j,_) -> let nvi = cudf2opam i in let nvj = cudf2opam j in if OpamPackage.name nvi = OpamPackage.name nvj then None else let nva = min nvi nvj in let nvb = max nvi nvj in let str = Printf.sprintf "%s is in conflict with %s." (OpamPackage.to_string nva) (OpamPackage.to_string nvb) in Some str | Missing (p,m) -> let of_package = if p.Cudf.package = "dose-dummy-request" then "" else let nv = cudf2opam p in Printf.sprintf " of package %s" (OpamPackage.to_string nv) in let pinned_deps, deps = List.partition (fun (p,_) -> let name = OpamPackage.Name.of_string (Common.CudfAdd.decode p) in OpamPackage.Name.Map.mem name opam_universe.u_pinned) m in let pinned_deps = List.rev_map (vpkg2opamstr cudf2opam) pinned_deps in let deps = List.rev_map (vpkg2opamstr cudf2opam) deps in let str = "" in let str = if pinned_deps <> [] then let dependencies, are, s, have = if List.length pinned_deps > 1 then "dependencies", "are", "s", "have" else "dependency", "is", "", "has" in Printf.sprintf "%s\nThe %s %s%s %s not available because the package%s %s been pinned." str dependencies (String.concat ", " pinned_deps) of_package are s have else str in let str = if deps <> [] then let dependencies, are = if List.length deps > 1 then "dependencies", "are" else "dependency", "is" in Printf.sprintf "%s\nThe %s %s%s %s not available for your compiler or your OS." str dependencies (String.concat ", " deps) of_package are else str in Some str | Dependency _ -> None let make_chains depends = let open Algo.Diagnostic in let g = Graph.create () in let init = function | Dependency (i,_,jl) -> Graph.add_vertex g i; List.iter (Graph.add_vertex g) jl; List.iter (Graph.add_edge g i) jl | _ -> () in List.iter init depends; Graph.iter_vertex (fun v -> if v.Cudf.package = "dose-dummy-request" then Graph.remove_vertex g v ) g; let roots = Graph.fold_vertex (fun v accu -> if Graph.in_degree g v = 0 then v :: accu else accu ) g [] in let rec unroll root = match Graph.succ g root with | [] -> [[root]] | children -> let chains = List.flatten (List.map unroll children) in List.map (fun cs -> root :: cs) chains in let chains = List.flatten (List.map unroll roots) in List.filter (function [_] -> false | _ -> true) chains let string_of_reasons cudf2opam opam_universe reasons = let open Algo.Diagnostic in let depends, reasons = List.partition (function Dependency _ -> true | _ -> false) reasons in let chains = make_chains depends in let rec string_of_chain = function | [] -> "" | [p] -> Printf.sprintf "%s." (OpamPackage.to_string (cudf2opam p)) | p::t -> Printf.sprintf "%s needed by %s" (OpamPackage.to_string (cudf2opam p)) (string_of_chain t) in let string_of_chain c = string_of_chain (List.rev c) in let b = Buffer.create 1024 in let reasons = OpamMisc.filter_map (string_of_reason cudf2opam opam_universe) reasons in let reasons = OpamMisc.StringSet.(elements (of_list reasons)) in begin match reasons with | [] -> () | [r] -> Buffer.add_string b r | _ -> let reasons = String.concat "\n (and) " reasons in Printf.bprintf b "Your request cannot be satisfied. The reasons are:\n\ \ %s" reasons; match chains with | [] -> () | _ -> let chains = List.map string_of_chain chains in let chains = String.concat "\n (or) " chains in Printf.bprintf b "\nThis is due to the following unmet dependencies(s):\n\ \ %s" chains end; Buffer.contents b let s_reinstall = "reinstall" let s_installed_root = "installed-root" let check flag p = try Cudf.lookup_package_property p flag = "true" with Not_found -> false let need_reinstall = check s_reinstall let is_installed_root = check s_installed_root let aspcud_path = lazy ( try match OpamSystem.read_command_output ~verbose:false [ "which"; "aspcud" ] with | [] -> None | h::_ -> Some (OpamMisc.strip h) with _ -> None ) let aspcud_command path = Printf.sprintf "%s $in $out $pref" path let default_preamble = let l = [ ("recommends",(`Vpkgformula (Some []))); ("number",(`String None)); ("source",(`String (Some ""))) ; ("sourcenumber",(`String (Some ""))); ("sourceversion",(`Int (Some 1))) ; ("essential",(`Bool (Some false))) ; ("buildessential",(`Bool (Some false))) ; (s_reinstall,`Bool (Some false)); (s_installed_root, `Bool (Some false)); ] in Common.CudfAdd.add_properties Cudf.default_preamble l let remove universe name constr = let filter p = p.Cudf.package <> name || not (Cudf.version_matches p.Cudf.version constr) in let packages = Cudf.get_packages ~filter universe in Cudf.load_universe packages let uninstall_all universe = let packages = Cudf.get_packages universe in let packages = List.rev_map (fun p -> { p with Cudf.installed = false }) packages in Cudf.load_universe packages let install universe package = let p = Cudf.lookup_package universe (package.Cudf.package, package.Cudf.version) in let p = { p with Cudf.installed = true } in let packages = let filter p = p.Cudf.package <> package.Cudf.package || p.Cudf.version <> package.Cudf.version in Cudf.get_packages ~filter universe in Cudf.load_universe (p :: packages) let remove_all_uninstalled_versions_but universe name constr = let filter p = p.Cudf.installed || p.Cudf.package <> name || Cudf.version_matches p.Cudf.version constr in let packages = Cudf.get_packages ~filter universe in Cudf.load_universe packages let to_cudf univ req = ( default_preamble, univ, { Cudf.request_id = "opam"; install = req.wish_install; remove = req.wish_remove; upgrade = req.wish_upgrade; req_extra = [] } ) let external_solver_available () = !OpamGlobals.use_external_solver && Lazy.force aspcud_path <> None let solver_calls = ref 0 let dump_cudf_request (_, univ,_ as cudf) = function | None -> None | Some f -> incr solver_calls; let filename = Printf.sprintf "%s-%d.cudf" f !solver_calls in let oc = open_out filename in begin match Lazy.force aspcud_path with | Some path when !OpamGlobals.use_external_solver -> Printf.fprintf oc "#!%s %s\n" (aspcud_command path) OpamGlobals.aspcud_criteria | _ -> Printf.fprintf oc "#internal OPAM solver\n" end; Cudf_printer.pp_cudf oc cudf; close_out oc; Graph.output (Graph.of_universe univ) f; Some filename let call_external_solver ~explain univ req = let cudf_request = to_cudf univ req in ignore (dump_cudf_request cudf_request !OpamGlobals.cudf_file); match Lazy.force aspcud_path with | Some path when !OpamGlobals.use_external_solver -> if Cudf.universe_size univ > 0 then begin let cmd = aspcud_command path in let criteria = OpamGlobals.aspcud_criteria in try Algo.Depsolver.check_request ~cmd ~criteria ~explain:true cudf_request with e -> OpamGlobals.warning "'%s' failed with %s" cmd (Printexc.to_string e); Algo.Depsolver.check_request ~explain cudf_request end else Algo.Depsolver.Sat(None,Cudf.load_universe []) | _ -> (* No external solver is available, use the default one *) Algo.Depsolver.check_request ~explain cudf_request (* Return the universe in which the system has to go *) let get_final_universe univ req = let fail msg = OpamGlobals.use_external_solver := false; let cudf_file = match !OpamGlobals.cudf_file with | Some f -> f | None -> let (/) = Filename.concat in !OpamGlobals.root_dir / "log" / ("solver-error-"^string_of_int (Unix.getpid())) in let f = dump_cudf_request (to_cudf univ req) (Some cudf_file) in OpamGlobals.warning "External solver failed with %s Request saved to %S" msg (match f with Some x -> x | None -> ""); failwith "opamSolver" in let open Algo.Depsolver in match call_external_solver ~explain:true univ req with | Sat (_,u) -> Success (remove u "dose-dummy-request" None) | Error "(CRASH) Solution file is empty" -> Success (Cudf.load_universe []) | Error str -> fail str | Unsat r -> let open Algo.Diagnostic in match r with | Some {result=Failure f} -> Conflicts f | _ -> fail "inconsistent return value." (* A modified version of CudfDiff to handle reinstallations *) module Diff = struct type package = { installed : Set.t; removed : Set.t; reinstalled: Set.t; } type universe = (string, package) Hashtbl.t (* for each pkgname I've the list of all versions that were installed or removed *) let diff univ sol = let pkgnames = OpamMisc.StringSet.of_list (List.rev_map (fun p -> p.Cudf.package) (Cudf.get_packages univ)) in let h = Hashtbl.create (OpamMisc.StringSet.cardinal pkgnames) in let needed_reinstall = Set.of_list (Cudf.get_packages ~filter:need_reinstall univ) in OpamMisc.StringSet.iter (fun pkgname -> let were_installed = Set.of_list (Cudf.get_installed univ pkgname) in let are_installed = Set.of_list (Cudf.get_installed sol pkgname) in let removed = Set.diff were_installed are_installed in let installed = Set.diff are_installed were_installed in let reinstalled = Set.inter are_installed needed_reinstall in let s = { removed; installed; reinstalled } in Hashtbl.add h pkgname s ) pkgnames ; h end (* Transform a diff from current to final state into a list of actions. At this point, we don't know about the root causes of the actions, they will be computed later. *) let actions_of_diff diff = Hashtbl.fold (fun _ s acc -> let add x = x :: acc in let removed = try Some (Set.choose_one s.Diff.removed) with Not_found -> None in let installed = try Some (Set.choose_one s.Diff.installed) with Not_found -> None in let reinstalled = try Some (Set.choose_one s.Diff.reinstalled) with Not_found -> None in match removed, installed, reinstalled with | None , Some p , _ -> add (To_change (None, p)) | Some p , None , _ -> add (To_delete p) | Some p_old, Some p_new , _ -> add (To_change (Some p_old, p_new)) | None , None , Some p -> add (To_recompile p) | None , None , None -> acc ) diff [] let resolve universe request = log "resolve request=%s" (string_of_request request); match get_final_universe universe request with | Conflicts e -> Conflicts e | Success u -> try let diff = Diff.diff universe u in Success (actions_of_diff diff) with Cudf.Constraint_violation s -> OpamGlobals.error_and_exit "constraint violations: %s" s let create_graph filter universe = let pkgs = Cudf.get_packages ~filter universe in let u = Cudf.load_universe pkgs in Graph.of_universe u (* Compute a full solution from a set of root actions. This means: 1/ computing the right sequence of removal. 2/ computing the transitive closure of reinstallations. 3/ computing the root causes of actions Parameters: - [simple _universe] is the graph with 'depends' only - [complex_universe] is the graph with 'depends' + 'depopts' *) let solution_of_actions ~simple_universe ~complete_universe root_actions = log "graph_of_actions root_actions=%s" (string_of_actions root_actions); (* The packages to remove or upgrade *) let to_remove_or_upgrade = OpamMisc.filter_map (function | To_change (Some pkg, _) | To_delete pkg -> Some pkg | _ -> None ) root_actions in (* Initial actions to process *) let actions = Map.of_list (OpamMisc.filter_map (function | To_recompile pkg | To_change (_, pkg) as act -> Some (pkg, act) | To_delete _ -> None ) root_actions) in let all_packages = (* we consider the complete universe here (eg. including optional dependencies) *) let graph = create_graph (fun p -> p.Cudf.installed || Map.mem p actions) complete_universe in Graph.mirror graph in (* the graph of interesting packages, which might be impacted by the current actions *) let interesting_packages = let graph = Graph.copy all_packages in List.iter (Graph.remove_vertex graph) to_remove_or_upgrade; graph in (* the packages to remove, and the associated root causes *) let to_remove, root_causes = let remove_roots = Set.of_list (OpamMisc.filter_map (function | To_delete pkg -> Some pkg | _ -> None ) root_actions) in (* we consider here only the simple universe (eg. hard dependencies only): we don't want to uninstall a package if some of its optional dependencies disapear, however we must recompile it (see below). *) let graph = create_graph (fun p -> Set.mem p remove_roots) simple_universe in let to_remove = List.rev (Graph.close_and_linearize graph remove_roots) in let root_causes = let graph = Graph.PO.O.add_transitive_closure graph in let cause pkg = let roots = List.filter (fun v -> Graph.in_degree graph v = 0) (Graph.pred graph pkg) in let roots = List.filter is_installed_root roots in let sinks = List.filter (fun v -> Graph.out_degree graph v = 0) (Graph.succ graph pkg) in let sinks = List.filter is_installed_root sinks in match roots, sinks with | [], [] -> Unknown | [], _ -> Use sinks | _ -> Required_by roots in List.rev_map (fun pkg -> pkg, cause pkg) to_remove in to_remove, root_causes in (* the packages to recompile *) let to_recompile = let recompile_roots = Set.of_list (OpamMisc.filter_map (function | To_recompile pkg -> Some pkg | _ -> None ) root_actions) in (* add the packages to recompile due to the REMOVAL of packages (ie. when an optional dependency has been removed). *) List.fold_left (fun to_recompile pkg -> let succ = Graph.succ all_packages pkg in Set.union to_recompile (Set.of_list succ) ) recompile_roots to_remove in (* Compute the transitive closure of packages to recompile *) let _, actions = Graph.Topo.fold (fun pkg (to_recompile, actions) -> let add_succ pkg action = let succ = Graph.succ interesting_packages pkg in let to_recompile = Set.union to_recompile (Set.of_list succ) in let actions = Map.add pkg action (Map.remove pkg actions) in to_recompile, actions in if Map.mem pkg actions then add_succ pkg (Map.find pkg actions) else if Set.mem pkg to_recompile then add_succ pkg (To_recompile pkg) else to_recompile, actions) interesting_packages (to_recompile, actions) in (* Construct the full graph of actions to proceed to reach the new state given by the solver. *) let to_process = ActionGraph.create () in Map.iter (fun _ act -> ActionGraph.add_vertex to_process act) actions; Graph.iter_edges (fun v1 v2 -> try let v1 = Map.find v1 actions in let v2 = Map.find v2 actions in ActionGraph.add_edge to_process v1 v2 with Not_found -> ()) interesting_packages; (* Now we can compute the root causes. Install & Upgrades are either the original cause of the action, or they are here because of some dependency constrains: so we need to look forward in the graph. At the opposite, Reinstall are there because of some install/upgrade, so need to look backward in the graph. *) let root_causes = let to_process_complete = ActionGraph.add_transitive_closure (ActionGraph.copy to_process) in ActionGraph.Topological.fold (fun action root_causes -> match ActionGraph.out_degree to_process action, action with | 0, To_change _ -> root_causes | _, To_change (_, pkg) -> let succ = ActionGraph.succ to_process_complete action in let causes = List.filter (fun a -> ActionGraph.out_degree to_process a = 0) succ in let causes = List.filter (function To_change _ -> true | _ -> false) causes in let causes = List.rev_map action_contents causes in let cause = match causes with | [] -> Unknown | _ -> Required_by causes in (pkg, cause) :: root_causes | _, To_recompile pkg -> let pred = ActionGraph.pred to_process_complete action in let causes = List.filter (fun a -> ActionGraph.in_degree to_process a = 0) pred in let causes = List.rev_map action_contents causes in let causes = List.fold_left (fun causes removed_pkg -> if List.mem pkg (Graph.succ all_packages removed_pkg) then removed_pkg :: causes else causes) causes to_remove in let cause = match causes with | [] -> Upstream_changes | _ -> Use causes in (pkg, cause) :: root_causes | _, To_delete _ -> (* the to_process graph should not contain remove actions. *) assert false ) to_process root_causes in { ActionGraph.to_remove; to_process; root_causes } opam-1.1.1/src/solver/opamCudf.mli0000644000175000017500000001272012272210733015255 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) (** Cudf interface *) open OpamTypes (** Cudf sets *) module Set: OpamMisc.SET with type elt = Cudf.package (** Cudf maps *) module Map: OpamMisc.MAP with type key = Cudf.package (** Cudf graph *) module Graph: sig (** Graph of cudf packages *) type t (** Build a graph from a CUDF universe *) val of_universe: Cudf.universe -> t (** Return the transitive closure of [g] *) val transitive_closure: t -> t (** Return the transitive closure of dependencies of [set], sorted in topological order. *) val close_and_linearize: t -> Set.t -> Cudf.package list end (** Difference between universes *) module Diff: sig (** Differences between the versions of a given package *) type package = { installed : Set.t; removed : Set.t; reinstalled: Set.t; } (** Difference between universe *) type universe = (Cudf_types.pkgname, package) Hashtbl.t (** Computation of differences between universe *) val diff: Cudf.universe -> Cudf.universe -> universe end (** Cudf action graph *) module ActionGraph: ACTION_GRAPH with type package = Cudf.package (** Return the transitive closure of dependencies of [set], sorted in topological order *) val dependencies: Cudf.universe -> Cudf.package list -> Cudf.package list (** Return the transitive closure of dependencies of [set], sorted in topological order *) val reverse_dependencies: Cudf.universe -> Cudf.package list -> Cudf.package list (** Compute the final universe state. *) val get_final_universe: Cudf.universe -> Cudf_types.vpkg request -> (Cudf.universe, Algo.Diagnostic.reason list) result (** Compute the list of actions to match the difference between two universe. Remark: the result order is unspecified, ie. need to use [solution_of_actions] to get a solution which respects the topological order induced by dependencies. *) val actions_of_diff: Diff.universe -> Cudf.package action list (** Compution the actions to process from a solution *) val solution_of_actions: simple_universe:Cudf.universe -> complete_universe:Cudf.universe -> Cudf.package action list -> ActionGraph.solution (** Resolve a CUDF request. The result is either a conflict explaining the error, or a list of action to proceed. Note however than the action list is not yet complete: the transitive closure of reinstallations is not yet completed, as it requires to fold over the dependency graph in considering the optional dependencies -- which is something that dose/cudf obviously does not handle. *) val resolve: Cudf.universe -> Cudf_types.vpkg request -> (Cudf.package action list, Algo.Diagnostic.reason list) result (** [remove universe name constr] Remove all the packages called [name] satisfying the constraints [constr] in the universe [universe]. *) val remove: Cudf.universe -> Cudf_types.pkgname -> Cudf_types.constr -> Cudf.universe (** Uninstall all the package in the universe. *) val uninstall_all: Cudf.universe -> Cudf.universe (** Install a package in the universe. We don't care about any invariant here (eg. the resulting universe can have mutliple versions of the same package installed). *) val install: Cudf.universe -> Cudf.package -> Cudf.universe (** Remove all the versions of a given package, but the one given as argument. *) val remove_all_uninstalled_versions_but: Cudf.universe -> string -> Cudf_types.constr -> Cudf.universe (** The "reinstall" string *) val s_reinstall: string (** The "installed-root" string *) val s_installed_root: string (** {2 Pretty-printing} *) (** Convert a package constraint to something readable. *) val string_of_vpkgs: Cudf_types.vpkg list -> string (** Convert a reason to something readable by the user *) val string_of_reason: (Cudf.package -> package) -> universe -> Algo.Diagnostic.reason -> string option (** Convert a list of reasons to something readable by the user *) val string_of_reasons: (Cudf.package -> package) -> universe -> Algo.Diagnostic.reason list -> string (** Pretty-print atoms *) val string_of_atom: Cudf_types.vpkg -> string (** Pretty-print requests *) val string_of_request: Cudf_types.vpkg request -> string (** Pretty-print the universe *) val string_of_universe: Cudf.universe -> string (** Pretty-print of packages *) val string_of_packages: Cudf.package list -> string (** {2 External solver} *) val external_solver_available: unit -> bool opam-1.1.1/src/solver/solver.ocp0000644000175000017500000000026412272210733015031 0ustar i33173i33173comp += [ "-warn-error" "A" ] begin library "opam-solver" files = [ "opamCudf.ml" "opamHeuristic.ml" "opamSolver.ml" ] requires = [ "opam-core" ] end opam-1.1.1/src/client/0000755000175000017500000000000012272210733012756 5ustar i33173i33173opam-1.1.1/src/client/opamArg.ml0000644000175000017500000015765412272210733014720 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) open OpamTypes open Cmdliner (* Global options *) type global_options = { debug : bool; verbose: bool; quiet : bool; color : bool; switch : string option; yes : bool; strict : bool; root : dirname; no_base_packages: bool; git_version : bool; compat_mode_1_0 : bool; no_aspcud : bool; } let create_global_options git_version debug verbose quiet color switch yes strict root no_base_packages compat_mode_1_0 no_aspcud = { git_version; debug; verbose; quiet; color; switch; yes; strict; root; no_base_packages; compat_mode_1_0; no_aspcud } let apply_global_options o = if o.git_version then ( begin match OpamGitVersion.version with | None -> () | Some v -> OpamGlobals.msg "%s\n%!" v end; exit 0 ); OpamGlobals.debug := !OpamGlobals.debug || o.debug; OpamMisc.debug := !OpamGlobals.debug; OpamGlobals.verbose := (not o.quiet) && (!OpamGlobals.verbose || o.verbose); OpamGlobals.color := !OpamGlobals.color || o.color; begin match o.switch with | None -> () | Some s -> OpamGlobals.switch := `Command_line s end; OpamGlobals.root_dir := OpamFilename.Dir.to_string o.root; OpamGlobals.yes := !OpamGlobals.yes || o.yes; OpamGlobals.strict := !OpamGlobals.strict || o.strict; OpamGlobals.no_base_packages := !OpamGlobals.no_base_packages || o.no_base_packages; OpamGlobals.compat_mode_1_0 := !OpamGlobals.compat_mode_1_0 || o.compat_mode_1_0; OpamGlobals.use_external_solver := !OpamGlobals.use_external_solver && not o.no_aspcud (* Build options *) type build_options = { keep_build_dir: bool; make : string option; no_checksums : bool; build_test : bool; build_doc : bool; dryrun : bool; cudf_file : string option; fake : bool; external_tags : string list; jobs : int option; json : string option; } let create_build_options keep_build_dir make no_checksums build_test build_doc dryrun external_tags cudf_file fake jobs json = { keep_build_dir; make; no_checksums; build_test; build_doc; dryrun; external_tags; cudf_file; fake; jobs; json } let json_update = function | None -> () | Some f -> let write str = OpamFilename.write (OpamFilename.of_string f) str in OpamJson.set_output write let apply_build_options b = OpamGlobals.keep_build_dir := !OpamGlobals.keep_build_dir || b.keep_build_dir; OpamGlobals.no_checksums := !OpamGlobals.no_checksums || b.no_checksums; OpamGlobals.build_test := !OpamGlobals.build_test || b.build_test; OpamGlobals.build_doc := !OpamGlobals.build_doc || b.build_doc; OpamGlobals.dryrun := !OpamGlobals.dryrun || b.dryrun; OpamGlobals.external_tags := b.external_tags; OpamGlobals.cudf_file := b.cudf_file; OpamGlobals.fake := b.fake; json_update b.json; OpamGlobals.jobs := begin match b.jobs with | None -> !OpamGlobals.jobs | Some j -> Some j end; match b.make with | None -> () | Some s -> OpamGlobals.makecmd := (fun () -> s) (* Help sections common to all commands *) let global_option_section = "COMMON OPTIONS" let help_sections = [ `S global_option_section; `P "These options are common to all commands."; `S "ENVIRONMENT VARIABLES"; `P "opam makes use of environment variables listed here."; `P "$(i,OPAMCOLOR), when set to $(i,always) or $(i,never), sets a default \ value for the --color option"; `P "$(i,OPAMCURL) can be used to define an alternative for the 'curl' \ command-line utility to download files"; `S "FURTHER DOCUMENTATION"; `P (Printf.sprintf "See %s." OpamGlobals.default_repository_address); `S "AUTHORS"; `P "Thomas Gazagnaire "; `Noblank; `P "Anil Madhavapeddy "; `Noblank; `P "Fabrice Le Fessant "; `Noblank; `P "Frederic Tuong "; `Noblank; `P "Louis Gesbert "; `Noblank; `P "Vincent Bernardoff "; `Noblank; `P "Guillem Rieu "; `S "BUGS"; `P "Check bug reports at https://github.com/OCamlPro/opam/issues."; ] (* Converters *) let pr_str = Format.pp_print_string let repository_name = let parse str = `Ok (OpamRepositoryName.of_string str) in let print ppf name = pr_str ppf (OpamRepositoryName.to_string name) in parse, print let address = let parse str = `Ok (address_of_string str) in let print ppf address = pr_str ppf (string_of_address address) in parse, print let filename = let parse str = `Ok (OpamFilename.of_string str) in let print ppf filename = pr_str ppf (OpamFilename.to_string filename) in parse, print let dirname = let parse str = `Ok (OpamFilename.Dir.of_string str) in let print ppf dir = pr_str ppf (OpamFilename.prettify_dir dir) in parse, print let compiler = let parse str = `Ok (OpamCompiler.of_string str) in let print ppf comp = pr_str ppf (OpamCompiler.to_string comp) in parse, print let package_name = let parse str = `Ok (OpamPackage.Name.of_string str) in let print ppf pkg = pr_str ppf (OpamPackage.Name.to_string pkg) in parse, print let enum_with_default sl: 'a Arg.converter = let parse, print = Arg.enum sl in let parse s = match parse s with | `Ok _ as x -> x | _ -> `Ok (`default s) in parse, print (* Helpers *) let mk_flag ?section flags doc = let doc = Arg.info ?docs:section ~doc flags in Arg.(value & flag & doc) let mk_opt ?section flags value doc conv default = let doc = Arg.info ?docs:section ~docv:value ~doc flags in Arg.(value & opt conv default & doc) let mk_tristate_opt ?section flags value doc auto default = let doc = Arg.info ?docs:section ~docv:value ~doc flags in let choices = Arg.enum [ "always", `Always; "never", `Never; "auto", `Auto ] in let arg = Arg.(value & opt choices default & doc) in let to_bool = function | `Always -> true | `Never -> false | `Auto -> auto () in Term.(pure to_bool $ arg) let mk_subdoc ?(names="COMMANDS") commands = `S names :: List.map (fun (cs,_,d) -> let bold s = Printf.sprintf "$(b,%s)" s in let cmds = String.concat ", " (List.map bold cs) in `I (cmds, d) ) commands let mk_subcommands_aux ?(name="COMMAND") my_enum commands default = let command = let doc = Arg.info ~docv:name ~doc: (Printf.sprintf "Name of the sub-command. See the $(b,%sS) section for more info.%s" name (match default with | None -> "" | Some d -> " " ^ d)) [] in let commands = List.fold_left (fun acc (cs,f,_) -> List.map (fun c -> c,f) cs @ acc) [] commands in Arg.(value & pos 0 (some & my_enum commands) None & doc) in let params = let doc = Arg.info ~doc:"Optional parameters." [] in Arg.(value & pos_right 0 string [] & doc) in command, params let mk_subcommands ?name commands = mk_subcommands_aux ?name Arg.enum commands None let mk_subcommands_with_default ?name commands default = mk_subcommands_aux ?name enum_with_default commands (Some default) let term_info title ~doc ~man = let man = man @ help_sections in Term.info ~sdocs:global_option_section ~doc ~man title let arg_list name doc conv = let doc = Arg.info ~docv:name ~doc [] in Arg.(value & pos_all conv [] & doc) (* Common flags *) let print_short_flag = mk_flag ["s";"short"] "Output the names separated by one whitespace instead of using the usual formatting." let installed_flag = mk_flag ["i";"installed"] "List installed packages only." let installed_roots_flag = mk_flag ["installed-roots"] "Display only the installed roots." let fish_flag = mk_flag ["fish"] "Use fish-compatible mode for configuring OPAM." let zsh_flag = mk_flag ["zsh"] "Use zsh-compatible mode for configuring OPAM." let csh_flag = mk_flag ["csh"] "Use csh-compatible mode for configuring OPAM." let sh_flag = mk_flag ["sh"] "Use sh-compatible mode for configuring OPAM." let dot_profile_flag = mk_opt ["dot-profile"] "FILENAME" "Name of the configuration file to update instead of \ $(i,~/.profile) or $(i,~/.zshrc) based on shell detection." (Arg.some filename) None let repo_kind_flag = let kinds = [ (* main kinds *) "http" , `http; "local", `local; "git" , `git; "darcs" , `darcs; "hg" , `hg; (* aliases *) "wget" , `http; "curl" , `http; "rsync", `local; ] in mk_opt ["k";"kind"] "KIND" "Specify the kind of the repository to be set (the main ones \ are 'http', 'local', 'git', 'darcs' or 'hg')." Arg.(some (enum kinds)) None let jobs_flag = mk_opt ["j";"jobs"] "JOBS" "Set the maximal number of concurrent jobs to use. You can also set it using \ the OPAMJOBS environment variable." Arg.(some int) None let pattern_list = arg_list "PATTERNS" "List of package patterns." Arg.string let name_list = arg_list "PACKAGES" "List of package names." package_name let repository_list = arg_list "REPOSITORIES" "List of repository names." repository_name let param_list = arg_list "PARAMS" "List of parameters." Arg.string (* Options common to all commands *) let global_options = let section = global_option_section in let git_version = mk_flag ~section ["git-version"] "Print the git version if it exists and exit." in let debug = mk_flag ~section ["debug"] "Print debug message on stdout. \ This is equivalent to setting $(b,\\$OPAMDEBUG) to a non-empty value." in let verbose = mk_flag ~section ["v";"verbose"] "Be more verbose. \ This is equivalent to setting $(b,\\$OPAMVERBOSE) to a non-empty value." in let quiet = mk_flag ~section ["q";"quiet"] "Be quiet when installing a new compiler." in let color = mk_tristate_opt ~section ["color"] "WHEN" "Colorize the output. $(docv) must be `always', `never' or `auto'." (fun () -> Unix.isatty Unix.stdout) OpamGlobals.color_tri_state in let switch = mk_opt ~section ["switch"] "SWITCH" "Use $(docv) as the current compiler switch. \ This is equivalent to setting $(b,\\$OPAMSWITCH) to $(i,SWITCH)." Arg.(some string) None in let yes = mk_flag ~section ["y";"yes"] "Disable interactive mode and answer yes \ to all questions that would otherwise be \ asked to the user. \ This is equivalent to setting $(b,\\$OPAMYES) to a non-empty string." in let strict = mk_flag ~section ["strict"] "Fail whenever an error is found in a package definition \ or a configuration file. The default is to continue silently \ if possible." in let root = mk_opt ~section ["r";"root"] "ROOT" "Use $(docv) as the current root path. \ This is equivalent to setting $(b,\\$OPAMROOT) to $(i,ROOT)." dirname (OpamPath.root ()) in let no_base_packages = mk_flag ~section ["no-base-packages"] "Do not install base packages (useful for testing purposes). \ This is equivalent to setting $(b,\\$OPAMNOBASEPACKAGES) to a non-empty \ string." in let compat_mode_1_0 = mk_flag ~section ["compat-mode-1.0"] "Compatibility mode with OPAM 1.0" in let no_aspcud = mk_flag ~section ["no-aspcud"] "Do not use the external aspcud solver, even if available." in Term.(pure create_global_options $git_version $debug $verbose $quiet $color $switch $yes $strict $root $no_base_packages $compat_mode_1_0 $no_aspcud) let json_flag = mk_opt ["json"] "FILENAME" "Save the result output of an OPAM run in a computer-readable file" Arg.(some string) None (* Options common to all build commands *) let build_options = let keep_build_dir = mk_flag ["b";"keep-build-dir"] "Keep the build directory. \ This is equivalent to setting $(b,\\$OPAMKEEPBUILDIR) to a non-empty string." in let no_checksums = mk_flag ["no-checksums"] "Do not verify the checksum of downloaded archives.\ This is equivalent to setting $(b,\\$OPAMNOCHECKSUMS) to a non-empty string." in let build_test = mk_flag ["t";"build-test"] "Build and $(b,run) the package unit-tests. \ This is equivalent to setting $(b,\\$OPAMBUILDTEST) to a non-empty string." in let build_doc = mk_flag ["d";"build-doc"] "Build the package documentation. \ This is equivalent to setting $(b,\\$OPAMBUILDDOC) to a non-empty string." in let make = mk_opt ["m";"make"] "MAKE" "Use $(docv) as the default 'make' command." Arg.(some string) None in let dryrun = mk_flag ["dry-run"] "Simply call the solver without actually performing any build/install operations." in let external_tags = mk_opt ["e";"external"] "TAGS" "Display the external packages associated to the given tags." Arg.(list string) [] in let cudf_file = mk_opt ["cudf"] "FILENAME" "Save the CUDF request sent to the solver to $(docv)-.cudf." Arg.(some string) None in let fake = mk_flag ["fake"] "WARNING: This option is for testing purposes only! Using this option without \ care is the best way to corrupt your current compiler environment. When using \ this option OPAM will run a dry-run of the solver and then fake the build and \ install commands." in Term.(pure create_build_options $keep_build_dir $make $no_checksums $build_test $build_doc $dryrun $external_tags $cudf_file $fake $jobs_flag $json_flag) let init_dot_profile shell dot_profile = match dot_profile with | Some n -> n | None -> OpamFilename.of_string (OpamMisc.guess_dot_profile shell) module Client = OpamClient.SafeAPI type command = unit Term.t * Term.info (* INIT *) let init_doc = "Initialize OPAM state." let init = let doc = init_doc in let man = [ `S "DESCRIPTION"; `P "The $(b,init) command creates a fresh client state. This initializes OPAM \ configuration in $(i,~/.opam) and configures a default package repository."; `P "Once the fresh client has been created, OPAM will ask the user if he wants \ $(i,~/.profile) (or $i,~/.zshrc, depending on his shell) and $(i,~/.ocamlinit) \ to be updated. \ If $(b,--auto-setup) is used, OPAM will modify the configuration files automatically, \ without asking the user. If $(b,--no-setup) is used, OPAM will *NOT* modify \ anything outside of $(i,~/.opam)."; `P "Additional repositories can be added later by using the $(b,opam repository) command."; `P "The state of repositories can be synchronized by using $(b,opam update)."; `P "The user and global configuration files can be setup later by using $(b,opam config setup)."; ] in let jobs = mk_opt ["j";"jobs"] "JOBS" "Number of jobs to use when building packages." Arg.int OpamGlobals.default_jobs in let compiler = mk_opt ["comp"] "VERSION" "Which compiler version to use." compiler OpamCompiler.system in let repo_name = let doc = Arg.info ~docv:"NAME" ~doc:"Name of the repository." [] in Arg.(value & pos ~rev:true 1 repository_name OpamRepositoryName.default & doc) in let repo_address = let doc = Arg.info ~docv:"ADDRESS" ~doc:"Address of the repository." [] in Arg.(value & pos ~rev:true 0 address OpamRepository.default_address & doc) in let no_setup = mk_flag ["n";"no-setup"] "Do not update the global and user configuration options to setup OPAM." in let auto_setup = mk_flag ["a";"auto-setup"] "Automatically setup all the global and user configuration options for OPAM." in let init global_options build_options repo_kind repo_name repo_address compiler jobs no_setup auto_setup sh csh zsh fish dot_profile_o = (* Create the dir in current directory so that it can be made absolute *) OpamFilename.mkdir global_options.root; apply_global_options global_options; apply_build_options build_options; let repo_kind = guess_repository_kind repo_kind repo_address in let repo_priority = 0 in let repository = { repo_root = OpamPath.Repository.create (OpamPath.root ()) repo_name; repo_name; repo_kind; repo_address; repo_priority } in let update_config = if no_setup then `no else if auto_setup then `yes else `ask in let shell = if sh then `sh else if csh then `csh else if zsh then `zsh else if fish then `fish else OpamMisc.guess_shell_compat () in let dot_profile = init_dot_profile shell dot_profile_o in Client.init repository compiler ~jobs shell dot_profile update_config in Term.(pure init $global_options $build_options $repo_kind_flag $repo_name $repo_address $compiler $jobs $no_setup $auto_setup $sh_flag $csh_flag $zsh_flag $fish_flag $dot_profile_flag), term_info "init" ~doc ~man (* LIST *) let list_doc = "Display the list of available packages." let list = let doc = list_doc in let man = [ `S "DESCRIPTION"; `P "This command displays the list of installed packages, or the list of \ all the available packages if the $(b,--all) flag is used."; `P "Unless the $(b,--short) switch is used, the output format displays one \ package per line, and each line contains the name of the package, the \ installed version or -- if the package is not installed, and a short \ description. In color mode, root packages (eg. manually installed) are \ underlined."; `P " The full description can be obtained by doing $(b,opam info ). \ You can search through the package descriptions using the $(b,opam search) \ command." ] in let all = mk_flag ["a";"all"] "List all the packages which can be installed on the system." in let sort = mk_flag ["sort";"S"] "Sort the packages in dependency order." in let list global_options print_short all installed installed_roots sort packages = apply_global_options global_options; let filter = match all, installed, installed_roots with | true, _, _ -> `installable | _, _, true -> `roots | _, true, _ -> `installed | _ -> `installed in let order = if sort then `depends else `normal in Client.list ~print_short ~filter ~order ~exact_name:true ~case_sensitive:false packages in Term.(pure list $global_options $print_short_flag $all $installed_flag $installed_roots_flag $sort $pattern_list), term_info "list" ~doc ~man (* SEARCH *) let search = let doc = "Search into the package list." in let man = [ `S "DESCRIPTION"; `P "This command displays the list of available packages that match one of \ the package patterns specified as arguments."; `P "Unless the $(b,--short) flag is used, the output format is the same as the \ $(b,opam list) command. It displays one package per line, and each line \ contains the name of the package, the installed version or -- if the package \ is not installed, and a short description."; `P "The full description can be obtained by doing $(b,opam info )."; ] in let case_sensitive = mk_flag ["c";"case-sensitive"] "Force the search in case sensitive mode." in let search global_options print_short installed installed_roots case_sensitive pkgs = apply_global_options global_options; let filter = match installed, installed_roots with | _, true -> `roots | true, _ -> `installed | _ -> `all in let order = `normal in Client.list ~print_short ~filter ~order ~exact_name:false ~case_sensitive pkgs in Term.(pure search $global_options $print_short_flag $installed_flag $installed_roots_flag $case_sensitive $pattern_list), term_info "search" ~doc ~man (* SHOW *) let show_doc = "Display information about specific packages." let show = let doc = show_doc in let man = [ `S "DESCRIPTION"; `P "This command displays the information block for the selected \ package(s)."; `P "The information block consists in the name of the package, \ the installed version if this package is installed in the currently \ selected compiler, the list of available (installable) versions, and a \ complete description."; `P "$(b,opam list) can be used to display the list of \ available packages as well as a short description for each."; ] in let fields = let doc = Arg.info ~docv:"FIELDS" ~doc:"Only display these fields. You can specify multiple fields by separating them with commas." ["f";"field"] in Arg.(value & opt (list string) [] & doc) in let pkg_info global_options fields packages = apply_global_options global_options; Client.info ~fields packages in Term.(pure pkg_info $global_options $fields $pattern_list), term_info "show" ~doc ~man (* CONFIG *) let config_doc = "Display configuration options for packages." let config = let doc = config_doc in let commands = [ ["env"] , `env , "Return the environment variables PATH, MANPATH, OCAML_TOPLEVEL_PATH \ and CAML_LD_LIBRARY_PATH according to the currently selected \ compiler. The output of this command is meant to be evaluated by a \ shell, for example by doing $(b,eval `opam config env`)."; ["setup"] , `setup , "Configure global and user parameters for OPAM. Use $(b, opam config setup) \ to display more options. Use $(b,--list) to display the current configuration \ options. You can use this command to automatically update: (i) user-configuration \ files such as ~/.profile and ~/.ocamlinit; and (ii) global-configaration files \ controlling which shell scripts are loaded on startup, such as auto-completion. \ These configuration options can be updated using: $(b,opam config setup --global) \ to setup the global configuration files stored in $(b,~/.opam/opam-init/) and \ $(b,opam config setup --user) to setup the user ones. \ To modify both the global and user configuration, use $(b,opam config setup --all)."; ["exec"] , `exec , "Execute the shell script given in parameter with the correct environment variables. \ This option can be used to cross-compile between switches using \ $(b,opam config exec \"CMD ARG1 ... ARGn\" --switch=SWITCH)"; ["var"] , `var , "Return the value associated with the given variable. If the variable \ contains a colon such as $(i,pkg:var), then the left element will be \ understood as the package in which the variable is defined. \ The variable resolution is done as follows: first, OPAM will check whether \ $(b,\\$var) exists; for package variables, it will look for $(b,\\$pkg_var). \ If the variable is not found, OPAM will then check whether the variable is \ implicit. There are two global implicit variables: $(i,ocaml-version) and \ $(i,preinstalled) and two implicit variables per package: $(i,pkg:installed) \ which is either $(b,\"true\") or $(b,\"false\"), and $(i,pkg:enable) which is \ either $(b,\"enable\") or $(b,\"disable\"). Finally, OPAM will look into \ its global and package config files to find whether these variables exist."; ["list"] , `list , "Return the list of all variables defined in the listed packages. It is possible \ to filter the list of variables by giving package names (use $(b,globals) to get \ the list of global variables). No parameter means displaying all the variables."; ["subst"] , `subst , "Substitute variables in the given files. The strings $(i,%{var}%) are \ replaced by the value of the variable $(i,var) (see the documentation associated \ to $(b,opam config var))."; ["includes"], `includes, "returns include options."; ["bytecomp"], `bytecomp, "returns bytecode compile options."; ["asmcomp"] , `asmcomp , "returns assembly compile options."; ["bytelink"], `bytelink, "returns bytecode linking options."; ["asmlink"] , `asmlink , "returns assembly compile options."; ["report"] , `report, "Prints a summary of your setup, useful for bug-reports."; ] in let man = [ `S "DESCRIPTION"; `P "This command uses OPAM state to output information on how to use \ installed libraries, update the $(b,PATH), and substitute \ variables used in OPAM packages."; `P "Apart from $(b,opam config env), most of these commands are used \ by OPAM internally, and are of limited interest for the casual \ user."; ] @ mk_subdoc ~names:"DOMAINS" commands in let command, params = mk_subcommands ~name:"DOMAIN" commands in let is_rec = mk_flag ["R";"rec"] "Recursive query." in let all_doc = "Enable all the global and user configuration options." in let global_doc = "Enable all the global configuration options." in let user_doc = "Enable all the user configuration options." in let ocamlinit_doc = "Modify ~/.ocamlinit to make `#use \"topfind\"` works in the toplevel." in let profile_doc = "Modify ~/.profile (or ~/.zshrc if running zsh) to \ setup an OPAM-friendly environment when starting a new shell." in let no_complete_doc = "Do not load the auto-completion scripts in the environment." in let no_eval_doc = "Do not install `opam-switch-eval` to switch & eval using a single command." in let dot_profile_doc = "Select which configuration file to update (default is ~/.profile)." in let list_doc = "List the current configuration." in let sexp_doc = "Display environment variables as an s-expression" in let profile = mk_flag ["profile"] profile_doc in let ocamlinit = mk_flag ["ocamlinit"] ocamlinit_doc in let no_complete = mk_flag ["no-complete"] no_complete_doc in let no_switch_eval = mk_flag ["no-switch-eval"] no_eval_doc in let all = mk_flag ["a";"all"] all_doc in let user = mk_flag ["u";"user"] user_doc in let global = mk_flag ["g";"global"] global_doc in let list = mk_flag ["l";"list"] list_doc in let sexp = mk_flag ["sexp"] sexp_doc in let env = mk_opt ["e"] "" "Backward-compatible option, equivalent to $(b,opam config env)." Arg.string "" in let config global_options command env is_rec sh csh zsh fish sexp dot_profile_o list all global user profile ocamlinit no_complete no_switch_eval params = apply_global_options global_options; let mk ~is_byte ~is_link = { conf_is_rec = is_rec; conf_is_link = is_link; conf_is_byte = is_byte; conf_options = List.map OpamVariable.Section.Full.of_string params; } in let csh, fish = match sh, csh, sexp, fish with | false, false, false, false -> (* No overrides have been provided, so guess which shell is active *) (match OpamMisc.guess_shell_compat () with | `csh -> true , false | `fish -> false, true | `sh | `bash | `zsh -> false, false) | _ -> csh, fish in match command with | None -> if env="nv" then OpamConfigCommand.env ~csh ~sexp ~fish else OpamGlobals.error_and_exit "Missing subcommand. Usage: 'opam config '" | Some `env -> Client.CONFIG.env ~csh ~sexp ~fish | Some `setup -> let user = all || user in let global = all || global in let profile = user || profile in let ocamlinit = user || ocamlinit in let complete = global && not no_complete in let switch_eval = global && not no_switch_eval in let shell = if sh then `sh else if csh then `csh else if zsh then `zsh else if fish then `fish else OpamMisc.guess_shell_compat () in let dot_profile = init_dot_profile shell dot_profile_o in if list then Client.CONFIG.setup_list shell dot_profile else if profile || ocamlinit || complete || switch_eval then let dot_profile = if profile then Some dot_profile else None in let user = if user then Some { shell; ocamlinit; dot_profile } else None in let global = if global then Some { complete; switch_eval } else None in Client.CONFIG.setup user global else OpamGlobals.msg "usage: opam config setup [options]\n\ \n\ Main options\n\ \ -l, --list %s\n\ \ -a, --all %s\n\ \ --sh,--csh,--zsh,--fish Force the configuration mode to a given shell.\n\ \n\ User configuration\n\ \ -u, --user %s\n\ \ --ocamlinit %s\n\ \ --profile %s\n\ \ --dot-profile FILE %s\n\ \n\ Global configuration\n\ \ -g,--global %s\n\ \ --no-complete %s\n\ \ --no-switch-eval %s\n\n" list_doc all_doc user_doc ocamlinit_doc profile_doc dot_profile_doc global_doc no_complete_doc no_eval_doc | Some `exec -> let usage = "Usage: 'opam config exec \" ... \"'" in begin match params with | [] -> OpamGlobals.error_and_exit "Missing parameter. %s" usage | [c] -> Client.CONFIG.exec c | _ -> OpamGlobals.error_and_exit "Too many parameters. %s" usage end; | Some `list -> Client.CONFIG.list (List.map OpamPackage.Name.of_string params) | Some `var -> if params = [] then OpamGlobals.error_and_exit "Missing parameter. Usage: 'opam config var '" else Client.CONFIG.variable (OpamVariable.Full.of_string (List.hd params)) | Some `subst -> Client.CONFIG.subst (List.map OpamFilename.Base.of_string params) | Some `includes -> Client.CONFIG.includes ~is_rec (List.map OpamPackage.Name.of_string params) | Some `bytecomp -> Client.CONFIG.config (mk ~is_byte:true ~is_link:false) | Some `bytelink -> Client.CONFIG.config (mk ~is_byte:true ~is_link:true) | Some `asmcomp -> Client.CONFIG.config (mk ~is_byte:false ~is_link:false) | Some `asmlink -> Client.CONFIG.config (mk ~is_byte:false ~is_link:true) | Some `report -> let print label fmt = Printf.printf ("# %-15s "^^fmt^^"\n") label in Printf.printf "# OPAM status report\n"; let version = OpamVersion.to_string OpamVersion.current in let version = match OpamVersion.git with | None -> version | Some v -> Printf.sprintf "%s (%s)" version (OpamVersion.to_string v) in print "opam-version" "%s" version; print "os" "%s" (OpamGlobals.os_string ()); print "external-solver" "%b" (OpamCudf.external_solver_available ()); try let state = OpamState.load_state "config-report" in let open OpamState.Types in print "jobs" "%d" (OpamState.jobs state); print "repositories" "%d" (OpamRepositoryName.Map.cardinal state.repositories); print "pinned" "%d" (OpamPackage.Name.Map.cardinal state.pinned); print "current-switch" "%s" (OpamSwitch.to_string state.switch); print "preinstalled" "%b" (OpamFile.Comp.preinstalled (OpamFile.Comp.read (OpamPath.compiler_comp state.root state.compiler))); let index_file = OpamFilename.to_string (OpamPath.package_index state.root) in let u = Unix.gmtime (Unix.stat index_file).Unix.st_mtime in Unix.(print "last-update" "%04d-%02d-%02d %02d:%02d" (1900 + u.tm_year) (1 + u.tm_mon) u.tm_mday u.tm_hour u.tm_min); () with e -> print "read-state" "%s" (Printexc.to_string e) in Term.(pure config $global_options $command $env $is_rec $sh_flag $csh_flag $zsh_flag $fish_flag $sexp $dot_profile_flag $list $all $global $user $profile $ocamlinit $no_complete $no_switch_eval $params), term_info "config" ~doc ~man (* INSTALL *) let install_doc = "Install a list of packages." let install = let doc = install_doc in let man = [ `S "DESCRIPTION"; `P "This command installs one or more packages to the currently selected \ compiler. To install packages for another compiler, you need to switch \ compilers using $(b,opam switch). You can remove installed packages with \ $(b,opam remove), and list installed packages with $(b,opam list -i). \ See $(b,opam pin) as well to understand how to manage package versions."; `P "This command makes OPAM use the dependency solver to compute the \ transitive closure of dependencies to be installed, and will also handle \ conflicts. If the dependency solver returns more than one \ solution, OPAM will arbitrarily select the first one. If dependencies \ are to be installed, OPAM will confirm if the installation should \ proceed."; ] in let add_to_roots = let root = Some true, Arg.info ["set-root"] ~doc:"Mark given packages as installed roots. This is the default \ for newly manually-installed packages." in let unroot = Some false, Arg.info ["unset-root"] ~doc:"Mark given packages as \"installed automatically\"." in Arg.(value & vflag None[root; unroot]) in let deps_only = Arg.(value & flag & info ["deps-only"] ~doc:"Install all its dependencies, but don't actually install the \ package.") in let install global_options build_options add_to_roots deps_only packages = apply_global_options global_options; apply_build_options build_options; let packages = OpamPackage.Name.Set.of_list packages in Client.install packages add_to_roots deps_only in Term.(pure install $global_options $build_options $add_to_roots $deps_only $name_list), term_info "install" ~doc ~man (* REMOVE *) let remove_doc = "Remove a list of packages." let remove = let doc = remove_doc in let man = [ `S "DESCRIPTION"; `P "This command removes (i.e. uninstalls) one or more packages currently \ installed in the currently selected compiler switch. To remove packages \ installed in another compiler, you need to switch compilers using \ $(b,opam switch) or use the $(b,--switch) flag. This command is the \ inverse of $(b,opam-install)."; ] in let autoremove = mk_flag ["a";"auto-remove"] "Remove all the packages which have not been explicitly installed and \ which are not necessary anymore. It is possible to prevent the removal of an \ already-installed package by running $(b,opam install ). This flag \ can also be set using the $(b,\\$OPAMAUTOREMOVE) configuration variable." in let force = mk_flag ["force"] "Execute the remove commands of given packages directly, even if they are \ not considered installed by OPAM." in let remove global_options build_options autoremove force packages = apply_global_options global_options; apply_build_options build_options; let packages = OpamPackage.Name.Set.of_list packages in Client.remove ~autoremove ~force packages in Term.(pure remove $global_options $build_options $autoremove $force $name_list), term_info "remove" ~doc ~man (* REINSTALL *) let reinstall = let doc = "Reinstall a list of packages." in let man = [ `S "DESCRIPTION"; `P "This command removes the given packages, reinstalls them and \ recompiles the right package dependencies." ] in let reinstall global_options build_options packages = apply_global_options global_options; apply_build_options build_options; let packages = OpamPackage.Name.Set.of_list packages in Client.reinstall packages in Term.(pure reinstall $global_options $build_options $name_list), term_info "reinstall" ~doc ~man (* UPDATE *) let update_doc = "Update the list of available packages." let update = let doc = update_doc in let man = [ `S "DESCRIPTION"; `P "This command updates each repository that has been previously set up \ by the $(b,opam init) or $(b,opam repository) commands. The list of packages \ that can be upgraded will be printed out, and the user can use \ $(b,opam upgrade) to upgrade them."; ] in let repos_only = mk_flag ["R"; "repositories"] "Only update repositories, not development packages." in let sync = mk_flag ["sync-archives"] "Always sync the remote archives files. This is not \ a good idea to enable this, unless your really know \ what your are doing: this flag will make OPAM try to \ download the archive files for ALL the available \ packages." in let upgrade = mk_flag ["u";"upgrade"] "Automatically run $(b,opam upgrade --yes) after the update." in let update global_options jobs json repositories repos_only sync upgrade = apply_global_options global_options; json_update json; OpamGlobals.sync_archives := sync; OpamGlobals.jobs := jobs; Client.update ~repos_only repositories; if upgrade then ( OpamGlobals.yes := true; Client.upgrade None ) in Term.(pure update $global_options $jobs_flag $json_flag $repository_list $repos_only $sync $upgrade), term_info "update" ~doc ~man (* UPGRADE *) let upgrade_doc = "Upgrade the installed package to latest version." let upgrade = let doc = upgrade_doc in let man = [ `S "DESCRIPTION"; `P "This command upgrades the installed packages to their latest available \ versions. More precisely, this command calls the dependency solver to \ find a consistent state where $(i,most) of the installed packages are \ upgraded to their latest versions."; ] in let upgrade global_options build_options names = apply_global_options global_options; apply_build_options build_options; let packages = match names with | [] -> None | _ -> Some (OpamPackage.Name.Set.of_list names) in Client.upgrade packages in Term.(pure upgrade $global_options $build_options $name_list), term_info "upgrade" ~doc ~man (* REPOSITORY *) let repository_doc = "Manage OPAM repositories." let repository = let doc = repository_doc in let commands = [ ["add"] , `add , "Add the repository $(b,name) available at address \ $(b,address) to the list of repositories used by OPAM, \ with priority $(b,priority). \ The repository priority can be optionally specified with \ $(b,--priority), otherwise the new repository has a higher \ priority then any other existing repositories. \ The kind of the repository can be specified with the \ $(b,--kind) option, otherwise it will be determined \ automatically."; ["remove"] , `remove , "Remove the repository named $(b,name) from the list of \ repositories used by OPAM."; ["list"] , `list , "List all repositories used by OPAM."; ["priority"] , `priority, "Change the priority of repository named $(b,name) to $(b,priority)."; ] in let man = [ `S "DESCRIPTION"; `P "This command is used to manage OPAM repositories. To synchronize OPAM \ with the last versions of the packages available in remote \ repositories, $(b,opam update) should be used."; ] @ mk_subdoc commands in let command, params = mk_subcommands commands in let priority = mk_opt ["p";"priority"] "INT" "Set the repository priority (bigger is better)" Arg.(some int) None in let error number usage = let msg = match number with | `missing -> "Missing parameter(s)" | `toomany -> "Too many parameters" in OpamGlobals.error_and_exit "%s. Usage: '%s'" msg usage in let usage_add = "opam repository add
" in let usage_list = "opam repository list" in let usage_priority = "opam repository priority " in let usage_remove = "opam repository remove " in let repository global_options command kind priority short params = apply_global_options global_options; let add = function | [] | [_] -> error `missing usage_add | [name;address] -> let name = OpamRepositoryName.of_string name in let address = address_of_string address in let kind = guess_repository_kind kind address in Client.REPOSITORY.add name kind address ~priority | _ -> error `toomany usage_add in let list = function | [] -> Client.REPOSITORY.list ~short | _ -> error `toomany usage_list in let priority = function | [] | [_] -> error `missing usage_priority | [name; p] -> let name = OpamRepositoryName.of_string name in let priority = try int_of_string p with _ -> OpamGlobals.error_and_exit "%s is not an integer." p in Client.REPOSITORY.priority name ~priority | _ -> error `toomany usage_priority in let remove = function | [name] -> let name = OpamRepositoryName.of_string name in Client.REPOSITORY.remove name | [] -> error `missing usage_remove | _ -> error `toomany usage_remove in match command with | Some `add -> add params | None | Some `list -> list params | Some `priority -> priority params | Some `remove -> remove params in Term.(pure repository $global_options $command $repo_kind_flag $priority $print_short_flag $params), term_info "repository" ~doc ~man (* SWITCH *) let switch_doc = "Manage multiple installation of compilers." let switch = let doc = switch_doc in let commands = [ ["install"] , `install , "Install the given compiler. The commands fails if the package is \ already installed (e.g. it will not transparently switch to the \ installed compiler switch, as $(b,opam switch ) does)."; ["remove"] , `remove , "Remove the given compiler."; ["export"] , `export , "Export the list installed package to a file."; ["import"] , `import , "Install the packages from a file."; ["reinstall"] , `reinstall, "Reinstall the given compiler switch. This will also try reinstall the \ installed packages."; ["list"] , `list , "List compilers. \ By default, lists installed and `standard' compilers. Use `--all' to get \ the list of all installable compilers.\n\ The first column displays the switch name (if any), the second one \ the switch state (C = current, I = installed, -- = not installed), \ the third one the compiler name and the last one the compiler \ description. To switch to an already installed compiler alias (with \ state = I), use $(b,opam switch ). If you want to use a new \ compiler , use $(b,opam switch ): this will download, \ compile and create a fresh and independent environment where new \ packages can be installed. If you want to create a new compiler alias \ (for instance because you already have this compiler version installed), \ use $(b,opam switch --alias-of ). In case \ and are the same, this is equivalent to $(b,opam switch )."; ["show"] , `current , "Show the current compiler."; ] in let man = [ `S "DESCRIPTION"; `P "This command allows one to switch between different compiler versions, \ installing the compiler if $(b,opam switch) is used to switch to that \ compiler for the first time. The different compiler versions are \ totally independent from each other, meaning that OPAM maintains a \ separate state (e.g. list of installed packages...) for each."; `P "See the documentation of $(b,opam switch list) to see the compilers which \ are available, and how to switch or to install a new one." ] @ mk_subdoc commands in let command, params = mk_subcommands_with_default commands "If a compiler switch is given instead of an usual command, this command \ will switch to the given compiler. You will then need to run \ $(b,eval `opam config env`) to update your environment variables." in let alias_of = mk_opt ["A";"alias-of"] "COMP" "The name of the compiler description which will be aliased." Arg.(some string) None in let filename = mk_opt ["f";"filename"] "FILENAME" "The name of the file to export to/import from." Arg.(some filename) None in let no_warning = mk_flag ["no-warning"] "Do not display any warning related to environment variables." in let no_switch = mk_flag ["no-switch"] "Only install the compiler switch, without switching to it. If the compiler \ switch is already installed, then do nothing." in let installed = mk_flag ["i";"installed"] "List installed compiler switches only." in let all = mk_flag ["a";"all"] "List all the compilers which can be installed on the system." in let switch global_options build_options command alias_of filename print_short installed all no_warning no_switch params = apply_global_options global_options; apply_build_options build_options; let no_alias_of () = if alias_of <> None then OpamGlobals.error_and_exit "invalid -alias-of option" in let mk_comp alias = match alias_of with | None -> OpamCompiler.of_string alias | Some comp -> OpamCompiler.of_string comp in let warning = not no_warning in match command, params with | None , [] | Some `list, [] -> no_alias_of (); Client.SWITCH.list ~print_short ~installed ~all | Some `install, [switch] -> Client.SWITCH.install ~quiet:global_options.quiet ~warning ~update_config:(not no_switch) (OpamSwitch.of_string switch) (mk_comp switch) | Some `export, [] -> no_alias_of (); Client.SWITCH.export filename | Some `import, [] -> no_alias_of (); Client.SWITCH.import filename | Some `remove, switches -> no_alias_of (); List.iter (fun switch -> Client.SWITCH.remove (OpamSwitch.of_string switch)) switches | Some `reinstall, [switch] -> no_alias_of (); Client.SWITCH.reinstall (OpamSwitch.of_string switch) | Some `current, [] -> no_alias_of (); Client.SWITCH.show () | Some `default switch, [] -> (match alias_of with | None -> Client.SWITCH.switch ~quiet:global_options.quiet ~warning (OpamSwitch.of_string switch) | _ -> Client.SWITCH.install ~quiet:global_options.quiet ~warning ~update_config:(not no_switch) (OpamSwitch.of_string switch) (mk_comp switch)) | _, l -> OpamGlobals.error_and_exit "wrong number of arguments (%d)" (List.length l) in Term.(pure switch $global_options $build_options $command $alias_of $filename $print_short_flag $installed $all $no_warning $no_switch $params), term_info "switch" ~doc ~man (* PIN *) let pin_doc = "Pin a given package to a specific version." let pin = let doc = pin_doc in let man = [ `S "DESCRIPTION"; `P "This command will 'pin' a package to a specific version, or use a \ specific source path for installing and upgrading the package. Using \ $(b,opam pin none) will undo the 'pinned' status of \ ."; `P "It is possible to pin a package to a specific git commit/tag/branch \ with $(b,opam pin #)."; `P "By default, local directories will be pinned as `local` backends. \ You can change that default choice by forcing a given backend kind \ using the $(b,--kind) option."; `P "To list all the currently pinned packages, call the $(b,opam pin) \ without arguments or use $(b,--list)." ] in let package = let doc = Arg.info ~docv:"PACKAGE" ~doc:"Package name." [] in Arg.(value & pos 0 (some string) None & doc) in let pin_option = let doc = Arg.info ~docv:"PIN" ~doc: "Specific version, local path, git or darcs url to pin the package to, \ or 'none' to unpin the package." [] in Arg.(value & pos 1 (some string) None & doc) in let edit = mk_flag ["e";"edit"] "Edit the OPAM file associated to the given package." in let list = mk_flag ["l";"list"] "List the currently pinned packages." in let remove = mk_flag ["u";"unpin"] "Unpin the given package." in let kind = let doc = Arg.info ~docv:"KIND" ~doc:"Force the kind of pinning." ["k";"kind"] in let kinds = [ "git" , `git; "darcs" , `darcs; "version", `version; "local" , `local; "rsync" , `local; "hg" , `hg ] in Arg.(value & opt (some & enum kinds) None & doc) in let force = mk_flag ["f";"force"] "Disable consistency checks." in let pin global_options force kind edit remove list package pin = apply_global_options global_options; let edit_opam n = let pin = { pin_package = OpamPackage.Name.of_string n; pin_option = Edit } in Client.PIN.pin ~force pin in let unpin n = let pin = { pin_package = OpamPackage.Name.of_string n; pin_option = Unpin } in Client.PIN.pin ~force pin in match package, pin, edit, remove, list with | Some n, None, true, false, false -> edit_opam n | Some n, None, false, true, false -> unpin n | None, None, false, false, _ -> Client.PIN.list () | Some n, Some p, _ , false, false -> let pin = { pin_package = OpamPackage.Name.of_string n; pin_option = pin_option_of_string ?kind:kind p } in Client.PIN.pin ~force pin; if edit then edit_opam n | _ -> OpamGlobals.error_and_exit "Wrong arguments" in Term.(pure pin $global_options $force $kind $edit $remove $list $package $pin_option), term_info "pin" ~doc ~man (* HELP *) let help = let doc = "Display help about OPAM and OPAM commands." in let man = [ `S "DESCRIPTION"; `P "Prints help about OPAM commands."; `P "Use `$(mname) help topics' to get the full list of help topics."; ] in let topic = let doc = Arg.info [] ~docv:"TOPIC" ~doc:"The topic to get help on." in Arg.(value & pos 0 (some string) None & doc ) in let help man_format cmds topic = match topic with | None -> `Help (`Pager, None) | Some topic -> let topics = "topics" :: cmds in let conv, _ = Cmdliner.Arg.enum (List.rev_map (fun s -> (s, s)) topics) in match conv topic with | `Error e -> `Error (false, e) | `Ok t when t = "topics" -> List.iter print_endline cmds; `Ok () | `Ok t -> `Help (man_format, Some t) in Term.(ret (pure help $Term.man_format $Term.choice_names $topic)), Term.info "help" ~doc ~man let default = let doc = "source-based OCaml package management" in let man = [ `S "DESCRIPTION"; `P "OPAM is a package manager for OCaml. It uses the powerful mancoosi \ tools to handle dependencies, including support for version \ constraints, optional dependencies, and conflict management."; `P "It has support for different remote repositories such as HTTP, rsync, git, \ darcs and mercurial. It handles multiple OCaml versions concurrently, and is \ flexible enough to allow you to use your own repositories and packages \ in addition to the central ones it provides."; `P "Use either $(b,opam --help) or $(b,opam help ) \ for more information on a specific command."; ] @ help_sections in let usage global_options = apply_global_options global_options; OpamGlobals.msg "usage: opam [--version]\n\ \ [--help]\n\ \ []\n\ \n\ The most commonly used opam commands are:\n\ \ init %s\n\ \ list %s\n\ \ show %s\n\ \ install %s\n\ \ remove %s\n\ \ update %s\n\ \ upgrade %s\n\ \ config %s\n\ \ repository %s\n\ \ switch %s\n\ \ pin %s\n\ \n\ See 'opam help ' for more information on a specific command.\n" init_doc list_doc show_doc install_doc remove_doc update_doc upgrade_doc config_doc repository_doc switch_doc pin_doc in Term.(pure usage $global_options), Term.info "opam" ~version:(OpamVersion.to_string OpamVersion.current) ~sdocs:global_option_section ~doc ~man let make_command_alias cmd name = let term, info = cmd in let orig = Term.name info in let doc = Printf.sprintf "An alias for $(b,%s)." orig in let man = [ `S "DESCRIPTION"; `P (Printf.sprintf "$(b,$(mname) %s) is an alias for $(b,$(mname) %s)." name orig); `P (Printf.sprintf "See $(b,$(mname) %s --help) for details." orig); ] in term, Term.info name ~docs:"COMMANDS ALIASES" ~doc ~man let commands = [ init; list; search; show; make_command_alias show "info"; install; remove; make_command_alias remove "uninstall"; reinstall; update; upgrade; config; repository; make_command_alias repository "remote"; switch; pin; help; ] let is_external_command () = Array.length Sys.argv > 1 && let opam = Sys.argv.(0) in let name = Sys.argv.(1) in String.length name > 1 && name.[0] <> '-' && List.for_all (fun (_,info) -> Term.name info <> name) commands && OpamSystem.command_exists (opam ^ "-" ^ name) let run_external_command () = let n = Array.length Sys.argv in if n > 1 then ( let opam = Sys.argv.(0) in let name = Sys.argv.(1) in let args = Array.sub Sys.argv 2 (n-2) in let r = OpamProcess.run (opam ^ "-" ^ name) (Array.to_list args) in exit r.OpamProcess.r_code ) else () let run default commands = Sys.catch_break true; let _ = Sys.signal Sys.sigpipe Sys.Signal_ignore in try if is_external_command () then run_external_command (); match Term.eval_choice ~catch:false default commands with | `Error _ -> exit 1 | _ -> exit 0 with | OpamGlobals.Exit 0 -> () | e -> Printf.eprintf "'%s' failed.\n" (String.concat " " (Array.to_list Sys.argv)); let exit_code = ref 1 in begin match e with | OpamGlobals.Exit i -> exit_code := i; if !OpamGlobals.debug && i <> 0 then Printf.eprintf "%s" (OpamMisc.pretty_backtrace ()) | OpamSystem.Internal_error _ | OpamSystem.Process_error _ -> Printf.eprintf "%s\n" (Printexc.to_string e); Printf.eprintf "%s" (OpamMisc.pretty_backtrace ()); | Sys.Break -> exit_code := 1 | _ -> Printf.fprintf stderr "Fatal error:\n%s\n" (Printexc.to_string e); Printf.eprintf "%s" (OpamMisc.pretty_backtrace ()); end; exit !exit_code opam-1.1.1/src/client/opamAction.ml0000644000175000017500000005605312272210733015413 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) let log fmt = OpamGlobals.log "ACTION" fmt open OpamTypes open OpamFilename.OP open OpamState.Types (* Install the package files *) (* IMPORTANT: this function is executed by the children processes, thus it is important to NOT modify the global state of OPAM here. Thus, the update of ~/.opam/ OpamGlobals.msg "Installing %s.\n" (OpamPackage.to_string nv); let name = OpamPackage.name nv in let opam_f = OpamPath.opam t.root nv in let opam_ = OpamState.opam t nv in let config_f = OpamPath.Switch.build_config t.root t.switch nv in let config = OpamFile.Dot_config.safe_read config_f in let install_f = OpamPath.Switch.build_install t.root t.switch nv in let install = OpamFile.Dot_install.safe_read install_f in (* check that libraries and syntax extensions specified in .opam and .config are in sync *) let check kind config_sections opam_sections = List.iter (fun cs -> if not (List.mem cs opam_sections) then OpamGlobals.error_and_exit "The %s %s does not appear in %s" kind (OpamVariable.Section.to_string cs) (OpamFilename.to_string opam_f) ) config_sections; List.iter (fun os -> if not (List.mem os config_sections) then OpamGlobals.error_and_exit "The %s %s does not appear in %s" kind (OpamVariable.Section.to_string os) (OpamFilename.to_string config_f) ) opam_sections in if not (OpamFilename.exists config_f) && (OpamFile.OPAM.libraries opam_ <> [] || OpamFile.OPAM.syntax opam_ <> []) then OpamGlobals.error_and_exit "%s does not exist but %s defines some libraries and syntax extensions" (OpamFilename.to_string config_f) (OpamFilename.to_string opam_f); check "library" (OpamFile.Dot_config.Library.available config) (OpamFile.OPAM.libraries opam_); check "syntax" (OpamFile.Dot_config.Syntax.available config) (OpamFile.OPAM.syntax opam_); (* check that depends (in .opam) and requires (in .config) fields are in almost in sync *) (* NOTES: the check is partial as we don't know which clause is valid in depends (XXX there is surely a way to get it from the solver) *) let local_sections = OpamFile.Dot_config.Section.available config in let libraries_in_opam = OpamFormula.fold_left (fun accu (n,_) -> if OpamState.is_name_installed t n then ( let nv = OpamState.find_installed_package_by_name t n in let opam = OpamState.opam t nv in let libs = OpamFile.OPAM.libraries opam in let syntax = OpamFile.OPAM.syntax opam in List.fold_right OpamVariable.Section.Set.add (libs @ syntax) accu ) else accu ) OpamVariable.Section.Set.empty (OpamFile.OPAM.depends opam_) in let libraries_in_config = List.fold_left (fun accu s -> List.fold_left (fun accu r -> OpamVariable.Section.Set.add r accu ) accu (OpamFile.Dot_config.Section.requires config s) ) OpamVariable.Section.Set.empty local_sections in OpamVariable.Section.Set.iter (fun s -> if not (List.mem s local_sections) && not (OpamVariable.Section.Set.mem s libraries_in_opam) then let config_f = OpamFilename.to_string (OpamPath.Switch.build_config t.root t.switch nv) in let opam_f = OpamFilename.to_string (OpamPath.opam t.root nv) in let local_sections = List.map OpamVariable.Section.to_string local_sections in let opam_sections = List.map OpamVariable.Section.to_string (OpamVariable.Section.Set.elements libraries_in_opam) in OpamGlobals.error_and_exit "%s appears as a library dependency in %s, but:\n\ - %s defines the libraries {%s}\n\ - Packages in %s defines the libraries {%s}" (OpamVariable.Section.to_string s) config_f config_f (String.concat ", " local_sections) opam_f (String.concat ", " opam_sections) ) libraries_in_config; (* .install *) OpamFile.Dot_install.write (OpamPath.Switch.install t.root t.switch name) install; (* .config *) OpamFile.Dot_config.write (OpamPath.Switch.config t.root t.switch name) config; let warnings = ref [] in let check ~src ~dst base = let src_file = OpamFilename.create src base.c in if base.optional && not (OpamFilename.exists src_file) then log "Not installing %s is not present and optional." (OpamFilename.to_string src_file); if not base.optional && not (OpamFilename.exists src_file) then ( warnings := (dst, base.c) :: !warnings ); OpamFilename.exists src_file in (* Install a list of files *) let install_files dst_fn files_fn = let dst_dir = dst_fn t.root t.switch name in let files = files_fn install in if not (OpamFilename.exists_dir dst_dir) then ( log "creating %s" (OpamFilename.Dir.to_string dst_dir); OpamFilename.mkdir dst_dir; ); List.iter (fun (base, dst) -> let src_file = OpamFilename.create build_dir base.c in let dst_file = match dst with | None -> OpamFilename.create dst_dir (OpamFilename.basename src_file) | Some d -> OpamFilename.create dst_dir d in if check ~src:build_dir ~dst:dst_dir base then OpamFilename.copy ~src:src_file ~dst:dst_file; ) files in (* bin *) install_files (fun r s _ -> OpamPath.Switch.bin r s) OpamFile.Dot_install.bin; (* sbin *) install_files (fun r s _ -> OpamPath.Switch.sbin r s) OpamFile.Dot_install.sbin; (* lib *) install_files OpamPath.Switch.lib OpamFile.Dot_install.lib; (* toplevel *) install_files (fun r s _ -> OpamPath.Switch.toplevel r s) OpamFile.Dot_install.toplevel; install_files (fun r s _ -> OpamPath.Switch.stublibs r s) OpamFile.Dot_install.stublibs; (* Man pages *) install_files (fun r s _ -> OpamPath.Switch.man_dir r s) OpamFile.Dot_install.man; (* Shared files *) install_files OpamPath.Switch.share OpamFile.Dot_install.share; (* Etc files *) install_files OpamPath.Switch.etc OpamFile.Dot_install.etc; (* Documentation files *) install_files OpamPath.Switch.doc OpamFile.Dot_install.doc; (* misc *) List.iter (fun (src, dst) -> let src_file = OpamFilename.create (OpamFilename.cwd ()) src.c in if OpamFilename.exists dst && OpamState.confirm "Overwriting %s ?" (OpamFilename.to_string dst) then OpamFilename.copy ~src:src_file ~dst else begin OpamGlobals.msg "Installing %s to %s.\n" (OpamFilename.Base.to_string src.c) (OpamFilename.to_string dst); if OpamState.confirm "Continue ?" then OpamFilename.copy ~src:src_file ~dst end ) (OpamFile.Dot_install.misc install); if !warnings <> [] then ( let print (dir, base) = Printf.sprintf " - %s in %s" (OpamFilename.Base.to_string base) (OpamFilename.Dir.to_string dir) in OpamSystem.internal_error "While installing the following files:\n%s" (String.concat "\n" (List.map print !warnings)); ) ); if not (!OpamGlobals.keep_build_dir || !OpamGlobals.debug) then OpamFilename.rmdir build_dir (* Prepare the package build: * apply the patches * substitute the files *) let prepare_package_build t nv = let p_build = OpamPath.Switch.build t.root t.switch nv in let opam = OpamState.opam t nv in if not (OpamFilename.exists_dir p_build) then OpamFilename.mkdir p_build; (* Substitute the patched files.*) let patches = OpamFile.OPAM.patches opam in OpamFilename.in_dir p_build (fun () -> let all = OpamFile.OPAM.substs opam in let patches = OpamMisc.filter_map (fun (f,_) -> if List.mem f all then Some f else None ) patches in List.iter (OpamState.substitute_file t OpamVariable.Map.empty) patches ); (* Apply the patches *) List.iter (fun (base, filter) -> let root = OpamPath.Switch.build t.root t.switch nv in let patch = root // OpamFilename.Base.to_string base in if OpamState.eval_filter t OpamVariable.Map.empty filter then ( OpamGlobals.msg "Applying %s.\n" (OpamFilename.Base.to_string base); OpamFilename.patch patch p_build) ) patches; (* Substitute the configuration files. We should be in the right directory to get the correct absolute path for the substitution files (see [substitute_file] and [OpamFilename.of_basename]. *) OpamFilename.in_dir p_build (fun () -> List.iter (OpamState.substitute_file t OpamVariable.Map.empty) (OpamFile.OPAM.substs opam) ) let extract_package t nv = log "extract_package: %s" (OpamPackage.to_string nv); let build_dir = OpamPath.Switch.build t.root t.switch nv in OpamFilename.rmdir build_dir; let extract_and_copy_files nv file = begin match file with | None -> () | Some f -> OpamFilename.extract_generic_file f build_dir end; OpamState.copy_files t nv build_dir in if OpamState.is_locally_pinned t (OpamPackage.name nv) then let dir = OpamPath.Switch.dev_package t.root t.switch nv in extract_and_copy_files nv (OpamState.download_upstream t nv dir) else ( let nv = OpamState.pinning_version t nv in match OpamState.download_archive t nv with | Some f -> OpamFilename.extract f build_dir | None -> let dir = OpamPath.dev_package t.root nv in extract_and_copy_files nv (OpamState.download_upstream t nv dir) ); prepare_package_build t nv; build_dir let string_of_commands commands = let commands_s = List.map (fun cmd -> String.concat " " cmd) commands in " " ^ if commands_s <> [] then String.concat "\n " commands_s else "Nothing to do." let compilation_env t opam = let env0 = OpamState.get_full_env t in let env1 = [ ("OPAM_PACKAGE_NAME", OpamPackage.Name.to_string (OpamFile.OPAM.name opam)); ("OPAM_PACKAGE_VERSION", OpamPackage.Version.to_string (OpamFile.OPAM.version opam)) ] @ env0 in OpamState.add_to_env t env1 (OpamFile.OPAM.build_env opam) let get_metadata t = let compiler = if t.compiler = OpamCompiler.system then let system_version = match OpamCompiler.Version.system () with | None -> "" | Some v -> OpamCompiler.Version.to_string v in Printf.sprintf "system (%s)" system_version else OpamCompiler.to_string t.compiler in [ ("compiler", compiler); ] let update_metadata t ~installed ~installed_roots ~reinstall = let mark_pinned_versions = OpamPackage.Set.map (fun p -> let name = OpamPackage.name p in if OpamPackage.Name.Map.mem name t.pinned then OpamPackage.pinned name else p) in let installed = mark_pinned_versions installed in let installed_roots = mark_pinned_versions installed_roots in let reinstall = mark_pinned_versions reinstall in let installed_roots = OpamPackage.Set.inter installed_roots installed in let reinstall = OpamPackage.Set.inter installed_roots reinstall in OpamFile.Installed.write (OpamPath.Switch.installed t.root t.switch) installed; OpamFile.Installed_roots.write (OpamPath.Switch.installed_roots t.root t.switch) installed_roots; OpamFile.Reinstall.write (OpamPath.Switch.reinstall t.root t.switch) reinstall let dev_opam_opt t nv build_dir = let opam () = OpamState.opam_opt t nv in if OpamState.is_dev_package t nv then let dir = if OpamFilename.exists_dir (build_dir / "opam") then build_dir / "opam" else build_dir in let overlay = dir // "opam" in if OpamFilename.exists overlay then try Some (OpamFile.OPAM.read overlay) with _ -> opam () else opam () else opam () let dev_opam t nv build_dir = match dev_opam_opt t nv build_dir with | None -> OpamPackage.unknown (OpamPackage.name nv) (Some (OpamPackage.version nv)) | Some nv' -> OpamFile.OPAM.with_name (OpamFile.OPAM.with_version nv' (OpamPackage.version nv)) (OpamPackage.name nv) (* Remove a given package *) (* This will be done by the parent process, so theoritically we are allowed to modify the global state of OPAM here. However, for consistency reasons, this is done in the main function only. *) let remove_package_aux t ~metadata ~rm_build ?(silent=false) nv = log "Removing %s (%b)" (OpamPackage.to_string nv) metadata; let name = OpamPackage.name nv in (* Run the remove script *) let opam = OpamState.opam_opt t nv in OpamGlobals.msg "Removing %s.\n" (OpamPackage.to_string nv); begin match opam with | None -> OpamGlobals.msg " No OPAM file has been found!\n" | Some opam -> let env = compilation_env t opam in let commands = OpamState.filter_commands t OpamVariable.Map.empty (OpamFile.OPAM.remove opam) in match commands with | [] -> () | remove -> let p_build = OpamPath.Switch.build t.root t.switch nv in (* We try to run the remove scripts in the folder where it was extracted If it does not exist, we try to download and extract the archive again, if that fails, we don't really care. *) (* We also use a small hack: if the remove command is simply 'ocamlfind remove xxx' then, no need to extract the archive again. *) let use_ocamlfind = function | [] -> true | "ocamlfind" :: _ -> true | _ -> false in if not (OpamFilename.exists_dir p_build) && not (List.for_all use_ocamlfind remove) then ( try let _ = extract_package t nv in () with _ -> () ); let opam = dev_opam t nv p_build in let remove = OpamState.filter_commands t OpamVariable.Map.empty (OpamFile.OPAM.remove opam) in let name = OpamPackage.Name.to_string name in let exec_dir, name = if OpamFilename.exists_dir p_build then p_build, Some name else t.root , None in try OpamGlobals.msg "%s\n" (string_of_commands remove); let metadata = get_metadata t in OpamFilename.exec ~env ?name exec_dir ~metadata ~keep_going:true remove with OpamSystem.Process_error r -> if not silent then OpamGlobals.warning "failure in package uninstall script, some files may remain:\n%s" (OpamProcess.string_of_result r) end; (* Remove the libraries *) OpamFilename.rmdir (OpamPath.Switch.lib t.root t.switch name); (* Remove the documentation *) OpamFilename.rmdir (OpamPath.Switch.doc t.root t.switch name); (* Remove build/ if requested *) if not !OpamGlobals.keep_build_dir && rm_build then OpamFilename.rmdir (OpamPath.Switch.build t.root t.switch nv); (* Clean-up the active repository *) log "Cleaning-up the switch repository"; let dev_dir = OpamPath.Switch.dev_package t.root t.switch nv in if OpamFilename.exists_dir dev_dir then OpamFilename.rmdir dev_dir; let install = OpamFile.Dot_install.safe_read (OpamPath.Switch.install t.root t.switch name) in let remove_files dst_fn files = let files = files install in List.iter (fun (base, dst) -> let dst_dir = dst_fn t.root t.switch in let dst_file = match dst with | None -> dst_dir // Filename.basename (OpamFilename.Base.to_string base.c) | Some b -> OpamFilename.create dst_dir b in OpamFilename.remove dst_file ) files in (* Remove the binaries *) log "Removing the binaries"; remove_files OpamPath.Switch.bin OpamFile.Dot_install.bin; remove_files OpamPath.Switch.sbin OpamFile.Dot_install.sbin; (* Remove the C bindings *) remove_files OpamPath.Switch.stublibs OpamFile.Dot_install.stublibs; (* Remove man pages *) remove_files OpamPath.Switch.man_dir OpamFile.Dot_install.man; (* Remove the misc files *) log "Removing the misc files"; List.iter (fun (_,dst) -> if OpamFilename.exists dst then begin OpamGlobals.msg "Removing %s." (OpamFilename.to_string dst); if OpamState.confirm "Continue ?" then OpamFilename.remove dst end ) (OpamFile.Dot_install.misc install); (* Removing the shared dir *) OpamFilename.rmdir (OpamPath.Switch.share t.root t.switch name); (* Removing the etc dir *) OpamFilename.rmdir (OpamPath.Switch.etc t.root t.switch name); (* Remove .config and .install *) log "Removing config and install files"; OpamFilename.remove (OpamPath.Switch.install t.root t.switch name); OpamFilename.remove (OpamPath.Switch.config t.root t.switch name); (* Remove the pinned cache *) log "Removing the pinned cache"; OpamFilename.rmdir (OpamPath.Switch.dev_package t.root t.switch nv); (* Update the metadata *) if metadata then ( let installed = OpamPackage.Set.remove nv t.installed in let installed_roots = OpamPackage.Set.remove nv t.installed_roots in let reinstall = OpamPackage.Set.remove nv t.reinstall in update_metadata t ~installed ~installed_roots ~reinstall; OpamState.remove_metadata t (OpamPackage.Set.singleton nv); ); (* Remove the dev archive if no switch uses the package anymore *) let dev = OpamPath.dev_package t.root nv in if OpamFilename.exists_dir dev && not (OpamPackage.Set.mem nv (OpamState.all_installed t)) then ( log "Removing %S" (OpamFilename.Dir.to_string dev); OpamFilename.rmdir dev; ) let remove_package t ~metadata ~rm_build ?silent nv = if not (!OpamGlobals.fake || !OpamGlobals.dryrun) then ( remove_package_aux t ~metadata ~rm_build ?silent nv ) else OpamGlobals.msg "(simulation) Removing %s.\n" (OpamPackage.to_string nv) (* Remove all the packages appearing in a solution (and which need to be removed, eg. because of a direct uninstall action or because of recompilation. *) let remove_all_packages t ~metadata sol = let deleted = ref [] in let delete nv = if !deleted = [] then OpamGlobals.header_msg "Removing Packages"; deleted := nv :: !deleted; try remove_package t ~rm_build:true ~metadata:false nv; with _ -> () in let action n = match n with | To_change (Some nv, _) | To_recompile nv | To_delete nv -> delete nv | To_change (None, _) -> () in List.iter delete PackageActionGraph.(sol.to_remove); PackageActionGraph.(Topological.iter action (mirror sol.to_process)); let deleted = OpamPackage.Set.of_list !deleted in if metadata then ( let installed = OpamPackage.Set.diff t.installed deleted in let installed_roots = OpamPackage.Set.diff t.installed_roots deleted in let reinstall = OpamPackage.Set.diff t.reinstall deleted in update_metadata t ~installed ~installed_roots ~reinstall; OpamState.remove_metadata t deleted; ); deleted (* Build and install a package. In case of error, simply return the error traces, and let the repo in a state that the user can explore. Do not try to recover yet. *) let build_and_install_package_aux t ~metadata nv = OpamGlobals.header_msg "Installing %s" (OpamPackage.to_string nv); let exec = try (* This one can raise an exception (for insance a user's CTRL-C when the sync takes too long. *) let p_build = extract_package t nv in (* For dev packages, we look for any opam file at the root of the build directory *) let opam = dev_opam t nv p_build in (* Get the env variables set up in the compiler description file *) let env = compilation_env t opam in (* Exec the given commands. *) let exec name f = match OpamState.filter_commands t OpamVariable.Map.empty (f opam) with | [] -> () | commands -> OpamGlobals.msg "%s:\n%s\n" name (string_of_commands commands); let name = OpamPackage.Name.to_string (OpamPackage.name nv) in let metadata = get_metadata t in OpamFilename.exec ~env ~name ~metadata p_build commands in exec with e -> raise (OpamGlobals.Package_error (Printf.sprintf "Could not get the source for %s:\n%s" (OpamPackage.to_string nv) (Printexc.to_string e))) in try (* First, we build the package. *) exec ("Building " ^ OpamPackage.to_string nv) OpamFile.OPAM.build; (* If necessary, build and run the test. *) if !OpamGlobals.build_test then exec "Building and running the test" OpamFile.OPAM.build_test; (* If necessary, build the documentation. *) if !OpamGlobals.build_doc then exec "Generating the documentation" OpamFile.OPAM.build_doc; (* If everyting went fine, finally install the package. *) install_package t nv; (* update the metadata *) if metadata then ( let installed = OpamPackage.Set.add nv t.installed in let installed_roots = OpamPackage.Set.add nv t.installed_roots in let reinstall = OpamPackage.Set.remove nv t.reinstall in update_metadata t ~installed ~installed_roots ~reinstall; OpamState.install_metadata t nv; ) with e -> let cause = match e with | Sys.Break -> "was aborted" | _ -> "failed" in (* We keep the build dir to help debugging *) OpamGlobals.error "The compilation of %s %s." (OpamPackage.to_string nv) cause; remove_package ~rm_build:false ~metadata:false t ~silent:true nv; raise e let build_and_install_package t ~metadata nv = if not !OpamGlobals.fake then build_and_install_package_aux t ~metadata nv else OpamGlobals.msg "(simulation) Building and installing %s.\n" (OpamPackage.to_string nv) opam-1.1.1/src/client/opamState.ml0000644000175000017500000023076312272210733015260 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) open OpamTypes open OpamMisc.OP open OpamFilename.OP let log fmt = OpamGlobals.log "STATE" fmt let () = OpamHTTP.register (); OpamGit.register (); OpamDarcs.register(); OpamLocal.register (); OpamHg.register () let confirm fmt = Printf.ksprintf (fun msg -> OpamGlobals.msg "%s [Y/n] %!" msg; if not !OpamGlobals.yes then match read_line () with | "y" | "Y" | "" -> true | _ -> false else true ) fmt let read fmt = Printf.ksprintf (fun msg -> OpamGlobals.msg "%s %!" msg; if not !OpamGlobals.yes then ( try match read_line () with | "" -> None | s -> Some s with _ -> OpamGlobals.msg "\n"; None ) else None ) fmt let switch_reinstall_hook = ref (fun _ -> assert false) module Types = struct type t = { partial: bool; root: OpamPath.t; switch: switch; compiler: compiler; compiler_version: compiler_version lazy_t; opams: OpamFile.OPAM.t package_map; repositories: OpamFile.Repo_config.t repository_name_map; packages: package_set; available_packages: package_set Lazy.t; aliases: OpamFile.Aliases.t; compilers: compiler_set; pinned: OpamFile.Pinned.t; installed: OpamFile.Installed.t; installed_roots: OpamFile.Installed_roots.t; reinstall: OpamFile.Reinstall.t; config: OpamFile.Config.t; package_index: OpamFile.Package_index.t; compiler_index: OpamFile.Compiler_index.t; } end type state = Types.t open Types let string_of_repositories r = OpamMisc.string_of_list OpamRepositoryName.to_string (OpamRepositoryName.Map.keys r) let print_state t = let packages = if OpamPackage.Set.cardinal t.packages <= 20 then OpamPackage.Set.to_string t.packages else Printf.sprintf "%d packages" (OpamPackage.Set.cardinal t.packages) in log "ROOT : %s" (OpamFilename.Dir.to_string t.root); log "SWITCH : %s" (OpamSwitch.to_string t.switch); log "COMPILER : %s" (OpamCompiler.to_string t.compiler); log "COMPILERS : %s" (OpamCompiler.Set.to_string t.compilers); log "REPOS : %s" (string_of_repositories t.repositories); log "PACKAGES : %s" packages; log "INSTALLED : %s" (OpamPackage.Set.to_string t.installed); log "ROOTS : %s" (OpamPackage.Set.to_string t.installed_roots); log "REINSTALL : %s" (OpamPackage.Set.to_string t.reinstall) let compiler_comp t c = OpamFile.Comp.read (OpamPath.compiler_comp t.root c) let is_name_installed_aux installed name = let set = OpamPackage.Set.filter (fun nv -> OpamPackage.name nv = name) installed in not (OpamPackage.Set.is_empty set) let is_name_installed t name = is_name_installed_aux t.installed name let find_installed_package_by_name_aux installed name = try OpamPackage.Set.find (fun nv -> OpamPackage.name nv = name) installed with Not_found -> OpamGlobals.error_and_exit "Package %s is not installed" (OpamPackage.Name.to_string name) let find_installed_package_by_name t name = find_installed_package_by_name_aux t.installed name let find_packages_by_name t name = let r = OpamPackage.Set.filter (fun nv -> OpamPackage.name nv = name) t.packages in if OpamPackage.Set.is_empty r then None else Some r let installed_map t = OpamPackage.Name.Map.map OpamPackage.Version.Set.choose_one (OpamPackage.to_map t.installed) let dot_config t nv = OpamFile.Dot_config.safe_read (OpamPath.Switch.config t.root t.switch nv) let is_package_installed t nv = OpamPackage.Set.mem nv t.installed let jobs t = match !OpamGlobals.jobs with | None -> OpamFile.Config.jobs t.config | Some j -> j (* filter handling *) let env_filter t local_variables v = let name = OpamVariable.Full.package v in let var = OpamVariable.Full.variable v in let var_str = OpamVariable.to_string var in let string str = Some (S str) in let bool b = Some (B b) in let int i = string (string_of_int i) in let dirname dir = string (OpamFilename.Dir.to_string dir) in let read_var name = let c = dot_config t name in try match OpamVariable.Full.section v with | None -> OpamFile.Dot_config.variable c var | Some s -> OpamFile.Dot_config.Section.variable c s var with Not_found -> OpamGlobals.error "%s is not defined" (OpamVariable.Full.to_string v); None in let local_var = try Some (OpamVariable.Map.find var local_variables) with Not_found -> None in if local_var <> None then local_var else if name = OpamPackage.Name.global_config then ( try match var_str with | "ocaml-version" -> string (OpamMisc.getenv "ocaml_version") | "opam-version" -> string (OpamMisc.getenv "opam_version") | _ -> string (OpamMisc.getenv var_str) with Not_found -> match var_str with | "ocaml-version" -> string (OpamCompiler.Version.to_string (Lazy.force t.compiler_version)) | "opam-version" -> string (OpamVersion.to_string OpamVersion.current) | "preinstalled" -> bool (OpamFile.Comp.preinstalled (compiler_comp t t.compiler)) | "switch" -> string (OpamSwitch.to_string t.switch) | "jobs" -> int (jobs t) | _ -> read_var name ) else ( let exists = find_packages_by_name t name <> None in let name_str = OpamPackage.Name.to_string name in if not exists then None else try let var_hook = Printf.sprintf "OPAM_%s_%s" name_str var_str in match OpamMisc.getenv var_hook with | "true" | "1" -> bool true | "false" | "0" -> bool false | s -> string s with Not_found -> let is_installed = is_name_installed t name in let no_section = OpamVariable.Full.section v = None in if var = OpamVariable.enable && is_installed && no_section then string "enable" else if var = OpamVariable.enable && not is_installed && no_section then string "disable" else if var = OpamVariable.installed && no_section then bool is_installed else if var = OpamVariable.installed || var = OpamVariable.enable then ( OpamGlobals.error "Syntax error: invalid section argument in '%s'.\nUse '%s:%s' instead." (OpamVariable.Full.to_string v) name_str (OpamVariable.to_string var); None ) else if var = OpamVariable.of_string "pinned" then bool (OpamPackage.Name.Map.mem name t.pinned) else if is_installed then ( match OpamVariable.to_string var with | "bin" -> dirname (OpamPath.Switch.bin t.root t.switch) | "sbin" -> dirname (OpamPath.Switch.sbin t.root t.switch) | "lib" -> dirname (OpamPath.Switch.lib t.root t.switch name) | "man" -> dirname (OpamPath.Switch.man_dir t.root t.switch) | "doc" -> dirname (OpamPath.Switch.doc t.root t.switch name) | "share" -> dirname (OpamPath.Switch.share t.root t.switch name) | "etc" -> dirname (OpamPath.Switch.etc t.root t.switch name) | "version" -> let nv = find_installed_package_by_name t name in string (OpamPackage.Version.to_string (OpamPackage.version nv)) | _ -> read_var name ) else None ) let eval_filter t local_variables = OpamFilter.eval_opt (env_filter t local_variables) let filter_commands t local_variables = OpamFilter.commands (env_filter t local_variables) let substitute_file t local_variables = OpamFilter.substitute_file (env_filter t local_variables) let substitute_string t local_variables = OpamFilter.substitute_string (env_filter t local_variables) let contents_of_variable t local_variables = OpamFilter.contents_of_variable (env_filter t local_variables) let contents_of_variable_exn t local_variables = OpamFilter.contents_of_variable_exn (env_filter t local_variables) let redirect t repo = if repo.repo_kind <> `http then None else let redirect = repo |> OpamPath.Repository.repo |> OpamFile.Repo.safe_read |> OpamFile.Repo.redirect in let redirect = List.fold_left (fun acc (redirect, filter) -> if eval_filter t OpamVariable.Map.empty filter then (redirect, filter) :: acc else acc ) [] redirect in match redirect with | [] -> None | (r,f) :: _ -> let config_f = OpamPath.Repository.config repo in let config = OpamFile.Repo_config.read config_f in let repo_address = address_of_string r in if repo_address <> config.repo_address then ( let config = { config with repo_address } in OpamFile.Repo_config.write config_f config; Some (config, f) ) else None let sorted_repositories t = OpamRepository.sort t.repositories let mem_repository t repo_name = OpamRepositoryName.Map.mem repo_name t.repositories let find_repository_aux repo_name repositories = try OpamRepositoryName.Map.find repo_name repositories with Not_found -> OpamGlobals.error_and_exit "%s is not a valid repository name." (OpamRepositoryName.to_string repo_name) let find_repository t repo_name = find_repository_aux repo_name t.repositories let find_repository_exn t repo_name = OpamRepositoryName.Map.find repo_name t.repositories let find_repository_opt t repo_name = try Some (find_repository_exn t repo_name) with Not_found -> None let compiler_index t = OpamRepository.compiler_index t.repositories let package_index t = OpamRepository.package_index t.repositories let package_state_one t all nv = let opam = OpamPath.opam t.root nv in let descr = OpamPath.descr t.root nv in let url = OpamPath.url t.root nv in let files = OpamPath.files t.root nv in let archive = OpamPath.archive t.root nv in if not (OpamFilename.exists opam) then [] else match all with | `all -> OpamFilename.checksum opam @ OpamFilename.checksum descr @ OpamRepository.url_checksum url @ OpamFilename.checksum_dir files @ OpamFilename.checksum archive | `partial true -> OpamRepository.url_checksum url @ OpamFilename.checksum_dir files @ OpamFilename.checksum archive | `partial false -> OpamRepository.url_checksum url @ OpamFilename.checksum_dir files let all_installed t = OpamSwitch.Map.fold (fun switch _ accu -> let installed_f = OpamPath.Switch.installed t.root switch in let installed = OpamFile.Installed.safe_read installed_f in OpamPackage.Set.union installed accu ) t.aliases OpamPackage.Set.empty let package_state t = let installed = OpamPackage.Set.fold (fun nv map -> let state = package_state_one t `all nv in OpamPackage.Map.add nv state map ) (all_installed t) OpamPackage.Map.empty in OpamPackage.Map.fold (fun nv (repo, prefix) map -> if OpamPackage.Map.mem nv map then map else if OpamFilename.exists (OpamPath.opam t.root nv) then let state = package_state_one t `all nv in OpamPackage.Map.add nv state map else let repo = find_repository_exn t repo in let state = OpamRepository.package_state repo prefix nv `all in OpamPackage.Map.add nv state map ) t.package_index installed let package_partial_state t nv ~archive = match package_state_one t (`partial archive) nv with | [] -> false, [] | state -> let archive = OpamPath.archive t.root nv in OpamFilename.exists archive, state let package_repository_state t = OpamPackage.Map.fold (fun nv (repo, prefix) map -> let repo = find_repository_exn t repo in match OpamRepository.package_state repo prefix nv `all with | [] -> map | state -> OpamPackage.Map.add nv state map ) t.package_index OpamPackage.Map.empty let package_repository_partial_state t nv ~archive = let repo, prefix = OpamPackage.Map.find nv t.package_index in let repo = find_repository_exn t repo in let exists_archive = OpamFilename.exists (OpamPath.Repository.archive repo nv) in exists_archive, OpamRepository.package_state repo prefix nv (`partial archive) let repository_and_prefix_of_package t nv = try let repo, prefix = OpamPackage.Map.find nv t.package_index in let repo = find_repository_exn t repo in Some (repo, prefix) with Not_found -> None let repository_of_package t nv = try let repo, _ = OpamPackage.Map.find nv t.package_index in let repo = OpamRepositoryName.Map.find repo t.repositories in Some repo with Not_found -> None let compiler_state_one t c = let comp = OpamPath.compiler_comp t.root c in let descr = OpamPath.compiler_descr t.root c in if OpamFilename.exists comp then Some (OpamFilename.checksum comp @ OpamFilename.checksum descr) else None let compiler_state t = OpamCompiler.Set.fold (fun c map -> match compiler_state_one t c with | None -> map | Some s -> OpamCompiler.Map.add c s map ) t.compilers OpamCompiler.Map.empty let compiler_repository_state t = OpamCompiler.Map.fold (fun comp (repo, prefix) map -> let repo = find_repository_exn t repo in match OpamRepository.compiler_state repo prefix comp with | [] -> map | l -> OpamCompiler.Map.add comp l map ) t.compiler_index OpamCompiler.Map.empty let repository_and_prefix_of_compiler t comp = try let repo, prefix = OpamCompiler.Map.find comp t.compiler_index in let repo = find_repository_exn t repo in Some (repo, prefix) with Not_found -> None let is_pinned t n = OpamPackage.Name.Map.mem n t.pinned (* is the current package locally pinned *) let is_locally_pinned t name = if OpamPackage.Name.Map.mem name t.pinned then match OpamPackage.Name.Map.find name t.pinned with | Edit | Unpin | Version _ -> false | _ -> true else false let locally_pinned_package t n = let option = OpamPackage.Name.Map.find n t.pinned in let path = string_of_pin_option option in match kind_of_pin_option option with | None -> OpamGlobals.error_and_exit "%s has a wrong pinning kind." (OpamPackage.Name.to_string n) | Some kind -> match repository_kind_of_pin_kind kind with | None -> OpamSystem.internal_error "locally pinned" | Some kind -> (address_of_string path, kind) let url_of_locally_pinned_package t n = let path, kind = locally_pinned_package t n in OpamFile.URL.create (Some kind) path let repository_of_locally_pinned_package t n = let url = url_of_locally_pinned_package t n in let repo_address = OpamFile.URL.url url in let repo_kind = guess_repository_kind (OpamFile.URL.kind url) repo_address in let repo_root = OpamPath.Switch.dev_package t.root t.switch (OpamPackage.pinned n) in { repo_name = OpamRepositoryName.of_string (OpamPackage.Name.to_string n); repo_priority = 0; repo_root; repo_address; repo_kind } let real_package t nv = let name = OpamPackage.name nv in if is_pinned t name then OpamPackage.pinned name else nv let opam_opt_no_pin t nv = let overlay = OpamPath.Switch.Overlay.opam t.root t.switch nv in if OpamFilename.exists overlay then Some (OpamFile.OPAM.read overlay) else try Some (OpamPackage.Map.find nv t.opams) with Not_found -> if OpamPackage.Set.mem nv t.installed then (* Work-around for installed packages with no more metadata *) Some (OpamFile.OPAM.create nv) else None let opam_no_pin t nv = match opam_opt_no_pin t nv with | None -> OpamPackage.unknown (OpamPackage.name nv) (Some (OpamPackage.version nv)) | Some nv -> nv let rec readn exists fn = function | [] -> None | h::t -> match h () with | None -> readn exists fn t | Some file -> if exists file then Some (fn file) else readn exists fn t let get_opt_no_pin overlay global repo exits read t nv = readn exits read [ (fun () -> Some (overlay t.root t.switch nv)); (fun () -> Some (global t.root nv)); (fun () -> try let r, prefix = OpamPackage.Map.find nv t.package_index in let r = find_repository_exn t r in Some (repo r prefix nv) with Not_found -> None) ] let descr_opt_no_pin = get_opt_no_pin OpamPath.Switch.Overlay.descr OpamPath.descr OpamPath.Repository.descr OpamFilename.exists OpamFile.Descr.read let descr_no_pin t nv = match descr_opt_no_pin t nv with | None -> OpamFile.Descr.empty | Some f -> f let url_no_pin = get_opt_no_pin OpamPath.Switch.Overlay.url OpamPath.url OpamPath.Repository.url OpamFilename.exists OpamFile.URL.read let files_no_pin = get_opt_no_pin OpamPath.Switch.Overlay.files OpamPath.files OpamPath.Repository.files OpamFilename.exists_dir (fun d -> d) let install_metadata t nv = if OpamFilename.exists (OpamPath.opam t.root nv) then () else let opam = opam_no_pin t nv in let descr = descr_opt_no_pin t nv in let url = url_no_pin t nv in let files = files_no_pin t nv in OpamFile.OPAM.write (OpamPath.opam t.root nv) opam; (match descr with | None -> () | Some d -> OpamFile.Descr.write (OpamPath.descr t.root nv) d); (match url with | None -> () | Some u -> OpamFile.URL.write (OpamPath.url t.root nv) u); (match files with | None -> () | Some d -> OpamFilename.copy_dir ~src:d ~dst:(OpamPath.files t.root nv)) let remove_metadata t packages = let all_installed = all_installed t in let packages = OpamPackage.Set.inter all_installed packages in OpamPackage.Set.iter (fun nv -> let dir = OpamPath.packages t.root nv in OpamFilename.rmdir dir; let archive = OpamPath.archive t.root nv in OpamFilename.remove archive; ) packages let overlay_of_name t name = let versions = OpamPackage.versions_of_name t.packages name in let versions = OpamPackage.Version.Set.filter ((<>) OpamPackage.Version.pinned) versions in let version = OpamPackage.Version.Set.max_elt versions in OpamPackage.create name version let add_opam_overlay t nv opam = let dst = OpamPath.Switch.Overlay.opam t.root t.switch nv in OpamFile.OPAM.write dst opam let add_url_overlay t nv url = let dst = OpamPath.Switch.Overlay.url t.root t.switch nv in OpamFile.URL.write dst url let add_descr_overlay t nv descr = let dst = OpamPath.Switch.Overlay.descr t.root t.switch nv in OpamFile.Descr.write dst descr let add_files_overlay t nv root files = let dst = OpamPath.Switch.Overlay.files t.root t.switch nv in List.iter (fun file -> let base = OpamFilename.remove_prefix root file in OpamFilename.copy ~src:file ~dst:(dst // base) ) files let add_pinned_overlay t name = let nv = OpamPackage.pinned name in let local_pin, rv = match OpamPackage.Name.Map.find name t.pinned with | Version v -> false, OpamPackage.create name v | _ -> true , overlay_of_name t name in let opam_f = if local_pin then let path, _ = locally_pinned_package t name in let dir = OpamFilename.raw_dir (fst path) in let dir = if OpamFilename.exists_dir (dir / "opam") then dir / "opam" else dir in let local_opam = dir // "opam" in if OpamFilename.exists local_opam then let opam = OpamFile.OPAM.read local_opam in let opam = OpamFile.OPAM.with_name opam name in OpamFile.OPAM.with_version opam (OpamPackage.version rv) else opam_no_pin t rv else opam_no_pin t rv in let descr_f = descr_opt_no_pin t rv in let url_f = if local_pin then Some (url_of_locally_pinned_package t name) else url_no_pin t rv in let files_f = files_no_pin t rv in log "opam: %s" (OpamPackage.Version.to_string (OpamFile.OPAM.version opam_f)); add_opam_overlay t nv opam_f; (match descr_f with | None -> () | Some d -> add_descr_overlay t nv d); (match url_f with | None -> () | Some u -> add_url_overlay t nv u); (match files_f with | None -> () | Some d -> add_files_overlay t nv d (OpamFilename.files d)) let remove_overlay t nv = OpamFilename.rmdir (OpamPath.Switch.Overlay.package t.root t.switch nv) let has_url_overlay t nv = OpamFilename.exists (OpamPath.Switch.Overlay.url t.root t.switch nv) let dev_package t nv = if has_url_overlay t nv then OpamPath.Switch.dev_package t.root t.switch nv else OpamPath.dev_package t.root nv let pinning_version t nv = let name = OpamPackage.name nv in try match OpamPackage.Name.Map.find name t.pinned with | Version v -> OpamPackage.create name v | _ -> let nv1 = OpamPackage.pinned name in let overlay = OpamPath.Switch.Overlay.opam t.root t.switch nv1 in if not (OpamFilename.exists overlay) then add_pinned_overlay t name; let opam = OpamFile.OPAM.read overlay in if OpamFile.OPAM.version opam = OpamPackage.Version.pinned then (OpamGlobals.warning "Package %s is pinned locally but with unspecified version:\n\ is your OPAM directory up-to-date ? Please try running \ 'mkdir ~/.opam/opam && opam list'." (OpamPackage.Name.to_string name); nv) else OpamPackage.create name (OpamFile.OPAM.version opam) with Not_found -> nv let opam_opt t nv = opam_opt_no_pin t (real_package t nv) let opam t nv = opam_no_pin t (real_package t nv) let descr_opt t nv = descr_opt_no_pin t (real_package t nv) let descr t nv = descr_no_pin t (real_package t nv) let url t nv = url_no_pin t (real_package t nv) let files t nv = files_no_pin t (real_package t nv) let copy_files t nv dst = match files t nv with | None -> () | Some src -> OpamFilename.copy_files ~src ~dst (* List the packages which do fulfil the compiler and OS constraints *) let available_packages t system = let env = env_filter t OpamVariable.Map.empty in let filter nv = match opam_opt t nv with | None -> false | Some opam -> let consistent_ocaml_version () = let atom (r,v) = match OpamCompiler.Version.to_string v with | "system" -> begin match r with | `Eq -> system | `Neq -> not system | _ -> OpamSystem.internal_error "%s is not a valid constraint for the system compiler \ (only '=' and '!=' are valid)." (OpamFormula.string_of_relop r) end | _ -> OpamCompiler.Version.eval_relop r (Lazy.force t.compiler_version) v in match OpamFile.OPAM.ocaml_version opam with | None -> true | Some c -> OpamFormula.eval atom c in let consistent_os () = match OpamFile.OPAM.os opam with | Empty -> true | f -> let atom (b, os) = let ($) = if b then (=) else (<>) in os $ OpamGlobals.os_string () in OpamFormula.eval atom f in let has_reposiotry () = OpamPackage.Map.mem nv t.package_index in let available () = OpamFilter.eval env (OpamFile.OPAM.available opam) in consistent_ocaml_version () && consistent_os () && available () && has_reposiotry () in let _pinned, set = OpamPackage.Map.fold (fun nv _ (pinned, set) -> if OpamPackage.Name.Set.mem (OpamPackage.name nv) pinned then (* Package has already been added to the set *) (pinned, set) else let nv1 = pinning_version t nv in let pinned = if nv1 != nv then OpamPackage.Name.Set.add (OpamPackage.name nv1) pinned else pinned in if filter nv1 then pinned, OpamPackage.Set.add nv1 set else pinned, set ) t.opams (OpamPackage.Name.Set.empty, OpamPackage.Set.empty) in set let base_packages = List.map OpamPackage.Name.of_string [ "base-unix"; "base-bigarray"; "base-threads" ] let create_system_compiler_description root = function | None -> () | Some version -> log "create-system-compiler-description %s" (OpamCompiler.Version.to_string version); match Lazy.force OpamSystem.system_ocamlc_where with | None -> () | Some dir -> let comp = OpamPath.compiler_comp root OpamCompiler.system in OpamFilename.remove comp; let f = OpamFile.Comp.create_preinstalled OpamCompiler.system version (if not !OpamGlobals.no_base_packages then base_packages else []) [ "CAML_LD_LIBRARY_PATH", "=", "%{lib}%/stublibs" ^ ":" ^ Filename.concat dir "stublibs" ] in OpamFile.Comp.write comp f let system_needs_upgrade_displayed = ref false let system_needs_upgrade t = t.compiler = OpamCompiler.system && match OpamCompiler.Version.system () with | None -> if not !system_needs_upgrade_displayed then ( system_needs_upgrade_displayed := true; OpamGlobals.error "You current switch use the system compiler, but no OCaml compiler \ has been found in the current path.\n\ You should either:\n\ \ (i) reinstall OCaml version %s on your system; or\n\ \ (ii) use a working compiler switch." (OpamCompiler.Version.to_string (Lazy.force t.compiler_version)) ); false | Some v -> OpamFilename.exists (OpamPath.compiler_comp t.root t.compiler) && (Lazy.force t.compiler_version) <> v let read_repositories root config = let names = OpamFile.Config.repositories config in List.fold_left (fun map repo_name -> let repo = OpamFile.Repo_config.read (OpamPath.Repository.raw_config root repo_name) in OpamRepositoryName.Map.add repo_name repo map ) OpamRepositoryName.Map.empty names (* load partial state to be able to read env variables *) let load_env_state call_site = log "LOAD-ENV-STATE(%s)" call_site; let root = OpamPath.root () in let config_p = OpamPath.config root in let config = OpamFile.Config.read config_p in let switch = match !OpamGlobals.switch with | `Command_line s | `Env s -> OpamSwitch.of_string s | `Not_set -> OpamFile.Config.switch config in let aliases = OpamFile.Aliases.safe_read (OpamPath.aliases root) in let compiler = try OpamSwitch.Map.find switch aliases with Not_found -> OpamGlobals.error_and_exit "The current switch (%s) is an unknown compiler switch." (OpamSwitch.to_string switch) in let partial = true in (* evertything else is empty *) let compilers = OpamCompiler.Set.empty in let repositories = OpamRepositoryName.Map.empty in let compiler_version = lazy (OpamCompiler.Version.of_string "none") in let opams = OpamPackage.Map.empty in let packages = OpamPackage.Set.empty in let available_packages = lazy OpamPackage.Set.empty in let installed = OpamPackage.Set.empty in let installed_roots = OpamPackage.Set.empty in let reinstall = OpamPackage.Set.empty in let pinned = OpamPackage.Name.Map.empty in let package_index = OpamPackage.Map.empty in let compiler_index = OpamCompiler.Map.empty in { partial; root; switch; compiler; compiler_version; repositories; opams; packages; available_packages; installed; installed_roots; reinstall; config; aliases; pinned; compilers; package_index; compiler_index; } let get_compiler_packages t comp = let comp = compiler_comp t comp in let available = OpamPackage.to_map (Lazy.force t.available_packages) in if OpamPackage.Name.Map.is_empty available then [] else ( let pkg_available, pkg_not = List.partition (fun (n, _) -> OpamPackage.Name.Map.mem n available) (OpamFormula.atoms (OpamFile.Comp.packages comp)) in (* check that all packages in [comp] are in [available] except for "base-..." (depending if "-no-base-packages" is set or not) *) let pkg_not = List.rev_map (function (n, _) -> n) pkg_not in let pkg_not = if not !OpamGlobals.no_base_packages then pkg_not else List.filter (fun n -> not (List.mem n base_packages)) pkg_not in if pkg_not <> [] then ( List.iter (OpamPackage.Name.to_string ++ OpamGlobals.error "Package %s not found") pkg_not; OpamGlobals.exit 1 ); pkg_available ) let is_compiler_installed t comp = OpamSwitch.Map.exists (fun _ c -> c = comp) t.aliases let is_switch_installed t switch = OpamSwitch.Map.mem switch t.aliases let universe t action = let opams = OpamPackage.Map.mapi (fun nv opam -> let overlay = OpamPath.Switch.Overlay.opam t.root t.switch nv in if OpamFilename.exists overlay then OpamFile.OPAM.read overlay else opam) t.opams in { u_packages = OpamPackage.Set.union t.installed t.packages; u_action = action; u_installed = t.installed; u_available = Lazy.force t.available_packages; u_depends = OpamPackage.Map.map OpamFile.OPAM.depends opams; u_depopts = OpamPackage.Map.map OpamFile.OPAM.depopts opams; u_conflicts = OpamPackage.Map.map OpamFile.OPAM.conflicts opams; u_installed_roots = t.installed_roots; u_pinned = OpamPackage.Name.Map.fold (fun k _ set -> let v = lazy (OpamPackage.version (pinning_version t (OpamPackage.pinned k))) in OpamPackage.Name.Map.add k v set) t.pinned OpamPackage.Name.Map.empty; } let check_base_packages t = let base_packages = get_compiler_packages t t.compiler in let missing_packages = List.filter (fun (name,_) -> not (is_name_installed t name)) base_packages in if missing_packages <> [] then ( let names = List.map (fst ++ OpamPackage.Name.to_string) missing_packages in OpamGlobals.warning "Some of the compiler base packages are not installed. \ You should run:\n\n $ opam install %s\n" (String.concat " " names) ) let installed_versions t name = OpamSwitch.Map.fold (fun switch _ map -> let installed = OpamFile.Installed.safe_read (OpamPath.Switch.installed t.root switch) in if is_name_installed_aux installed name then let nv = find_installed_package_by_name_aux installed name in if OpamPackage.Map.mem nv map then let aliases = OpamPackage.Map.find nv map in let map = OpamPackage.Map.remove nv map in OpamPackage.Map.add nv (switch :: aliases) map else OpamPackage.Map.add nv [switch] map else map ) t.aliases OpamPackage.Map.empty (* Checks: * correct opam version * only installed packages have something in $repo/tmp * only installed packages have something in $opam/pinned.cache *) let clean_dir dir nv = if OpamFilename.exists_dir dir then ( OpamGlobals.note "%s exists although %s is not installed. Removing it." (OpamFilename.Dir.to_string dir) (OpamPackage.to_string nv); OpamFilename.rmdir dir ) let clean_file file nv = if OpamFilename.exists file then ( OpamGlobals.note "%s exists although %s is not installed. Removing it." (OpamFilename.to_string file) (OpamPackage.to_string nv); OpamFilename.remove file ) let dev_packages_of_dir dir = let dirs = OpamFilename.dirs dir in List.fold_left (fun map dir -> match OpamPackage.of_dirname dir with | None -> OpamGlobals.error "Removing %s.\n" (OpamFilename.Dir.to_string dir); OpamFilename.rmdir dir; map | Some nv -> OpamPackage.Map.add nv dir map ) OpamPackage.Map.empty dirs let global_dev_packages t = dev_packages_of_dir (OpamPath.dev_packages_dir t.root) let switch_dev_packages t = dev_packages_of_dir (OpamPath.Switch.dev_packages_dir t.root t.switch) let keys map = OpamPackage.Map.fold (fun nv _ set -> OpamPackage.Set.add nv set ) map OpamPackage.Set.empty (* Check that the dev packages are installed -- if not, just remove the tempory files. *) let consistency_checks dir pinned installed all_installed = let dev_packages = dev_packages_of_dir dir in OpamPackage.Map.iter (fun nv dir -> let name = OpamPackage.name nv in if OpamPackage.is_pinned nv then ( if not (OpamPackage.Name.Map.mem name pinned) || OpamPackage.Set.for_all (fun nv -> OpamPackage.name nv <> name) installed then clean_dir dir nv ) else if not (OpamPackage.Set.mem nv all_installed) then clean_dir dir nv ) dev_packages; let files = OpamFilename.files dir in List.iter (fun f -> OpamGlobals.error "Removing %s.\n" (OpamFilename.to_string f); OpamFilename.remove f; ) files let is_dev_package t nv = match url t nv with | None -> false | Some url -> match guess_repository_kind (OpamFile.URL.kind url) (OpamFile.URL.url url) with | `http -> false | _ -> true let dev_packages t = let global = global_dev_packages t in let switch = switch_dev_packages t in let all = OpamPackage.Set.union (keys global) (keys switch) in OpamPackage.Set.filter (is_dev_package t) all let global_consistency_checks t = consistency_checks (OpamPath.dev_packages_dir t.root) t.pinned t.installed (all_installed t); let aliases = OpamFile.Aliases.safe_read (OpamPath.aliases t.root) in if OpamSwitch.Map.exists (fun _ c -> c = OpamCompiler.system) aliases then let comp_f = OpamPath.compiler_comp t.root OpamCompiler.system in if not (OpamFilename.exists comp_f) then ( OpamGlobals.msg "Regenerating the system compiler description.\n"; create_system_compiler_description t.root (OpamCompiler.Version.system ()); ) let switch_consistency_checks t = consistency_checks (OpamPath.Switch.dev_packages_dir t.root t.switch) t.pinned t.installed t.installed type cache = { cached_opams: OpamFile.OPAM.t OpamPackage.Map.t; } let check_marshaled_file file = let ic = open_in_bin (OpamFilename.to_string file) in let magic_len = String.length OpamVersion.magic in let magic = String.create magic_len in really_input ic magic 0 magic_len; if magic <> OpamVersion.magic then ( close_in ic; OpamSystem.internal_error "Wrong magic string in the cache (actual:%s expected:%s)." magic OpamVersion.magic; ); let header = String.create Marshal.header_size in really_input ic header 0 Marshal.header_size; let expected_size = magic_len + Marshal.total_size header 0 in let current_size = in_channel_length ic in if not (expected_size = current_size) then ( close_in ic; OpamGlobals.error "The local-state cache is corrupted, removing it."; OpamSystem.internal_error "Corrupted cache"; ); seek_in ic magic_len; ic let marshal_from_file file = try let chrono = OpamGlobals.timer () in let ic = check_marshaled_file file in let (cache: cache) = Marshal.from_channel ic in close_in ic; log "Loaded %s in %.3fs" (OpamFilename.to_string file) (chrono ()); Some cache.cached_opams with e -> log "Got an error while loading the cache: %s" (Printexc.to_string e); OpamFilename.remove file; None let save_state ~update t = let chrono = OpamGlobals.timer () in let file = OpamPath.state_cache t.root in OpamFilename.remove file; if update then ( OpamGlobals.msg "Updating the cache of metadata (%s) ...\n" (OpamFilename.prettify file); ) else OpamGlobals.msg "Creating a cache of metadata in %s ...\n" (OpamFilename.prettify file); let oc = open_out_bin (OpamFilename.to_string file) in output_string oc OpamVersion.magic; Marshal.to_channel oc { cached_opams = t.opams } [Marshal.No_sharing]; close_out oc; log "%s written in %.3fs" (OpamFilename.prettify file) (chrono ()) let remove_state_cache () = let root = OpamPath.root () in let file = OpamPath.state_cache root in OpamFilename.remove file let reinstall_system_compiler t = log "reinstall-system-compiler"; let continue = confirm "Your system compiler has been upgraded. Do you want to upgrade \ your OPAM installation?" in if continue then ( (* Update system.comp *) create_system_compiler_description t.root (OpamCompiler.Version.system ()); (* Reinstall all system compiler switches *) OpamSwitch.Map.iter (fun s a -> if a = OpamCompiler.system then ( OpamGlobals.msg "\n=o=o=o= Upgrading %s =o=o=o=\n" (OpamSwitch.to_string s); !switch_reinstall_hook s ) ) t.aliases ) else OpamGlobals.exit 1 let upgrade_to_1_1_hook = ref (fun () -> assert false) let load_state ?(save_cache=true) call_site = log "LOAD-STATE(%s)" call_site; let chrono = OpamGlobals.timer () in !upgrade_to_1_1_hook (); let root = OpamPath.root () in let config_p = OpamPath.config root in let config = let config = OpamFile.Config.read config_p in if OpamFile.Config.opam_version config <> OpamVersion.current then ( (* opam has been updated, so refresh the configuration file and clean-up the cache. *) let config = OpamFile.Config.with_current_opam_version config in OpamFile.Config.write config_p config; remove_state_cache (); config ) else config in let opams = let file = OpamPath.state_cache root in if OpamFilename.exists file then marshal_from_file file else None in let cached = opams <> None in let partial = false in let switch = match !OpamGlobals.switch with | `Command_line s | `Env s -> OpamSwitch.of_string s | `Not_set -> OpamFile.Config.switch config in let aliases = OpamFile.Aliases.safe_read (OpamPath.aliases root) in let compilers = let files = OpamFilename.rec_files (OpamPath.compilers_dir root) in let files = List.fold_left (fun acc file -> if OpamFilename.exists file then file :: acc else acc ) [] files in let comp = OpamMisc.filter_map OpamCompiler.of_filename files in OpamCompiler.Set.of_list comp in let switch, compiler = try switch, OpamSwitch.Map.find switch aliases with Not_found -> log "%S does not contain the compiler name associated to the switch %s" (OpamFilename.to_string (OpamPath.aliases root)) (OpamSwitch.to_string switch); match !OpamGlobals.switch with | `Command_line s | `Env s -> OpamSwitch.not_installed (OpamSwitch.of_string s) | `Not_set -> if OpamSwitch.Map.cardinal aliases > 0 then ( let new_switch, new_compiler = OpamSwitch.Map.choose aliases in OpamGlobals.error "The current switch (%s) is an unknown compiler \ switch. Switching back to %s ..." (OpamSwitch.to_string switch) (OpamSwitch.to_string new_switch); let config = OpamFile.Config.with_switch config new_switch in OpamFile.Config.write config_p config; new_switch, new_compiler; ) else OpamGlobals.error_and_exit "The current switch (%s) is an unknown compiler switch." (OpamSwitch.to_string switch) in let compiler_version = lazy ( let comp_f = OpamPath.compiler_comp root compiler in (* XXX: useful for upgrade to 1.1 *) if compiler = OpamCompiler.system && not (OpamFilename.exists comp_f) then create_system_compiler_description root (OpamCompiler.Version.system ()); if not (OpamFilename.exists comp_f) then OpamCompiler.unknown compiler else OpamFile.Comp.version (OpamFile.Comp.read comp_f) ) in let repositories = read_repositories root config in let package_index = OpamFile.Package_index.safe_read (OpamPath.package_index root) in let compiler_index = OpamFile.Compiler_index.safe_read (OpamPath.compiler_index root) in let opams = match opams with | None -> let packages = OpamPackage.Set.union (OpamFile.Installed.safe_read (OpamPath.Switch.installed root switch)) (OpamPackage.Set.of_list (OpamPackage.Map.keys package_index)) in OpamPackage.Set.fold (fun nv map -> try if OpamPackage.is_pinned nv then map else let file = let f1 = OpamPath.opam root nv in if OpamFilename.exists f1 then f1 else let repo, prefix = OpamPackage.Map.find nv package_index in let repo = OpamRepositoryName.Map.find repo repositories in OpamPath.Repository.opam repo prefix nv in let opam = OpamFile.OPAM.read file in OpamPackage.Map.add nv opam map with | Not_found -> OpamGlobals.warning "Cannot find an OPAM file for %s, skipping." (OpamPackage.to_string nv); map | Parsing.Parse_error | OpamSystem.Internal_error _ -> OpamGlobals.warning "Errors while parsing %s OPAM file, skipping." (OpamPackage.to_string nv); map ) packages OpamPackage.Map.empty | Some o -> o in let pinned = OpamFile.Pinned.safe_read (OpamPath.Switch.pinned root switch) in let installed = OpamFile.Installed.safe_read (OpamPath.Switch.installed root switch) in let installed_roots = OpamFile.Installed_roots.safe_read (OpamPath.Switch.installed_roots root switch) in let packages = OpamPackage.Name.Map.fold (fun name _ -> OpamPackage.Set.add (OpamPackage.pinned name)) pinned (OpamPackage.Set.of_list (OpamPackage.Map.keys opams)) in let reinstall = OpamFile.Reinstall.safe_read (OpamPath.Switch.reinstall root switch) in let system = (compiler = OpamCompiler.system) in let available_packages_stub = lazy OpamPackage.Set.empty in let t = { partial; root; switch; compiler; compiler_version; repositories; opams; packages; installed; installed_roots; reinstall; config; aliases; pinned; compilers; package_index; compiler_index; available_packages = available_packages_stub } in let t = { t with available_packages = lazy (available_packages t system) } in print_state t; if save_cache && not cached then save_state ~update:false t; let load_time = chrono () in log "State %s loaded in %.3fs" call_site load_time; (* Check whether the system compiler has been updated *) if system_needs_upgrade t then ( reinstall_system_compiler t; OpamGlobals.exit 0 ) else t (* install ~/.opam/switches//config/global-conf.config *) let install_global_config root switch = log "install_global_config switch=%s" (OpamSwitch.to_string switch); (* .config *) let vars = let map f l = List.rev_map (fun (s,p) -> OpamVariable.of_string s, S (f p)) l in let id x = x in map OpamFilename.Dir.to_string [ ("root", root); ("prefix", OpamPath.Switch.root root switch); ("lib", OpamPath.Switch.lib_dir root switch); ("bin", OpamPath.Switch.bin root switch); ("sbin", OpamPath.Switch.sbin root switch); ("doc", OpamPath.Switch.doc_dir root switch); ("stublibs", OpamPath.Switch.stublibs root switch); ("toplevel", OpamPath.Switch.toplevel root switch); ("man", OpamPath.Switch.man_dir root switch); ("share", OpamPath.Switch.share_dir root switch); ("etc", OpamPath.Switch.etc_dir root switch); ] @ map id [ ("user" , try (Unix.getpwuid (Unix.getuid ())).Unix.pw_name with _ -> "user"); ("group", try (Unix.getgrgid (Unix.getgid ())).Unix.gr_name with _ -> "group"); ("make" , !OpamGlobals.makecmd ()); ("os" , OpamGlobals.os_string ()); ] in let config = OpamFile.Dot_config.create vars in OpamFile.Dot_config.write (OpamPath.Switch.config root switch OpamPackage.Name.global_config) config let fix_descriptions_hook = ref (fun ?save_cache:_ _ ~verbose:_ -> assert false) (* Upgrade to the new file overlay *) let upgrade_to_1_1 () = let root = OpamPath.root () in let opam = root / "opam" in let opam_tmp = root / "opam_tmp" in let descr = root / "descr" in let compilers = root / "compilers" in let repo_index = root / "repo" // "index" in if OpamFilename.exists_dir opam || OpamFilename.exists repo_index then ( let cwd = OpamFilename.cwd () in let () = OpamSystem.chdir OpamGlobals.home in OpamGlobals.header_msg "Upgrading to OPAM 1.1 %s" (OpamGlobals.colorise `red "[DO NOT INTERRUPT THE PROCESS]"); OpamGlobals.msg "\n\ \ In case something goes wrong, you can run that upgrade\n\ \ process again by doing:\n\ \n\ \ mkdir %s/opam && opam list\n\ \n\ ** Processing **\n" (OpamFilename.prettify_dir (OpamPath.root ())); if OpamFilename.exists_dir opam then OpamFilename.move_dir ~src:opam ~dst:opam_tmp; OpamFilename.rmdir descr; if OpamFilename.exists_dir (OpamPath.packages_dir root) then OpamFilename.rmdir (OpamPath.packages_dir root); (* Remove the cache. *) if OpamFilename.exists (OpamPath.state_cache root) then OpamFilename.remove (OpamPath.state_cache root); (* Remove the index files *) OpamFilename.remove (OpamPath.root () / "repo" // "index"); OpamFilename.remove (OpamPath.root () / "repo" // "index.packages"); OpamFilename.remove (OpamPath.root () / "repo" // "index.compilers"); (* fix the base config files *) let aliases = OpamFile.Aliases.safe_read (OpamPath.aliases root) in OpamSwitch.Map.iter (fun switch _ -> install_global_config root switch ) aliases; OpamFilename.with_tmp_dir (fun tmp_dir -> let keep_compilers = OpamCompiler.Set.of_list (OpamSwitch.Map.values aliases) in (* Fix system.comp *) let backups = OpamCompiler.Set.fold (fun compname backups -> let comp = root / "compilers" // (OpamCompiler.to_string compname ^ ".comp") in if OpamFilename.exists comp then ( let tmp_file = OpamFilename.create tmp_dir (OpamFilename.basename comp) in log "backing up %s to %s" (OpamFilename.to_string comp) (OpamFilename.to_string tmp_file); OpamFilename.move ~src:comp ~dst:tmp_file; (compname,tmp_file) :: backups ) else backups ) keep_compilers [] in OpamFilename.rmdir compilers; List.iter (fun (compname,tmp_file) -> log "restoring %s" (OpamFilename.to_string tmp_file); let comp = OpamPath.compiler_comp root compname in OpamFilename.mkdir (OpamFilename.dirname comp); OpamFilename.move ~src:tmp_file ~dst:comp ) backups; if not (OpamFilename.exists (OpamPath.compiler_comp root OpamCompiler.system)) then create_system_compiler_description root (OpamCompiler.Version.system ()) ); (* Remove pinned cache *) OpamSwitch.Map.iter (fun switch _ -> let pinned_cache = OpamPath.Switch.root root switch / "pinned.cache" in if OpamFilename.exists_dir pinned_cache then ( OpamGlobals.msg "Removing the cache of pinned packages for the switch %s ...\n" (OpamSwitch.to_string switch); OpamFilename.rmdir pinned_cache; ) ) aliases; (* Fix all the descriptions *) let t = load_state ~save_cache:false "update-to-1.1." in !fix_descriptions_hook t ~verbose:false; (* Fix the pinned packages *) OpamSwitch.Map.iter (fun switch _ -> let pinned = OpamFile.Pinned.safe_read (OpamPath.Switch.pinned root switch) in OpamPackage.Name.Map.iter (fun name _ -> let t = { t with switch } in if is_pinned t name then ( let nv = OpamPackage.pinned name in OpamFilename.rmdir (OpamPath.Switch.Overlay.package root switch nv); add_pinned_overlay t name; ) ) pinned ) aliases; (* Workaround to add back packages without repositories *) List.iter (fun file -> let nv = file |> OpamFilename.chop_extension |> OpamFilename.basename |> OpamFilename.Base.to_string |> OpamPackage.of_string in let dst = OpamPath.opam root nv in if not (OpamFilename.exists dst) then OpamFilename.copy ~src:file ~dst ) (OpamFilename.files opam_tmp); OpamFilename.rmdir opam_tmp; let () = try OpamSystem.chdir (OpamFilename.Dir.to_string cwd) with OpamSystem.Internal_error _ -> () in OpamGlobals.header_msg "Upgrade complete. Now continuing with \"%s\"" (String.concat " " (Array.to_list Sys.argv)); OpamGlobals.msg "\n"; ) let () = upgrade_to_1_1_hook := upgrade_to_1_1 let rebuild_state_cache () = remove_state_cache (); let t = load_state ~save_cache:false "rebuild-cache" in save_state ~update:true t let switch_eval_sh = "switch_eval.sh" let complete_sh = "complete.sh" let complete_zsh = "complete.zsh" let variables_sh = "variables.sh" let variables_csh = "variables.csh" let init_sh = "init.sh" let init_zsh = "init.zsh" let init_csh = "init.csh" let init_fish = "init.fish" let init_file = function | `sh -> init_sh | `csh -> init_csh | `zsh -> init_zsh | `bash -> init_sh | `fish -> init_fish let source t ?(interactive_only=false) f = let file f = OpamFilename.to_string (OpamPath.init t.root // f) in let s = Printf.sprintf ". %s > /dev/null 2> /dev/null || true\n" (file f) in if interactive_only then Printf.sprintf "if tty -s >/dev/null 2>&1; then\n %sfi\n" s else s let expand_env t (env: env_updates) : env = let fenv = env_filter t OpamVariable.Map.empty in List.rev_map (fun (ident, symbol, string) -> let string = OpamFilter.substitute_string fenv string in let read_env () = let prefix = OpamFilename.Dir.to_string t.root in try OpamMisc.reset_env_value ~prefix (OpamMisc.getenv ident) with _ -> [] in let cons ~head a b = let c = List.filter ((<>)"") b in match b with | [] -> if head then [ ""; a ] else [ a; "" ] | "" :: _ -> "" :: a :: c | _ -> match List.rev b with | "" :: _ -> (a :: c) @ [""] | _ -> a :: c in match symbol with | "=" -> (ident, string) | "+=" -> (ident, String.concat ":" (string :: read_env ())) | "=+" -> (ident, String.concat ":" (read_env () @ [string])) | ":=" -> (ident, String.concat ":" (cons ~head:true string (read_env()))) | "=:" -> (ident, String.concat ":" (cons ~head:false string (read_env()))) | _ -> failwith (Printf.sprintf "expand_env: %s is an unknown symbol" symbol) ) env let add_to_env t (env: env) (updates: env_updates) = let env = List.filter (fun (k,_) -> List.for_all (fun (u,_,_) -> u <> k) updates) env in env @ expand_env t updates let env_updates ~opamswitch t = let comp = compiler_comp t t.compiler in let add_to_path = OpamPath.Switch.bin t.root t.switch in let new_path = "PATH", "+=", OpamFilename.Dir.to_string add_to_path in let perl5 = OpamPackage.Name.of_string "perl5" in let add_to_perl5lib = OpamPath.Switch.lib t.root t.switch perl5 in let new_perl5lib = "PERL5LIB", "+=", OpamFilename.Dir.to_string add_to_perl5lib in let toplevel_dir = "OCAML_TOPLEVEL_PATH", "=", OpamFilename.Dir.to_string (OpamPath.Switch.toplevel t.root t.switch) in let man_path = "MANPATH", "=:", OpamFilename.Dir.to_string (OpamPath.Switch.man_dir t.root t.switch) in let comp_env = OpamFile.Comp.env comp in let switch = if not opamswitch then [] else match !OpamGlobals.switch with | `Command_line s -> [ "OPAMSWITCH", "=", s ] | `Env _ | `Not_set -> [] in let root = if !OpamGlobals.root_dir <> OpamGlobals.default_opam_dir then [ "OPAMROOT", "=", !OpamGlobals.root_dir ] else [] in new_path :: man_path :: toplevel_dir :: new_perl5lib :: (switch @ root @ comp_env) (* This function is used by 'opam config env' and 'opam switch' to display the environment variables. We have to make sure that OPAMSWITCH is always the one being reported in '~/.opam/config' otherwise we can have very weird results (as the inability to switch between compilers). Note: when we do the later command with --switch=SWITCH, this mean we really want to get the environment for this switch. *) let get_opam_env t = let t = match !OpamGlobals.switch with | `Command_line _ | `Not_set -> t | `Env _ -> { t with switch = OpamFile.Config.switch t.config } in add_to_env t [] (env_updates ~opamswitch:true t) let get_full_env t = let env0 = OpamMisc.env () in add_to_env t env0 (env_updates ~opamswitch:true t) let mem_pattern_in_string ~pattern ~string = let pattern = Re.compile (Re.str pattern) in Re.execp pattern string let ocamlinit () = try let file = Filename.concat (OpamMisc.getenv "HOME") ".ocamlinit" in Some (OpamFilename.of_string file) with _ -> None let ocamlinit_needs_update () = match ocamlinit () with | None -> true | Some file -> if OpamFilename.exists file then ( let body = OpamFilename.read file in let pattern = "OCAML_TOPLEVEL_PATH" in not (mem_pattern_in_string ~pattern ~string:body) ) else true let update_ocamlinit () = if ocamlinit_needs_update () then ( match ocamlinit () with | None -> () | Some file -> let body = if not (OpamFilename.exists file) then "" else OpamFilename.read file in if body = "" then OpamGlobals.msg " Generating ~/.ocamlinit.\n" else OpamGlobals.msg " Updating ~/.ocamlinit.\n"; try let header = "(* Added by OPAM. *)\n\ let () =\n\ \ try Topdirs.dir_directory (Sys.getenv \"OCAML_TOPLEVEL_PATH\")\n\ \ with Not_found -> ()\n\ ;;\n\n" in let oc = open_out_bin (OpamFilename.to_string file) in output_string oc (header ^ body); close_out oc; with _ -> OpamSystem.internal_error "Cannot write ~/.ocamlinit." ) else OpamGlobals.msg " ~/.ocamlinit is already up-to-date.\n" let string_of_env_update t shell updates = let fenv = env_filter t OpamVariable.Map.empty in let sh (k,v) = Printf.sprintf "%s=%s; export %s;\n" k v k in let csh (k,v) = Printf.sprintf "setenv %s %S;\n" k v in let export = match shell with | `zsh | `sh -> sh | `csh -> csh in let aux (ident, symbol, string) = let string = OpamFilter.substitute_string fenv string in let key, value = match symbol with | "=" -> (ident, string) | "+=" | ":=" -> (ident, Printf.sprintf "%s:$%s" string ident) | "=:" | "=+" -> (ident, Printf.sprintf "$%s:%s" ident string) | _ -> failwith (Printf.sprintf "%s is not a valid env symbol" symbol) in export (key, value) in String.concat "" (List.rev_map aux updates) let init_script t ~switch_eval ~complete (variables_sh, switch_eval_sh, complete_sh)= let variables = Some (source t variables_sh) in let switch_eval = if switch_eval then Some (source t ~interactive_only:true switch_eval_sh) else None in let complete = if complete then Some (source t ~interactive_only:true complete_sh) else None in let buf = Buffer.create 128 in let append name = function | None -> () | Some c -> Printf.bprintf buf "# %s\n%s\n" name c in append "Load the environment variables" variables; append "Load the auto-complete scripts" complete; append "Load the opam-switch-eval script" switch_eval; Buffer.contents buf let update_init_scripts t ~global = let init_scripts = match global with | None -> [] | Some g -> let scripts = [ init_sh , (variables_sh , switch_eval_sh, complete_sh); init_zsh, (variables_sh , switch_eval_sh, complete_zsh); init_csh, (variables_csh, switch_eval_sh, complete_sh); ] in let aux (init, scripts) = init, init_script t ~switch_eval:g.switch_eval ~complete:g.complete scripts in List.map aux scripts in let scripts = [ (complete_sh , OpamScript.complete); (complete_zsh , OpamScript.complete_zsh); (switch_eval_sh, OpamScript.switch_eval); (variables_sh , string_of_env_update t `sh (env_updates ~opamswitch:false t)); (variables_csh , string_of_env_update t `csh (env_updates ~opamswitch:false t)); ] @ init_scripts in let overwrite = [ init_sh; init_csh; init_zsh; variables_sh; variables_csh; ] in let updated = ref false in let write (name, body) = let file = OpamPath.init t.root // name in let needs_update = if OpamFilename.exists file && List.mem name overwrite then let current = OpamFilename.read file in body <> current else not (OpamFilename.exists file) in if needs_update then ( updated := true; try OpamFilename.write file body with _ -> () ) in List.iter write scripts; match global with | None -> () | Some o -> List.iter (fun init_file -> let pretty_init_file = OpamFilename.prettify (OpamPath.init t.root // init_file) in if !updated then OpamGlobals.msg " Updating %s\n auto-completion : [%b]\n opam-switch-eval: [%b]\n" pretty_init_file o.complete o.switch_eval else OpamGlobals.msg " %s is already up-to-date.\n" pretty_init_file) [ init_sh; init_zsh; init_csh ] let status_of_init_file t init_sh = let init_sh = OpamPath.init t.root // init_sh in if OpamFilename.exists init_sh then ( let string = OpamFilename.read init_sh in let aux pattern = mem_pattern_in_string ~pattern ~string in if OpamFilename.exists init_sh then let complete_sh = aux complete_sh in let complete_zsh = aux complete_zsh in let switch_eval_sh = aux switch_eval_sh in Some (complete_sh, complete_zsh, switch_eval_sh) else None ) else None let dot_profile_needs_update t dot_profile = if OpamFilename.exists dot_profile then ( let body = OpamFilename.read dot_profile in let pattern1 = "opam config" in let pattern2 = OpamFilename.to_string (OpamPath.init t.root // "init") in let pattern3 = OpamMisc.remove_prefix ~prefix:!OpamGlobals.root_dir pattern2 in if mem_pattern_in_string ~pattern:pattern1 ~string:body then `no else if mem_pattern_in_string ~pattern:pattern2 ~string:body then `no else if mem_pattern_in_string ~pattern:pattern3 ~string:body then `otherroot else `yes ) else `yes let update_dot_profile t dot_profile shell = let pretty_dot_profile = OpamFilename.prettify dot_profile in match dot_profile_needs_update t dot_profile with | `no -> OpamGlobals.msg " %s is already up-to-date.\n" pretty_dot_profile | `otherroot -> OpamGlobals.msg " %s is already configured for another OPAM root.\n" pretty_dot_profile | `yes -> let init_file = init_file shell in let body = if OpamFilename.exists dot_profile then OpamFilename.read dot_profile else "" in OpamGlobals.msg " Updating %s.\n" pretty_dot_profile; let body = Printf.sprintf "%s\n\n\ # OPAM configuration\n\ %s" (OpamMisc.strip body) (source t init_file) in OpamFilename.write dot_profile body let update_setup t user global = begin match user with | Some { ocamlinit = false; dot_profile = None } | None -> () | Some l -> OpamGlobals.msg "User configuration:\n"; if l.ocamlinit then update_ocamlinit (); match l.dot_profile with | None -> () | Some f -> update_dot_profile t f l.shell; end; begin match global with | None -> () | Some _ -> OpamGlobals.msg "Global configuration:\n"; update_init_scripts t ~global end let display_setup t shell dot_profile = let print (k,v) = OpamGlobals.msg " %-25s - %s\n" k v in let not_set = "not set" in let ok = "string is already present so file unchanged" in let error = "error" in let user_setup = let ocamlinit_status = if ocamlinit_needs_update () then not_set else ok in let dot_profile_status = match dot_profile_needs_update t dot_profile with | `no -> ok | `yes -> not_set | `otherroot -> error in [ ("~/.ocamlinit" , ocamlinit_status); (OpamFilename.prettify dot_profile, dot_profile_status); ] in let init_file = init_file shell in let pretty_init_file = OpamFilename.prettify (OpamPath.init t.root // init_file) in let global_setup = match status_of_init_file t init_file with | None -> [pretty_init_file, not_set ] | Some(complete_sh, complete_zsh, switch_eval_sh) -> let completion = if not complete_sh && not complete_zsh then not_set else ok in let switch_eval = if switch_eval_sh then ok else not_set in [ ("init-script" , Printf.sprintf "%s" pretty_init_file); ("auto-completion" , completion); ("opam-switch-eval", switch_eval); ] in OpamGlobals.msg "User configuration:\n"; List.iter print user_setup; OpamGlobals.msg "Global configuration:\n"; List.iter print global_setup let eval_string () = let root = if !OpamGlobals.root_dir <> OpamGlobals.default_opam_dir then Printf.sprintf " --root=%s" !OpamGlobals.root_dir else "" in Printf.sprintf "eval `opam config env%s`\n" root let up_to_date_env t = let changes = List.filter (fun (s, v) -> Some v <> try Some (OpamMisc.getenv s) with _ -> None) (get_opam_env t) in changes = [] let print_env_warning_at_init t user = if up_to_date_env t then () else let profile_string = match user.dot_profile with | None -> "" | Some f -> Printf.sprintf "2. To correctly configure OPAM for subsequent use, add the following\n\ line to your profile file (for instance %s):\n\ \n\ \ %s\n" (OpamFilename.prettify f) (source t (init_file user.shell)) in let ocamlinit_string = if not user.ocamlinit then "" else "3. To avoid issues related to non-system installations of `ocamlfind`\n\ \ add the following lines to ~/.ocamlinit (create it if necessary):\n\ \n\ \ let () =\n\ \ try Topdirs.dir_directory (Sys.getenv \"OCAML_TOPLEVEL_PATH\")\n\ \ with Not_found -> ()\n\ \ ;;\n\n" in let line = "=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n" in OpamGlobals.msg "\n%s\n\ 1. To configure OPAM in the current shell session, you need to run:\n\ \n\ \ %s\n\ %s%s%s\n" line (eval_string ()) profile_string ocamlinit_string line let print_env_warning_at_switch t = if up_to_date_env t then () else OpamGlobals.msg "# To complete the configuration of OPAM, you need to run:\n%s" (eval_string ()) let update_setup_interactive t shell dot_profile = let update dot_profile = let modify_user_conf = dot_profile <> None in let user = Some { shell; ocamlinit = modify_user_conf; dot_profile } in let global = Some { complete = true ; switch_eval = true } in OpamGlobals.msg "\n"; update_setup t user global; modify_user_conf in OpamGlobals.msg "\n"; match read "In normal operation, OPAM only alters files within ~/.opam.\n\ \n\ During this initialisation, you can allow OPAM to add information to two\n\ other files for best results. You can also make these additions manually\n\ if you wish.\n\ \n\ If you agree, OPAM will modify:\n\n\ \ - %s (or a file you specify) to set the right environment\n\ \ variables and to load the auto-completion scripts for your shell (%s)\n\ \ on startup. Specifically, it checks for and appends the following line:\n\ \n\ \ . ~/.opam/opam-init/init.sh > /dev/null 2> /dev/null || true\n\ \n\ \ - ~/.ocamlinit to ensure that non-system installations of `ocamlfind`\n\ \ (i.e. those installed by OPAM) will work correctly when running the\n\ \ OCaml toplevel. It does this by adding $OCAML_TOPLEVEL_PATH to the list\n\ \ of include directories.\n\ \n\ If you choose to not configure your system now, you can either configure\n\ OPAM manually (instructions will be displayed) or launch the automatic setup\n\ later by running:\n\ \n\ \ `opam config setup -a`.\n\ \n\ \n\ Do you want OPAM to modify %s and ~/.ocamlinit?\n\ (default is 'no', use 'f' to name a file other than %s)\n\ \ [N/y/f]" (OpamFilename.prettify dot_profile) (string_of_shell shell) (OpamFilename.prettify dot_profile) (OpamFilename.prettify dot_profile) with | Some ("y" | "Y" | "yes" | "YES" ) -> update (Some dot_profile) | Some ("f" | "F" | "file" | "FILE") -> begin match read " Enter the name of the file to update:" with | None -> OpamGlobals.msg "-- No filename: skipping the auto-configuration step --\n"; false | Some f -> update (Some (OpamFilename.of_string f)) end | _ -> update None (* Add the given packages to the set of package to reinstall. If [all] is set, this is done for ALL the switches (useful when a package change upstream for instance). If not, only the reinstall state of the current switch is changed. *) let add_to_reinstall t ~all packages = log "add-to-reinstall all:%b packages:%s" all (OpamPackage.Set.to_string packages); let packages = OpamPackage.Set.fold (fun nv set -> try let nv = if not (OpamPackage.is_pinned nv) then nv else OpamPackage.pinned (OpamPackage.name nv) in OpamPackage.Set.add nv set with Not_found -> set ) packages OpamPackage.Set.empty in let aux switch = let installed = OpamFile.Installed.safe_read (OpamPath.Switch.installed t.root switch) in let reinstall = OpamPackage.Set.union (OpamFile.Reinstall.safe_read (OpamPath.Switch.reinstall t.root switch)) packages in let reinstall = OpamPackage.Set.filter (fun nv -> OpamPackage.Set.mem nv installed ) reinstall in let file = OpamPath.Switch.reinstall t.root switch in if not (OpamPackage.Set.is_empty reinstall) then OpamFile.Reinstall.write file reinstall else OpamFilename.remove file in if all then OpamSwitch.Map.iter (fun switch _ -> aux switch) t.aliases else aux t.switch let add_switch root switch compiler = log "add_switch switch=%s compiler=%s" (OpamSwitch.to_string switch) (OpamCompiler.to_string compiler); let aliases_f = OpamPath.aliases root in let aliases = OpamFile.Aliases.safe_read aliases_f in if not (OpamSwitch.Map.mem switch aliases) then begin OpamFile.Aliases.write aliases_f (OpamSwitch.Map.add switch compiler aliases); end (* - compiles and install $opam/compiler/[ocaml_version].comp in $opam/[switch] - update $opam/switch - update $opam/config *) let install_compiler t ~quiet switch compiler = log "install_compiler switch=%s compiler=%s" (OpamSwitch.to_string switch) (OpamCompiler.to_string compiler); let comp_f = OpamPath.compiler_comp t.root compiler in if not (OpamFilename.exists comp_f) then ( OpamGlobals.msg "Cannot find %s: %s is not a valid compiler name.\n" (OpamFilename.to_string comp_f) (OpamCompiler.to_string compiler); OpamGlobals.exit 0; ); let switch_dir = OpamPath.Switch.root t.root switch in (* Do some clean-up if necessary *) if not (is_switch_installed t switch) && OpamFilename.exists_dir switch_dir then OpamFilename.rmdir switch_dir; if OpamFilename.exists_dir switch_dir then ( OpamGlobals.msg "The compiler %s is already installed.\n" (OpamSwitch.to_string switch); OpamGlobals.exit 0; ); (* Create base directories *) OpamFilename.mkdir switch_dir; OpamFilename.mkdir (OpamPath.Switch.lib_dir t.root switch); OpamFilename.mkdir (OpamPath.Switch.stublibs t.root switch); OpamFilename.mkdir (OpamPath.Switch.toplevel t.root switch); OpamFilename.mkdir (OpamPath.Switch.build_dir t.root switch); OpamFilename.mkdir (OpamPath.Switch.bin t.root switch); OpamFilename.mkdir (OpamPath.Switch.sbin t.root switch); OpamFilename.mkdir (OpamPath.Switch.doc_dir t.root switch); OpamFilename.mkdir (OpamPath.Switch.man_dir t.root switch); OpamFilename.mkdir (OpamPath.Switch.install_dir t.root switch); OpamFilename.mkdir (OpamPath.Switch.config_dir t.root switch); List.iter (fun num -> OpamFilename.mkdir (OpamPath.Switch.man_dir ~num t.root switch) ) ["1";"1M";"2";"3";"4";"5";"6";"7";"9"]; install_global_config t.root switch; let comp = OpamFile.Comp.read comp_f in begin try if not (OpamFile.Comp.preinstalled comp) then begin OpamGlobals.verbose := not quiet; (* Install the compiler *) let comp_src = match OpamFile.Comp.src comp with | Some f -> f | None -> OpamGlobals.error_and_exit "No source for compiler %s" (OpamCompiler.to_string compiler) in let build_dir = OpamPath.Switch.build_ocaml t.root switch in let kind = guess_repository_kind (OpamFile.Comp.kind comp) comp_src in if kind = `local && Sys.file_exists (fst comp_src) && Sys.is_directory (fst comp_src) then OpamFilename.link_dir ~src:(OpamFilename.Dir.of_string (fst comp_src)) ~dst:build_dir else OpamFilename.with_tmp_dir (fun download_dir -> let result = OpamRepository.pull_url kind (OpamPackage.of_string "compiler.get") download_dir None comp_src in match result with | Not_available u -> OpamGlobals.error_and_exit "%s is not available." u | Up_to_date r | Result r -> OpamFilename.extract_generic_file r build_dir ); let patches = OpamFile.Comp.patches comp in let patches = List.map (fun f -> OpamFilename.download ~overwrite:true f build_dir ) patches in List.iter (fun f -> OpamFilename.patch f build_dir) patches; if OpamFile.Comp.configure comp @ OpamFile.Comp.make comp <> [] then begin OpamFilename.exec build_dir [ ( "./configure" :: OpamFile.Comp.configure comp ) @ [ "-prefix"; OpamFilename.Dir.to_string switch_dir ] (*-bindir %s/bin -libdir %s/lib -mandir %s/man*) (* NOTE In case it exists 2 '-prefix', in general the script ./configure will only consider the last one, others will be discarded. *) ; ( !OpamGlobals.makecmd () :: OpamFile.Comp.make comp ) ; [ !OpamGlobals.makecmd () ; "install" ] ] end else begin let t = { t with switch } in let env = env_filter t OpamVariable.Map.empty in let builds = OpamFilter.commands env (OpamFile.Comp.build comp) in OpamFilename.exec build_dir builds end; if not !OpamGlobals.debug then OpamFilename.rmdir build_dir end; (* Update ~/.opam/aliases *) add_switch t.root switch compiler with e -> if not !OpamGlobals.debug then OpamFilename.rmdir switch_dir; raise e end (* write the new version in the configuration file *) let update_switch_config t switch = let config = OpamFile.Config.with_switch t.config switch in OpamFile.Config.write (OpamPath.config t.root) config; update_init_scripts { t with switch } ~global:None (* Dev packages *) let update_dev_package t nv = log "update-dev-package %s" (OpamPackage.to_string nv); let nv = real_package t nv in let needs_update = OpamPackage.Set.singleton nv in let skip = OpamPackage.Set.empty in match url t nv with | None -> skip | Some url -> let remote_url = OpamFile.URL.url url in match guess_repository_kind (OpamFile.URL.kind url) remote_url with | ` http -> skip | kind -> log "updating %s:%s" (string_of_address remote_url) (string_of_repository_kind kind); let dirname = dev_package t nv in let checksum = OpamFile.URL.checksum url in let r = OpamRepository.pull_url kind nv dirname checksum remote_url in match r with | Not_available u -> OpamGlobals.error "%s is not available anymore!" u; skip | Up_to_date _ -> skip | Result _ -> needs_update let update_dev_packages t = log "update-dev-packages"; let updates packages = let packages = OpamPackage.Set.filter (is_dev_package t) packages in let packages = OpamPackage.Set.inter packages t.installed in let packages = OpamPackage.Set.elements packages in OpamPackage.Parallel.map_reduce_l (2 * jobs t) packages ~map:(update_dev_package t) ~merge:OpamPackage.Set.union ~init:OpamPackage.Set.empty in let switch_dev_packages = keys (switch_dev_packages t) in let global_dev_packages = let all = keys (global_dev_packages t) in OpamPackage.Set.diff all switch_dev_packages in let global_updates = updates global_dev_packages in add_to_reinstall t ~all:true global_updates; let switch_updates = updates switch_dev_packages in add_to_reinstall t ~all:false switch_updates; OpamPackage.Set.union global_updates switch_updates (* Try to download $name.$version+opam.tar.gz *) let download_archive t nv = log "get_archive %s" (OpamPackage.to_string nv); let dst = OpamPath.archive t.root nv in if OpamFilename.exists dst then Some dst else let repo, _ = OpamPackage.Map.find nv t.package_index in let repo = find_repository t repo in match OpamRepository.pull_archive repo nv with | Not_available _ -> None | Up_to_date f | Result f -> OpamFilename.copy ~src:f ~dst; Some dst (* Download a package from its upstream source, using 'cache_dir' as cache directory. *) let download_upstream t nv dirname = let nv = real_package t nv in match url t nv with | None -> None | Some u -> let url = OpamFile.URL.url u in let kind = guess_repository_kind (OpamFile.URL.kind u) url in let checksum = OpamFile.URL.checksum u in match OpamRepository.pull_url kind nv dirname checksum url with | Not_available u -> OpamGlobals.error_and_exit "%s is not available" u | Result f | Up_to_date f -> Some f let check f = let root = OpamPath.root () in let with_switch_lock a f = OpamFilename.with_flock (OpamPath.Switch.lock root a) f in let error () = OpamGlobals.error_and_exit "Please run 'opam init' first to initialize the state of OPAM." (OpamFilename.Dir.to_string root) in if not (OpamFilename.exists_dir root) || not (OpamFilename.exists (OpamPath.config root)) then error () else match f with | Global_lock f -> (* Take the global lock *) OpamFilename.with_flock (OpamPath.lock root) (fun () -> (* clean the log directory *) OpamFilename.cleandir (OpamPath.log root); (* Take all the switch locks *) let aliases = OpamFile.Aliases.safe_read (OpamPath.aliases root) in let f = OpamSwitch.Map.fold (fun a _ f -> if OpamFilename.exists_dir (OpamPath.Switch.root root a) then with_switch_lock a (fun () -> f ()) else f ) aliases f in let t = load_state "global-lock" in global_consistency_checks t; f () ) () | Read_lock f -> (* Simply check that OPAM is correctly initialized *) if OpamFilename.exists_dir root then f () else error () | Switch_lock f -> (* Take a switch lock (and check that the global lock is free). *) let switch = OpamFilename.with_flock (OpamPath.lock root) (fun () -> match !OpamGlobals.switch with | `Command_line s | `Env s -> OpamSwitch.of_string s | `Not_set -> OpamFile.Config.switch (OpamFile.Config.read (OpamPath.config root))) () in (* XXX: We can have a small race just here ... *) let t = load_state "switch-lock" in switch_consistency_checks t; with_switch_lock switch f () opam-1.1.1/src/client/opamSwitchCommand.ml0000644000175000017500000003372012272210733016732 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) open OpamTypes open OpamState.Types let log fmt = OpamGlobals.log "SWITCH" fmt (* name + state + compiler + description *) (* TODO: add repo *) let list ~print_short ~installed ~all = log "list"; let t = OpamState.load_state "switch-list" in let descr c = if c = OpamCompiler.system then let system_version = match OpamCompiler.Version.system () with | None -> "" | Some v -> OpamCompiler.Version.to_string v in OpamFile.Descr.of_string (Printf.sprintf "System compiler (%s)" system_version) else OpamFile.Descr.safe_read (OpamPath.compiler_descr t.root c) in let installed_str = "I" in let current_str = "C" in let not_installed_str = "--" in let installed_s = OpamSwitch.Map.fold (fun name comp acc -> let s = if name = t.switch then current_str else installed_str in let n = OpamSwitch.to_string name in let c = OpamCompiler.to_string comp in let d = descr comp in (n, s, c, d) :: acc ) t.aliases [] in let descrs = OpamCompiler.Set.filter (fun comp -> OpamSwitch.Map.for_all (fun s c -> (* it is either not installed *) c <> comp (* or it is installed with an alias name. *) || OpamSwitch.to_string s <> OpamCompiler.to_string comp ) t.aliases ) t.compilers in let officials, patches = OpamCompiler.Set.fold (fun comp (officials, patches) -> let c = OpamFile.Comp.read (OpamPath.compiler_comp t.root comp) in let version = OpamFile.Comp.version c in if OpamCompiler.Version.to_string version = OpamCompiler.to_string comp then comp :: officials, patches else officials, comp :: patches ) descrs ([],[]) in let mk l = List.fold_left (fun acc comp -> let c = OpamCompiler.to_string comp in let d = descr comp in (not_installed_str, not_installed_str, c, d) :: acc ) [] l in let all = if installed then installed_s else if all then installed_s @ mk officials @ mk patches else installed_s @ mk officials in let max_name, max_state, max_compiler = List.fold_left (fun (n,s,c) (name, state, compiler, _) -> let n = max (String.length name) n in let s = max (String.length state) s in let c = max (String.length compiler) c in (n, s, c) ) (0,0,0) all in let count = ref (List.length all) in let print_compiler (name, state, compiler, descr) = decr count; if print_short then ( let name = if name = not_installed_str then compiler else name in let sep = if !count = 0 then "\n" else " " in OpamGlobals.msg "%s%s" name sep ) else let bold_current s = if name = OpamSwitch.to_string t.switch then OpamGlobals.colorise `bold s else s in let colored_name = bold_current name in let colored_state = if state = not_installed_str then state else bold_current (OpamGlobals.colorise `blue state) in let colored_compiler = bold_current (OpamGlobals.colorise `yellow compiler) in let colored_descr = bold_current (OpamFile.Descr.synopsis descr) in let colored_body = if !OpamGlobals.verbose then match OpamMisc.strip (OpamFile.Descr.body descr) with | "" -> "" | d -> "\n"^d^"\n" else "" in OpamGlobals.msg "%s %s %s %s%s\n" (OpamMisc.indent_left colored_name ~visual:name max_name) (OpamMisc.indent_right colored_state ~visual:state max_state) (OpamMisc.indent_left colored_compiler ~visual:compiler max_compiler) colored_descr colored_body in List.iter print_compiler all let remove_t switch t = log "remove switch=%s" (OpamSwitch.to_string switch); let comp_dir = OpamPath.Switch.root t.root switch in if not (OpamFilename.exists_dir comp_dir) then ( OpamGlobals.msg "The compiler switch %s does not exist.\n" (OpamSwitch.to_string switch); OpamGlobals.exit 1; ); if t.switch = switch then ( OpamGlobals.msg "Cannot remove %s as it is the current compiler.\n" (OpamSwitch.to_string switch); OpamGlobals.exit 1; ); let aliases = OpamSwitch.Map.filter (fun a _ -> a <> switch) t.aliases in OpamFile.Aliases.write (OpamPath.aliases t.root) aliases; OpamFilename.rmdir comp_dir let update_global_config t ~warning switch = OpamState.update_switch_config t switch; let t = OpamState.load_state "switch-update-config" in if warning then OpamState.print_env_warning_at_switch t let install_compiler ~quiet switch compiler = log "install %b %s %s" quiet (OpamSwitch.to_string switch) (OpamCompiler.to_string compiler); (* Remember the current switch to be able to roll-back *) let t = OpamState.load_state "switch-install-with-packages-1" in (* install the new OCaml version *) try OpamState.install_compiler t ~quiet switch compiler with e -> (* in case of reinstall, the switch may still be in t.aliases *) let aliases = OpamSwitch.Map.filter (fun a _ -> a <> switch) t.aliases in OpamFile.Aliases.write (OpamPath.aliases t.root) aliases; let compdir = OpamPath.Switch.root t.root switch in (try OpamFilename.rmdir compdir with _ -> ()); raise e let install_packages ~packages switch compiler = (* install the compiler packages *) OpamGlobals.switch := `Command_line (OpamSwitch.to_string switch); let t = OpamState.load_state "switch-install-with-packages-2" in let to_install, roots = match packages with | Some (p, r) -> (OpamSolution.eq_atoms_of_packages p, OpamPackage.names_of_packages r) | None -> let to_install = OpamState.get_compiler_packages t compiler in let roots = OpamPackage.Name.Set.of_list (List.map fst to_install) in to_install, roots in let bad_packages = OpamMisc.filter_map (fun (n, c) -> if OpamState.is_name_installed t n then ( let nv = OpamState.find_installed_package_by_name t n in if c = Some (`Eq, OpamPackage.version nv) then None else Some (n, Some (OpamPackage.version nv)) ) else None ) to_install in let package_error = function | n, None -> OpamGlobals.error "%s is an invalid package" (OpamPackage.Name.to_string n) | n, Some v -> OpamGlobals.error "%s.%s is not available for the current compiler" (OpamPackage.Name.to_string n) (OpamPackage.Version.to_string v) in let remove_compiler () = let t = OpamState.load_state "remove-compiler" in remove_t switch t in match bad_packages with | [] -> let solution = OpamSolution.resolve_and_apply ~force:true t (Switch roots) { wish_install = []; wish_remove = []; wish_upgrade = to_install } in begin try OpamSolution.check_solution t solution; with e -> remove_compiler (); raise e end | p::_ -> remove_compiler (); package_error p let install_with_packages ~quiet ~packages switch compiler = install_compiler ~quiet switch compiler; install_packages ~packages switch compiler let install ~quiet ~warning ~update_config switch compiler = let t = OpamState.load_state "install" in let comp_dir = OpamPath.Switch.root t.root switch in let comp_f = OpamPath.compiler_comp t.root compiler in if not (OpamFilename.exists_dir comp_dir) && not (OpamFilename.exists comp_f) then OpamCompiler.unknown compiler; if not (OpamState.is_switch_installed t switch) then install_with_packages ~quiet ~packages:None switch compiler else ( let a = OpamSwitch.Map.find switch t.aliases in if a <> compiler then OpamGlobals.error_and_exit "The compiler switch %s is already installed as an alias for %s." (OpamSwitch.to_string switch) (OpamCompiler.to_string a) ); if update_config then update_global_config ~warning t switch let switch ~quiet ~warning switch = log "switch switch=%s" (OpamSwitch.to_string switch); let t = OpamState.load_state "switch-1" in if not (OpamState.is_switch_installed t switch) then ( let compiler = OpamCompiler.of_string (OpamSwitch.to_string switch) in install ~quiet ~warning ~update_config:true switch compiler ) else update_global_config ~warning t switch; let t = OpamState.load_state "switch-2" in OpamState.check_base_packages t (* Remove from [set] all the packages whose names appear in [filter]. *) let filter_names ~filter set = let names = OpamPackage.names_of_packages filter in OpamPackage.Set.filter (fun nv -> not (OpamPackage.Name.Set.mem (OpamPackage.name nv) names) ) set let import_t filename t = log "import switch=%s" (match filename with None -> "" | Some f -> OpamFilename.to_string f); let imported, import_roots = match filename with | None -> OpamFile.Export.read_from_channel stdin | Some f -> OpamFile.Export.read f in (* Import only the packages not currently installed at the right version. *) let imported = OpamPackage.Set.diff imported t.installed in let to_import = List.map (fun nv -> if OpamPackage.Set.mem nv (Lazy.force t.available_packages) then OpamSolution.eq_atom (OpamPackage.name nv) (OpamPackage.version nv) else OpamSolution.atom_of_package nv) (OpamPackage.Set.elements imported) in let to_keep = let keep_installed = filter_names ~filter:imported t.installed in List.map OpamSolution.atom_of_package (OpamPackage.Set.elements keep_installed) in let roots = let import_roots = OpamPackage.Set.diff import_roots t.installed_roots in let to_keep = filter_names ~filter:import_roots t.installed_roots in OpamPackage.names_of_packages (OpamPackage.Set.union import_roots to_keep) in let solution = OpamSolution.resolve_and_apply t (Import roots) { wish_install = to_keep; wish_remove = []; wish_upgrade = to_import } in OpamSolution.check_solution t solution let export filename = let t = OpamState.load_state "switch-export" in let export = (t.installed, t.installed_roots) in match filename with | None -> OpamFile.Export.write_to_channel stdout export | Some f -> OpamFile.Export.write f export let show () = let t = OpamState.load_state "switch-show" in OpamGlobals.msg "%s\n" (OpamSwitch.to_string t.switch) let reinstall_t switch t = log "reinstall switch=%s" (OpamSwitch.to_string switch); if not (OpamState.is_switch_installed t switch) then ( OpamGlobals.msg "The compiler switch %s does not exist.\n" (OpamSwitch.to_string switch); OpamGlobals.exit 1; ); let ocaml_version = OpamSwitch.Map.find switch t.aliases in let installed = let f = OpamPath.Switch.installed t.root switch in OpamFile.Installed.safe_read f in let installed_roots = let f = OpamPath.Switch.installed_roots t.root switch in OpamFile.Installed_roots.safe_read f in let packages = Some (installed, installed_roots) in (* Remove the directory (except the overlays) *) OpamFilename.with_tmp_dir (fun tmpdir -> let tmp dir = OpamFilename.(OP.(tmpdir / Base.to_string (basename_dir dir))) in let save dir = if OpamFilename.exists_dir dir then OpamFilename.move_dir ~src:dir ~dst:(tmp dir) in let restore dir = if OpamFilename.exists_dir (tmp dir) then ( OpamFilename.mkdir (OpamFilename.dirname_dir dir); OpamFilename.move_dir ~src:(tmp dir) ~dst:dir ) in let overlays = OpamPath.Switch.Overlay.dir t.root switch in let backups = OpamPath.Switch.backup_dir t.root switch in save overlays; save backups; OpamFilename.rmdir (OpamPath.Switch.root t.root switch); install_compiler ~quiet:false switch ocaml_version; restore backups; restore overlays; ); install_packages ~packages switch ocaml_version let with_backup command f = let t = OpamState.load_state command in let file = OpamPath.backup t.root in OpamFilename.mkdir (OpamPath.backup_dir t.root); OpamFile.Export.write file (t.installed, t.installed_roots); try f t; OpamFilename.remove file (* We might want to keep it even if successful ? *) with | OpamGlobals.Exit 0 as e -> raise e | err -> let t1 = OpamState.load_state "backup-err" in if OpamPackage.Set.equal t.installed t1.installed && OpamPackage.Set.equal t.installed_roots t1.installed_roots then OpamFilename.remove file else Printf.eprintf "The former package state can be restored with \ %s switch import -f %S\n" Sys.argv.(0) (OpamFilename.to_string file); raise err let reinstall switch = with_backup "switch-reinstall" (reinstall_t switch) let remove switch = with_backup "switch-remove" (remove_t switch) let import filename = with_backup "switch-import" (import_t filename) let () = OpamState.switch_reinstall_hook := reinstall opam-1.1.1/src/client/opamClient.ml0000644000175000017500000013651312272210733015414 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) open OpamTypes open OpamState.Types open OpamMisc.OP let log fmt = OpamGlobals.log "CLIENT" fmt let s_not_installed = "--" type item = { name: name; current_version: version; installed_version: version option; synopsis: string Lazy.t; descr: string Lazy.t; tags: string list; } let names_of_regexp t ~filter ~exact_name ~case_sensitive regexps = log "names_of_regexp regexps=%s" (OpamMisc.string_of_list (fun x -> x) regexps); (* the regexp can also simply be a package. *) let fix_versions = let packages = OpamMisc.filter_map OpamPackage.of_string_opt regexps in List.fold_left (fun map nv -> if OpamPackage.Set.mem nv t.packages then OpamPackage.Name.Map.add (OpamPackage.name nv) nv map else map) OpamPackage.Name.Map.empty packages in let regexps = OpamMisc.filter_map (fun str -> let re = match OpamPackage.of_string_opt str with | Some nv -> if OpamPackage.Set.mem nv t.packages then let name = OpamPackage.Name.to_string (OpamPackage.name nv) in Re_glob.globx name else Re_glob.globx str | None -> Re_glob.globx str in let re = if case_sensitive then re else Re.no_case re in try Some (Re.compile re) with Re_glob.Parse_error -> OpamGlobals.error "%S is not a valid package descriptor." str; None ) regexps in let exact_match str = List.exists (fun re -> OpamMisc.exact_match re str) regexps in let partial_match str = List.exists (fun re -> Re.execp re str) regexps in let partial_matchs strs = List.exists partial_match strs in let packages = match filter with | `all -> t.packages | `installed -> t.installed | `roots -> t.installed_roots | `installable -> let installable = OpamSolver.installable (OpamState.universe t Depends) in OpamPackage.Set.union t.installed installable in let names = OpamPackage.Set.fold (fun nv set -> OpamPackage.Name.Set.add (OpamPackage.name nv) set) packages OpamPackage.Name.Set.empty in let names = OpamPackage.Name.Set.fold (fun name map -> let has_name nv = OpamPackage.name nv = name in let installed_version = if OpamPackage.Set.exists has_name t.installed then let nv = OpamPackage.Set.find has_name t.installed in Some (OpamPackage.version nv) else None in let current_version = if OpamPackage.Name.Map.mem name fix_versions then let nv = OpamPackage.Name.Map.find name fix_versions in OpamPackage.version nv else match installed_version with | Some v -> v | None -> let nv = OpamPackage.Set.max_elt (OpamPackage.Set.filter has_name packages) in OpamPackage.version nv in let nv = OpamPackage.create name current_version in let descr_f = lazy ( OpamState.descr t nv ) in let synopsis = lazy ( OpamFile.Descr.synopsis (Lazy.force descr_f) ) in let descr = lazy ( OpamFile.Descr.full (Lazy.force descr_f) ) in let tags = OpamFile.OPAM.tags (OpamState.opam t nv) in OpamPackage.Name.Map.add name { name; current_version; installed_version; synopsis; descr; tags } map ) names OpamPackage.Name.Map.empty in (* Filter the list of packages, depending on user predicates *) let names = OpamPackage.Name.Map.filter (fun name { synopsis; descr; tags } -> regexps = [] || exact_match (OpamPackage.Name.to_string name) || not exact_name && (partial_match (OpamPackage.Name.to_string name) || partial_match (Lazy.force synopsis) || partial_match (Lazy.force descr) || partial_matchs tags) ) names in if not (OpamPackage.Set.is_empty t.packages) && OpamPackage.Name.Map.is_empty names then OpamGlobals.error_and_exit "No packages found." else names let with_switch_backup command f = let t = OpamState.load_state command in let file = OpamPath.Switch.backup t.root t.switch in OpamFilename.mkdir (OpamPath.Switch.backup_dir t.root t.switch); OpamFile.Export.write file (t.installed, t.installed_roots); try f t; OpamFilename.remove file (* We might want to keep it even if successful ? *) with | OpamGlobals.Exit 0 as e -> raise e | err -> let t1 = OpamState.load_state "switch-backup-err" in if OpamPackage.Set.equal t.installed t1.installed && OpamPackage.Set.equal t.installed_roots t1.installed_roots then OpamFilename.remove file else Printf.eprintf "\nThe former state can be restored with \ %s switch import -f %S\n%!" Sys.argv.(0) (OpamFilename.to_string file); raise err module API = struct let list ~print_short ~filter ~order ~exact_name ~case_sensitive regexp = let t = OpamState.load_state "list" in let names = names_of_regexp t ~filter ~exact_name ~case_sensitive regexp in if not print_short && OpamPackage.Name.Map.cardinal names > 0 then ( let kind = match filter with | `roots | `installed -> "Installed" | _ -> "Available" in OpamGlobals.msg "%s packages for %s:\n" kind (OpamSwitch.to_string t.switch); ); let names = OpamPackage.Name.Map.mapi (fun name stats -> if OpamState.is_name_installed t name && OpamState.is_pinned t name then { stats with installed_version = Some (OpamPackage.Version.pinned) } else stats ) names in let max_n, max_v = OpamPackage.Name.Map.fold (fun name { installed_version } (max_n, max_v) -> let max_n = max max_n (String.length (OpamPackage.Name.to_string name)) in let v_str = match installed_version with | None -> s_not_installed | Some v -> OpamPackage.Version.to_string v in let max_v = max max_v (String.length v_str) in max_n, max_v ) names (0,0) in let names = OpamPackage.Name.Map.bindings names in let names = match order with | `normal -> names | `depends -> let universe = OpamState.universe t Depends in let packages_info = List.map (fun (name, info) -> (OpamPackage.create name info.current_version, info) ) names in let packages = let packages = OpamPackage.Set.of_list (List.map fst packages_info) in OpamSolver.dependencies ~depopts:true ~installed:false universe packages in List.fold_left (fun acc nv -> try (OpamPackage.name nv, List.assoc nv packages_info) :: acc with Not_found -> acc ) [] packages in let roots = OpamPackage.names_of_packages t.installed_roots in List.iter ( if print_short then fun (name, _) -> let name_str = OpamPackage.Name.to_string name in let colored_name = if !OpamGlobals.color && OpamPackage.Name.Set.mem name roots then OpamGlobals.colorise `underline name_str else name_str in Printf.printf "%s " colored_name else let synop_len = let col = OpamMisc.terminal_columns () in max 0 (col - max_n - max_v - 4) in fun (name, { installed_version; synopsis }) -> let name_str = OpamPackage.Name.to_string name in let colored_name = if !OpamGlobals.color && OpamPackage.Name.Set.mem name roots then OpamGlobals.colorise `underline name_str else name_str in let version = match installed_version with | None -> s_not_installed | Some v -> OpamPackage.Version.to_string v in let colored_version = if installed_version = Some OpamPackage.Version.pinned then OpamGlobals.colorise `blue version else OpamGlobals.colorise `magenta version in Printf.printf "%s %s %s\n" (OpamMisc.indent_left colored_name ~visual:name_str max_n) (OpamMisc.indent_right colored_version ~visual:version max_v) (OpamMisc.sub_at synop_len (Lazy.force synopsis)) ) names let info ~fields regexps = let t = OpamState.load_state "info" in let names = names_of_regexp t ~filter:`all ~exact_name:true ~case_sensitive:false regexps in let show_fields = List.length fields <> 1 in let print_one name { current_version } = (* Compute the installed versions, for each switch *) let installed = OpamState.installed_versions t name in (* let installed = OpamPackage.Map.fold (fun nv alias map -> *) (* OpamPackage.Map.add (OpamState.pinning_version t nv) alias map *) (* ) installed OpamPackage.Map.empty in *) let installed_str = let one (nv, aliases) = Printf.sprintf "%s [%s]" (OpamPackage.to_string nv) (String.concat " " (List.map OpamSwitch.to_string aliases)) in String.concat ", " (List.map one (OpamPackage.Map.bindings installed)) in let is_pinned = current_version = OpamPackage.Version.pinned in let nv = OpamPackage.create name current_version in let nv = if is_pinned then OpamState.pinning_version t nv else nv in let opam = OpamState.opam t nv in (* where does it come from (eg. which repository) *) let repository = if is_pinned then ["pinned", "true"] else if OpamRepositoryName.Map.cardinal t.repositories <= 1 then [] else match OpamState.repository_of_package t nv with | None -> [] | Some r -> [ "repository", OpamRepositoryName.to_string r.repo_name ] in let revision = if is_pinned && OpamState.is_name_installed t name then let repo = OpamState.repository_of_locally_pinned_package t name in match OpamRepository.revision repo with | None -> [] | Some v -> [ "revision", OpamPackage.Version.to_string v ] else [] in let url = match OpamState.url t nv with | None -> [] | Some u -> let kind = match OpamFile.URL.kind u with | None -> "http" | Some k -> string_of_repository_kind k in let url = string_of_address (OpamFile.URL.url u) in let checksum = OpamFile.URL.checksum u in [ "upstream-url" , url; "upstream-kind", kind ] @ match checksum with | None -> [] | Some c -> [ "upstream-checksum", c ] in (* All the version of the package *) let versions = OpamPackage.versions_of_name t.packages name in let versions = OpamPackage.Version.Set.filter (fun v -> OpamPackage.Map.for_all (fun nv _ -> OpamPackage.version nv <> v) installed ) versions in let installed_version = match OpamPackage.Map.cardinal installed with | 0 -> [ "installed-version" , "" ] | 1 -> [ "installed-version" , installed_str ] | _ -> [ "installed-versions", installed_str ] in let available_versions = let strings = List.map OpamPackage.Version.to_string (OpamPackage.Version.Set.elements versions) in match strings with | [] -> [] | [v] -> [ "available-version" , v ] | l -> [ "available-versions", String.concat ", " l ] in let mk (empty, get, to_string) name field = let v = field opam in if empty = v then [] else [name, to_string (get v)] in let strings = mk ( [], (fun l -> l), (String.concat ", ") ) in let formula = mk ( Empty, (fun f -> f), OpamFormula.to_string ) in let author = strings "author" OpamFile.OPAM.author in let homepage = strings "homepage" OpamFile.OPAM.homepage in let license = strings "license" OpamFile.OPAM.license in let doc = strings "doc" OpamFile.OPAM.doc in let tags = strings "tags" OpamFile.OPAM.tags in let depends = formula "depends" OpamFile.OPAM.depends in let depopts = formula "depopts" OpamFile.OPAM.depopts in let os = mk ( Empty, (fun f -> f), OpamFormula.string_of_formula (fun (t,s) -> if t then s else "!"^s) ) "os" OpamFile.OPAM.os in let descr = let d = OpamState.descr t nv in ["description", OpamFile.Descr.full d] in let version = OpamPackage.version nv in let all_fields = [ "package", OpamPackage.Name.to_string name ] @ [ "version", OpamPackage.Version.to_string version ] @ revision @ repository @ url @ homepage @ author @ license @ doc @ tags @ depends @ depopts @ os @ installed_version @ available_versions @ descr in let all_fields = match fields with | [] -> all_fields | f -> List.filter (fun (d,_) -> List.mem d f) all_fields in List.iter (fun (f, desc) -> if show_fields then OpamGlobals.msg "%s " (OpamGlobals.colorise `blue (Printf.sprintf "%20s:" f)); OpamGlobals.msg "%s\n" desc ) all_fields in OpamPackage.Name.Map.iter print_one names (* When packages are removed from upstream, they normally disappear from the 'available' packages set and can't be seen by the solver anymore. This is a problem for several reasons, mainly breaking chains of dependencies. The solution here handles installed but no-longer-available packages, but it is a bit of a hack, and might be fragile. Another solution which may be worth investigating could be to keep those packages with a dummy "-1" version for the solver, that doesn't satisfy any dependency on this package. Then interpret "downgrade to -1" as remove. *) let removed_from_upstream t = let unavailable_names = OpamPackage.Name.Set.diff (OpamPackage.names_of_packages t.installed) (OpamPackage.names_of_packages (Lazy.force t.available_packages)) in let unavailable_versions = OpamPackage.Set.diff (OpamPackage.Set.filter (fun nv -> not (OpamPackage.is_pinned nv)) t.installed) (Lazy.force t.available_packages) in let t = (* This is a hack to tell the solver not to ignore unavailable packages, so that they can be removed (they must be added to the universe and to wish_remove, and otherwise removed from the request) *) let available_packages = lazy (OpamPackage.Set.union (Lazy.force t.available_packages) unavailable_versions) in {t with available_packages} in t, OpamPackage.packages_of_names t.installed unavailable_names, unavailable_versions (* Returns the set of packages that have to be fully removed (no version available anymore), and the full set of versionned packages to mark for removal or up/down-grade *) let must_be_removed t changed unavailable_versions = if OpamPackage.Set.is_empty unavailable_versions then OpamPackage.Set.empty, OpamPackage.Set.empty else let universe = OpamState.universe t Reinstall in (* Restrict to what has to be recompiled, we can keep the rest for now *) let recompile_cone = OpamPackage.Set.of_list (OpamSolver.reverse_dependencies ~depopts:true ~installed:false universe changed) in let unavailable_versions = OpamPackage.Set.inter recompile_cone unavailable_versions in let all = OpamPackage.Set.union t.packages t.installed in let unavailable_versions = let universe = let available_packages = lazy (OpamPackage.Set.diff (Lazy.force t.available_packages) unavailable_versions) in OpamState.universe {t with available_packages} Reinstall in OpamPackage.Set.diff all (OpamSolver.installable universe) in let unavailable_versions = OpamPackage.Set.inter recompile_cone unavailable_versions in (* Packages for which _no_ version is available anymore *) let to_remove_names = OpamPackage.Name.Set.diff (OpamPackage.names_of_packages all) (OpamPackage.names_of_packages (OpamPackage.Set.diff all unavailable_versions)) in let to_remove = OpamPackage.packages_of_names t.installed to_remove_names in log "Packages removed from upstream lead to REMOVAL of %s and VERSION CHANGE from %s" (OpamPackage.Set.to_string to_remove) (OpamPackage.Set.to_string unavailable_versions); to_remove, (OpamPackage.Set.union to_remove unavailable_versions) let dry_upgrade () = log "dry-upgrade"; let t = OpamState.load_state ~save_cache:false "dry-upgrade" in let t, _, bad_versions = removed_from_upstream t in let reinstall = OpamPackage.Set.inter t.reinstall t.installed in let to_remove, unavailable = must_be_removed t t.installed bad_versions in let roots = OpamPackage.Set.diff t.installed_roots to_remove in let to_keep = OpamPackage.Set.diff t.installed to_remove in let solution = OpamSolution.resolve ~verbose:false t (Upgrade reinstall) { wish_install = OpamSolution.atoms_of_packages to_keep; wish_remove = OpamSolution.eq_atoms_of_packages unavailable; wish_upgrade = OpamSolution.atoms_of_packages roots } in match solution with | Conflicts _ -> None | Success sol -> Some (OpamSolver.stats sol) (* Recursively traverse redirection links, but stop after 10 steps or if we start to cycle. *) let repository_update t repo = let max_loop = 10 in let rec loop r n = if n = 0 then OpamGlobals.warning "%s: Too many redirections, stopping." (OpamRepositoryName.to_string repo.repo_name) else ( OpamRepository.update r; if n <> max_loop && r = repo then OpamGlobals.warning "%s: Cyclic redirections, stopping." (OpamRepositoryName.to_string repo.repo_name) else match OpamState.redirect t r with | None -> () | Some (new_repo, f) -> OpamFilename.rmdir repo.repo_root; OpamFile.Repo_config.write (OpamPath.Repository.config repo) new_repo; let reason = match f with | None -> "" | Some f -> Printf.sprintf " (%s)" (OpamFilter.to_string f) in OpamGlobals.note "The repository '%s' will be *%s* redirected to %s%s" (OpamRepositoryName.to_string repo.repo_name) ((OpamGlobals.colorise `bold) "permanently") (OpamMisc.prettify_path (string_of_address new_repo.repo_address)) reason; loop new_repo (n-1); ) in loop repo max_loop let update ~repos_only repos = let t = OpamState.load_state ~save_cache:true "update" in log "UPDATE %s" (OpamMisc.string_of_list OpamRepositoryName.to_string repos); let repositories = if repos = [] then t.repositories else let aux r _ = List.mem r repos in OpamRepositoryName.Map.filter aux t.repositories in let repositories_need_update = not (OpamRepositoryName.Map.is_empty repositories) in let dev_packages = if repos_only then OpamPackage.Set.empty else let all = OpamPackage.Set.inter t.installed (OpamState.dev_packages t) in if repos = [] then all else OpamPackage.Set.filter (fun nv -> let name repo_name = (repo_name |> OpamRepositoryName.to_string |> OpamPackage.Name.of_string) = OpamPackage.name nv in let package repo_name = (repo_name |> OpamRepositoryName.to_string |> OpamPackage.of_string_opt) = Some nv in List.exists (fun repo_name -> name repo_name || package repo_name ) repos ) all in let dev_packages_need_update = not (OpamPackage.Set.is_empty dev_packages) in let valid_repositories = OpamMisc.StringSet.of_list (List.rev_map OpamRepositoryName.to_string (OpamRepositoryName.Map.keys repositories)) in let valid_pinned_packages = OpamMisc.StringSet.of_list (List.rev_map OpamPackage.Name.to_string (OpamPackage.Name.Map.keys t.pinned)) in let unknown_names, not_pinned = if repos = [] then [], [] else let all = OpamMisc.StringSet.of_list (List.rev_map OpamRepositoryName.to_string repos) in let valid_names = OpamMisc.StringSet.of_list (List.rev_map (OpamPackage.name ++ OpamPackage.Name.to_string) (OpamPackage.Set.elements t.packages)) in let (--) = OpamMisc.StringSet.diff in let unknown_names = all -- valid_repositories -- valid_names in let not_pinned = (OpamMisc.StringSet.inter all valid_names) -- valid_pinned_packages in OpamMisc.StringSet.elements unknown_names, OpamMisc.StringSet.elements not_pinned in begin let valid_repositories = match OpamMisc.StringSet.elements valid_repositories with | [] -> "" | [s] -> Printf.sprintf " Valid repository is %s." s | l -> Printf.sprintf " Valid repositories are %s." (OpamMisc.pretty_list l) in match unknown_names with | [] -> () | [s] -> OpamGlobals.error_and_exit "Cannot update the repository %s.%s" s valid_repositories | _ -> OpamGlobals.error_and_exit "Cannot update the repositories %s.%s" (OpamMisc.pretty_list unknown_names) valid_repositories end; begin let valid_pinned_packages = match OpamMisc.StringSet.elements valid_pinned_packages with | [] -> "" | [s] -> Printf.sprintf " Only %s is currently pinned." s | l -> Printf.sprintf " The currently pinned packages are %s." (OpamMisc.pretty_list l) in match not_pinned with | [] -> () | [s] -> OpamGlobals.msg "Cannot update the package %s because it is not pinned.%s\n" s valid_pinned_packages | _ -> OpamGlobals.msg "Cannot update %s because none of them is pinned.%s\n" (OpamMisc.pretty_list not_pinned) valid_pinned_packages end; if repositories_need_update then ( let repos = OpamRepositoryName.Map.values repositories in let child repo = try repository_update t repo with _ -> OpamGlobals.error "Skipping %s as the repository is not available.\n" (string_of_address repo.repo_address) in (* Update each remote backend *) OpamRepository.Parallel.iter_l (2 * OpamState.jobs t) repos ~child ~post:ignore ~pre:ignore; let t, compiler_updates = let t = OpamRepositoryCommand.update_compiler_index t in t, OpamRepositoryCommand.fix_compiler_descriptions t ~verbose:true in let package_updates = let t = OpamRepositoryCommand.update_package_index t in OpamRepositoryCommand.fix_package_descriptions t ~verbose:true in (* Eventually output some JSON file *) if OpamJson.verbose () then let json to_json update = `O [ ("created", to_json update.created); ("updated", to_json update.updated); ("deleted", to_json update.deleted); ("changed", to_json update.changed); ] in let updates = `O [ "package-updates" , (json OpamPackage.Set.to_json package_updates); "compiler-updates", (json OpamCompiler.Set.to_json compiler_updates); ] in OpamJson.add updates; ); if dev_packages_need_update then ( let updates = OpamRepositoryCommand.update_dev_packages ~verbose:true t dev_packages in let json = `O [ "dev-packages-update", OpamPackage.Set.to_json updates ] in OpamJson.add json ); OpamState.rebuild_state_cache (); match dry_upgrade () with | None -> OpamGlobals.msg "No stats.\n" | Some stats -> if OpamSolution.sum stats > 0 then ( OpamGlobals.msg "%s\n" (OpamSolver.string_of_stats stats); OpamGlobals.msg "You can now run 'opam upgrade' to upgrade your system.\n" ) else OpamGlobals.msg "Everything is up-to-date.\n" let upgrade_t names t = log "UPGRADE %s" (match names with | None -> "" | Some n -> OpamPackage.Name.Set.to_string n); let to_reinstall = match names with | None -> OpamPackage.Set.inter t.reinstall t.installed | Some n -> OpamPackage.Set.filter (fun nv -> OpamPackage.Name.Set.mem (OpamPackage.name nv) n) t.reinstall in let (--) = OpamPackage.Set.diff in let solution_found = match names with | None -> let t, _, bad_versions = removed_from_upstream t in let to_remove, unavailable = must_be_removed t t.installed bad_versions in let to_upgrade = t.installed -- to_remove in OpamSolution.resolve_and_apply t (Upgrade to_reinstall) { wish_install = []; wish_remove = OpamSolution.eq_atoms_of_packages unavailable; wish_upgrade = OpamSolution.atoms_of_packages to_upgrade } | Some names -> let names = OpamSolution.atoms_of_names t names in let to_upgrade = let packages = OpamMisc.filter_map (fun (n,_) -> if OpamState.is_name_installed t n then Some (OpamState.find_installed_package_by_name t n) else ( OpamGlobals.msg "%s is not installed.\n" (OpamPackage.Name.to_string n); None ) ) names in (OpamPackage.Set.of_list packages) in let t, removed, bad_versions = removed_from_upstream t in let conflicts = OpamPackage.Set.inter to_upgrade removed in if not (OpamPackage.Set.is_empty conflicts) then OpamGlobals.error_and_exit "These packages would need to be recompiled, but they are no longer available \ upstream:\n\ \ %s\n\ Please run \"opam upgrade\" without argument to get to a clean state." (OpamPackage.Set.to_string conflicts); let to_remove, unavailable = must_be_removed t to_upgrade bad_versions in let to_upgrade = to_upgrade -- to_remove in let installed_roots = t.installed -- to_upgrade -- to_remove in OpamSolution.resolve_and_apply t (Upgrade to_reinstall) { wish_install = OpamSolution.eq_atoms_of_packages installed_roots; wish_remove = OpamSolution.eq_atoms_of_packages unavailable; wish_upgrade = OpamSolution.atoms_of_packages to_upgrade } in begin match solution_found with | Aborted | No_solution | Error _ | OK _ -> () | Nothing_to_do -> OpamGlobals.msg "Already up-to-date.\n" end; OpamSolution.check_solution t solution_found let upgrade names = with_switch_backup "upgrade" (upgrade_t names) let init repo compiler ~jobs shell dot_profile update_config = log "INIT %s" (OpamRepository.to_string repo); let root = OpamPath.root () in let config_f = OpamPath.config root in let dot_profile_o = Some dot_profile in let user = { shell; ocamlinit = true; dot_profile = dot_profile_o } in let root_empty = not (OpamFilename.exists_dir root) || OpamFilename.files root = [] in let update_setup t = let updated = match update_config with | `ask -> OpamState.update_setup_interactive t shell dot_profile | `no -> false | `yes -> let global = { complete = true; switch_eval = true } in OpamState.update_setup t (Some user) (Some global); true in if updated then OpamState.print_env_warning_at_switch t else OpamState.print_env_warning_at_init t user in if OpamFilename.exists config_f then ( OpamGlobals.msg "OPAM has already been initialized."; let t = OpamState.load_state "init" in update_setup t ) else ( if not root_empty then ( OpamGlobals.warning "%s exists and is not empty" (OpamFilename.Dir.to_string root); if not (OpamState.confirm "Proceed ?") then OpamGlobals.exit 1); try (* Create (possibly empty) configuration files *) let switch = if compiler = OpamCompiler.system then OpamSwitch.default else OpamSwitch.of_string (OpamCompiler.to_string compiler) in (* Create ~/.opam/compilers/system.comp *) let system_version = OpamCompiler.Version.current () in OpamState.create_system_compiler_description root system_version; (* Create ~/.opam/config *) let config = OpamFile.Config.create switch [repo.repo_name] jobs in OpamFile.Config.write config_f config; (* Create ~/.opam/aliases *) OpamFile.Aliases.write (OpamPath.aliases root) (OpamSwitch.Map.add switch compiler OpamSwitch.Map.empty); (* Init repository *) OpamFile.Package_index.write (OpamPath.package_index root) OpamPackage.Map.empty; OpamFile.Compiler_index.write (OpamPath.compiler_index root) OpamCompiler.Map.empty; OpamFile.Repo_config.write (OpamPath.Repository.config repo) repo; OpamRepository.init repo; (* Init global dirs *) OpamFilename.mkdir (OpamPath.packages_dir root); OpamFilename.mkdir (OpamPath.compilers_dir root); (* Load the partial state, and update the global state *) log "updating repository state"; let t = OpamState.load_state ~save_cache:false "init-1" in OpamRepositoryCommand.fix_descriptions t ~save_cache:false ~verbose:false; (* Load the partial state, and install the new compiler if needed *) log "updating package state"; let t = OpamState.load_state ~save_cache:false "init-2" in let switch = OpamSwitch.of_string (OpamCompiler.to_string compiler) in let quiet = (compiler = OpamCompiler.system) in OpamState.install_compiler t ~quiet switch compiler; OpamState.update_switch_config t switch; (* Finally, load the complete state and install the compiler packages *) log "installing compiler packages"; let t = OpamState.load_state "init-3" in let compiler_packages = OpamState.get_compiler_packages t compiler in let compiler_names = OpamPackage.Name.Set.of_list (List.rev_map fst compiler_packages) in (* Ugly hack to quiet OPAM on base packages *) let display_messages = !OpamGlobals.display_messages in OpamGlobals.display_messages := false; let _solution = OpamSolution.resolve_and_apply ~force:true t (Init compiler_names) { wish_install = []; wish_remove = []; wish_upgrade = compiler_packages } in OpamGlobals.display_messages := display_messages; update_setup t with e -> if not !OpamGlobals.debug && root_empty then OpamFilename.rmdir root; raise e) let install_t names add_to_roots deps_only t = log "INSTALL %s" (OpamPackage.Name.Set.to_string names); let atoms = OpamSolution.atoms_of_names ~permissive:true t names in let names = OpamPackage.Name.Set.of_list (List.rev_map fst atoms) in let pkg_skip, pkg_new = List.partition (fun (n,v) -> match v with | None -> OpamState.is_name_installed t n | Some (_,v) -> if OpamState.is_name_installed t n then let nv = OpamState.find_installed_package_by_name t n in OpamPackage.version nv = v else false ) atoms in (* Add the packages to the list of package roots and display a warning for already installed package roots. *) let current_roots = t.installed_roots in let t = List.fold_left (fun t (n,_) -> let nv = OpamState.find_installed_package_by_name t n in if OpamPackage.Set.mem nv t.installed then match add_to_roots with | None -> OpamGlobals.note "Package %s is already installed (current version is %s)." (OpamPackage.Name.to_string (OpamPackage.name nv)) (OpamPackage.Version.to_string (OpamPackage.version nv)); t | Some true -> if OpamPackage.Set.mem nv t.installed_roots then OpamGlobals.note "Package %s is already installed as a root." (OpamPackage.Name.to_string (OpamPackage.name nv)); { t with installed_roots = OpamPackage.Set.add nv t.installed_roots } | Some false -> if OpamPackage.Set.mem nv t.installed_roots then { t with installed_roots = OpamPackage.Set.remove nv t.installed_roots } else (OpamGlobals.note "Package %s is already marked as 'installed automatically'." (OpamPackage.Name.to_string (OpamPackage.name nv)); t) else t ) t pkg_skip in if t.installed_roots <> current_roots then ( let diff = OpamPackage.Set.diff t.installed_roots current_roots in if not (OpamPackage.Set.is_empty diff) then let diff = OpamPackage.Set.elements diff in let diff = List.rev (List.rev_map OpamPackage.to_string diff) in OpamGlobals.msg "Adding %s to the list of installed roots.\n" (OpamMisc.pretty_list diff) else ( let diff = OpamPackage.Set.diff current_roots t.installed_roots in let diff = OpamPackage.Set.elements diff in let diff = List.rev (List.rev_map OpamPackage.to_string diff) in OpamGlobals.msg "Removing %s from the list of installed roots.\n" (OpamMisc.pretty_list diff) ); let file = OpamPath.Switch.installed_roots t.root t.switch in OpamFile.Installed_roots.write file t.installed_roots; ); OpamSolution.check_availability t atoms; if pkg_new <> [] then ( (* Display a warning if at least one package contains dependencies to some unknown packages *) let all_packages = OpamPackage.to_map t.packages in List.iter (fun (n,v) -> let versions = match v with | None -> OpamPackage.versions_of_name t.packages n | Some (_,v) -> OpamPackage.Version.Set.singleton v in OpamPackage.Version.Set.iter (fun v -> let nv = OpamPackage.create n v in let opam = OpamState.opam t nv in let f_warn (n, _) = if not (OpamPackage.Name.Map.mem n all_packages) then OpamGlobals.warning "%s references unknown package %s" (OpamPackage.to_string nv) (OpamPackage.Name.to_string n) in List.iter (OpamFormula.iter f_warn) [ OpamFile.OPAM.depends opam; OpamFile.OPAM.depopts opam; OpamFile.OPAM.conflicts opam; ] ) versions ) pkg_new; let request = if OpamCudf.external_solver_available () then { wish_install = atoms; wish_remove = [] ; wish_upgrade = [] } else { wish_install = OpamSolution.atoms_of_packages (OpamPackage.Set.inter t.installed_roots (Lazy.force t.available_packages)); wish_remove = [] ; wish_upgrade = atoms } in let action = if add_to_roots = Some false || deps_only then Install OpamPackage.Name.Set.empty else Install names in let solution = OpamSolution.resolve t action request in let solution = match solution with | Conflicts cs -> log "conflict!"; OpamGlobals.msg "%s\n" (cs()); No_solution | Success solution -> if deps_only then ( let to_install = PackageActionGraph.fold_vertex (fun act acc -> match act with | To_change (_, p) -> OpamPackage.Set.add p acc | _ -> acc) solution.PackageActionGraph.to_process OpamPackage.Set.empty in let all_deps = let universe = OpamState.universe t (Install names) in OpamPackage.Name.Set.fold (fun name deps -> let nvs = OpamPackage.packages_of_name to_install name in let deps_nv = OpamSolver.dependencies ~depopts:false ~installed:false universe nvs in let deps_only = OpamPackage.Set.diff (OpamPackage.Set.of_list deps_nv) nvs in OpamPackage.Set.union deps deps_only) names OpamPackage.Set.empty in PackageActionGraph.iter_vertex (function | To_change (_, p) as v -> if not (OpamPackage.Set.mem p all_deps) then PackageActionGraph.remove_vertex solution.PackageActionGraph.to_process v | _ -> ()) solution.PackageActionGraph.to_process ); OpamSolution.apply t action solution in OpamSolution.check_solution t solution ) let install names add_to_roots deps_only = with_switch_backup "install" (install_t names add_to_roots deps_only) let remove_t ~autoremove ~force names t = log "REMOVE autoremove:%b %s" autoremove (OpamPackage.Name.Set.to_string names); let nothing_to_do = ref true in let atoms = OpamSolution.atoms_of_names ~permissive:true t names in let atoms = List.filter (fun (n,_) -> if n = OpamPackage.Name.global_config then ( OpamGlobals.msg "Package %s can not be removed.\n" (OpamPackage.Name.to_string OpamPackage.Name.global_config); false ) else true ) atoms in let dummy_version = OpamPackage.Version.of_string "" in let atoms, not_installed = let aux (atoms, not_installed) atom nv = if OpamPackage.Set.mem nv t.installed then (atom :: atoms, not_installed) else (atoms, nv :: not_installed) in List.fold_left (fun accu (n,v as atom) -> let nv = match v with | None -> if OpamState.is_name_installed t n then OpamState.find_installed_package_by_name t n else OpamPackage.create n dummy_version | Some (_,v) -> OpamPackage.create n v in aux accu atom nv) ([], []) atoms in if not_installed <> [] then ( let to_string nv = if OpamPackage.version nv = dummy_version then OpamPackage.Name.to_string (OpamPackage.name nv) else OpamPackage.to_string nv in if force then let force_remove nv = let nv = if OpamPackage.version nv <> dummy_version then nv else let name = OpamPackage.name nv in OpamPackage.create name (OpamPackage.Version.Set.max_elt (OpamPackage.versions_of_name t.packages name)) in OpamGlobals.note "Forcing removal of %s" (OpamPackage.to_string nv); OpamAction.remove_package ~rm_build:true ~metadata:false t nv in nothing_to_do := false; List.iter force_remove not_installed else if List.length not_installed = 1 then OpamGlobals.msg "%s is not installed.\n" (to_string (List.hd not_installed)) else OpamGlobals.msg "%s are not installed.\n" (OpamMisc.string_of_list to_string not_installed) ); if autoremove || atoms <> [] then ( let t, _, _ = removed_from_upstream t in let packages = OpamPackage.Set.of_list (List.rev_map (fun (n,_) -> OpamState.find_installed_package_by_name t n ) atoms) in let universe = OpamState.universe t Remove in let to_remove = OpamPackage.Set.of_list (OpamSolver.reverse_dependencies ~depopts:false ~installed:true universe packages) in let to_keep = if autoremove then OpamPackage.Set.diff t.installed_roots to_remove else OpamPackage.Set.diff t.installed to_remove in let to_keep = OpamPackage.Set.of_list (OpamSolver.dependencies ~depopts:true ~installed:true universe to_keep) in (* to_keep includes the depopts, because we don't want to autoremove them. But that may re-include packages that we wanted removed, so we need to remove them again *) let to_keep = OpamPackage.Set.diff to_keep to_remove in let to_remove = if autoremove then let to_remove = OpamPackage.Set.diff t.installed to_keep in if atoms = [] then to_remove else (* restrict to the dependency cone of removed pkgs *) OpamPackage.Set.inter to_remove (OpamPackage.Set.of_list (OpamSolver.dependencies ~depopts:true ~installed:true universe to_remove)) else to_remove in let solution = OpamSolution.resolve_and_apply t Remove { wish_install = OpamSolution.eq_atoms_of_packages to_keep; wish_remove = OpamSolution.atoms_of_packages to_remove; wish_upgrade = [] } in OpamSolution.check_solution t solution ) else if !nothing_to_do then OpamGlobals.msg "Nothing to do.\n" let remove ~autoremove ~force names = with_switch_backup "remove" (remove_t ~autoremove ~force names) let reinstall_t names t = log "reinstall %s" (OpamPackage.Name.Set.to_string names); let t, _, _ = removed_from_upstream t in let atoms = OpamSolution.atoms_of_names t names in let reinstall = List.map (function (n,v) -> match v with | None -> if not (OpamState.is_name_installed t n) then OpamGlobals.error_and_exit "%s is not installed.\n" (OpamPackage.Name.to_string n) else OpamState.find_installed_package_by_name t n | Some (_,v) -> let nv = OpamPackage.create n v in if OpamPackage.Set.mem nv t.installed then nv else OpamGlobals.error_and_exit "%s is not installed.\n" (OpamPackage.to_string nv) ) atoms in let reinstall = OpamPackage.Set.of_list reinstall in let universe = OpamState.universe t Depends in let depends = (* Do not cast to a set, we need to keep the order *) OpamSolver.reverse_dependencies ~depopts:true ~installed:true universe reinstall in let to_process = List.map (fun pkg -> To_recompile pkg) depends in let solution = OpamSolver.sequential_solution to_process in let solution = OpamSolution.apply t Reinstall solution in OpamSolution.check_solution t solution let reinstall names = with_switch_backup "reinstall" (reinstall_t names) module PIN = OpamPinCommand module REPOSITORY = OpamRepositoryCommand module CONFIG = OpamConfigCommand module SWITCH = OpamSwitchCommand end let read_lock f = OpamState.check (Read_lock f) let switch_lock f = OpamState.check (Switch_lock f) let global_lock f = OpamState.check (Global_lock f) (** We protect each main functions with a lock depending on its access on some read/write data. *) module SafeAPI = struct let init = API.init let list ~print_short ~filter ~order ~exact_name ~case_sensitive pkg_str = read_lock (fun () -> API.list ~print_short ~filter ~order ~exact_name ~case_sensitive pkg_str ) let info ~fields regexps = read_lock (fun () -> API.info ~fields regexps) let install names add_to_roots deps_only = switch_lock (fun () -> API.install names add_to_roots deps_only) let reinstall names = switch_lock (fun () -> API.reinstall names) let upgrade names = switch_lock (fun () -> API.upgrade names) let remove ~autoremove ~force names = switch_lock (fun () -> API.remove ~autoremove ~force names) let update ~repos_only repos = global_lock (fun () -> API.update ~repos_only repos) module CONFIG = struct let config option = read_lock (fun () -> API.CONFIG.config option) let env ~csh ~sexp ~fish = read_lock (fun () -> API.CONFIG.env ~csh ~sexp ~fish) let setup local global = global_lock (fun () -> API.CONFIG.setup local global) let setup_list shell dot_profile = read_lock (fun () -> API.CONFIG.setup_list shell dot_profile) let exec command = read_lock (fun () -> API.CONFIG.exec command) let list names = read_lock (fun () -> API.CONFIG.list names) let variable var = read_lock (fun () -> API.CONFIG.variable var) let subst files = read_lock (fun () -> API.CONFIG.subst files) let includes ~is_rec names = read_lock (fun () -> API.CONFIG.includes ~is_rec names) end module REPOSITORY = struct let list ~short = global_lock (fun () -> API.REPOSITORY.list ~short) let add name kind address ~priority = global_lock (fun () -> API.REPOSITORY.add name kind address ~priority) let remove name = global_lock (fun () -> API.REPOSITORY.remove name) let priority name ~priority = global_lock (fun () -> API.REPOSITORY.priority name ~priority) end module SWITCH = struct let switch ~quiet ~warning name = global_lock (fun () -> API.SWITCH.switch ~quiet ~warning name) let install ~quiet ~warning ~update_config switch ocaml_version = global_lock (fun () -> API.SWITCH.install ~quiet ~warning ~update_config switch ocaml_version) let import filename = switch_lock (fun () -> API.SWITCH.import filename) let export filename = read_lock (fun () -> API.SWITCH.export filename) let remove switch = global_lock (fun () -> API.SWITCH.remove switch) let reinstall switch = global_lock (fun () -> API.SWITCH.reinstall switch) let list ~print_short ~installed ~all = read_lock (fun () -> API.SWITCH.list ~print_short ~installed ~all) let show () = read_lock API.SWITCH.show end module PIN = struct let pin ~force action = global_lock (fun () -> API.PIN.pin ~force action) let list () = read_lock API.PIN.list end end opam-1.1.1/src/client/opamClient.mli0000644000175000017500000001271412272210733015561 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) (** Client entry-point. *) open OpamTypes (** OPAM API. *) module API: sig (** Initialize the client a consistent state. *) val init: repository -> compiler -> jobs:int -> shell -> filename -> [`ask|`yes|`no] -> unit (** Display all available packages that matches any of the regexps. *) val list: print_short:bool -> filter:[`all|`installed|`roots|`installable] -> order:[`normal|`depends] -> exact_name:bool -> case_sensitive:bool -> string list -> unit (** Display a general summary of a collection of packages. *) val info: fields:string list -> string list -> unit (** Install the given set of packages. Second argument, if not None, specifies that given packages should be added or removed from the roots *) val install: name_set -> bool option -> bool -> unit (** Reinstall the given set of packages. *) val reinstall: name_set -> unit (** Refresh the available packages. *) val update: repos_only:bool -> repository_name list -> unit (** Find a consistent state where most of the installed packages are upgraded to their latest version. [None] means all the installed packages. *) val upgrade: name_set option -> unit (** Remove the given set of packages. *) val remove: autoremove:bool -> force:bool -> name_set -> unit (** Config API. *) module CONFIG: sig (** Display configuration options. *) val config: config -> unit (** Display environment. *) val env: csh:bool -> sexp:bool -> fish:bool -> unit (** Global and user setup of OPAM. *) val setup: user_config option -> global_config option -> unit (** Display global and user informations about OPAM setup. *) val setup_list: shell -> filename -> unit (** Execute a command in a subshell with the right environment variables. *) val exec: string -> unit (** Display includes files. *) val includes: is_rec:bool -> name list -> unit (** Display variables and their contents. *) val list: name list -> unit (** Display a given variable content. *) val variable: full_variable -> unit (** Substitute files. *) val subst: basename list -> unit end (** Repository API *) module REPOSITORY: sig (** Display the list of repositories. *) val list: short:bool -> unit (** Add a new repository. *) val add: repository_name -> repository_kind -> address -> priority:int option -> unit (** Remove a repository. *) val remove: repository_name -> unit (** Set-up repository priority. *) val priority: repository_name -> priority:int -> unit end (** Switch API *) module SWITCH: sig (** Switch to the given compiler. Take the global file lock. *) val switch: quiet:bool -> warning:bool -> switch -> unit (** Install the given compiler. *) val install: quiet:bool -> warning:bool -> update_config:bool -> switch -> compiler -> unit (** Import the packages from a file. If no filename is specified, read stdin. *) val import: filename option -> unit (** Export the packages to a file. If no filename is specified, write to stdout. *) val export: filename option -> unit (** Remove the given compiler. *) val remove: switch -> unit (** Reinstall the given compiler. *) val reinstall: switch -> unit (** List the available compiler descriptions. *) val list: print_short:bool -> installed:bool -> all:bool -> unit (** Display the name of the current compiler. *) val show: unit -> unit end (** Pin API *) module PIN: sig (** Pin a package to a specific version. *) val pin: force:bool -> pin -> unit (** List the current pinned packages. *) val list: unit -> unit end end (** Call an unsafe function while taking the global lock. *) val global_lock: (unit -> unit) -> unit (** Call an unsafe function while taking the current switch lock. *) val switch_lock: (unit -> unit) -> unit (** Call an unsafe function while checking that no lock is already held. *) val read_lock: (unit -> unit) -> unit (** Loads state with [command], and calls [f] on it. The loaded state is backed up, and in case of error, a message is displayed on how to revert. *) val with_switch_backup: string -> (OpamState.state -> unit) -> unit (** This version of the API can be used concurrently. *) module SafeAPI: (module type of API) opam-1.1.1/src/client/opamConfigCommand.mli0000644000175000017500000000364712272210733017054 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) (** Configuration commands *) open OpamTypes (** Display the current environment *) val env: csh:bool -> sexp:bool -> fish:bool -> unit (** Display the content of all available variables *) val list: name list -> unit (** Display the content of a given variable *) val variable: full_variable -> unit (** Display includes directives *) val includes: is_rec:bool -> name list -> unit (** Display configuration options *) val config: config -> unit (** Substitute files *) val subst: basename list -> unit (** Update the global and user configuration to use OPAM. *) val setup: user_config option -> global_config option -> unit (** Display the global and user configuration for OPAM. *) val setup_list: shell -> filename -> unit (** Execute a command in a subshell *) val exec: string -> unit opam-1.1.1/src/client/opamSolution.mli0000644000175000017500000000514212272210733016154 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) (** Applying solver solutions *) open OpamTypes (** Resolve an user request *) val resolve: ?verbose:bool -> OpamState.state -> user_action -> atom request -> (solution, string) result (** Apply a solution returned by the solver. *) val apply: ?force:bool -> OpamState.state -> user_action -> solution -> solver_result (** Call the solver to get a solution and then call [apply]. *) val resolve_and_apply: ?force:bool -> OpamState.state -> user_action -> atom request -> solver_result (** Raise an error if no solution is found or in case of error. *) val check_solution: OpamState.state -> solver_result -> unit (** {2 Atoms} *) (** Return an atom with a string version constraint *) val eq_atom: name -> version -> atom (** Return a simple atom, with no version constrain, from a package*) val atom_of_package: package -> atom (** Return a list of simple atoms (ie. with no version constraints) from a set of packages *) val atoms_of_packages: package_set -> atom list (** Return a list of constrained atoms from a set of packages *) val eq_atoms_of_packages: package_set -> atom list (** Return a list of atoms from a list of names (wich can eventually be of the form name.version). Unless [permissive] is set, will abort in case the package is not available *) val atoms_of_names: ?permissive: bool -> OpamState.state -> name_set -> atom list val check_availability: OpamState.state -> atom list -> unit (** {2 Stats} *) val sum: stats -> int opam-1.1.1/src/client/opamAction.mli0000644000175000017500000000344012272210733015554 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) (** OPAM actions *) open OpamTypes open OpamState.Types (** Build and install a package. *) val build_and_install_package: t -> metadata:bool -> package -> unit (** Remove a package. *) val remove_package: t -> metadata:bool -> rm_build:bool -> ?silent:bool -> package -> unit (** Remove all the packages from a solution. This includes the package to delete, to upgrade and to recompile. Return the set of all deleted packages. *) val remove_all_packages: t -> metadata:bool -> solution -> package_set (** Update package metadata *) val update_metadata: t -> installed:package_set -> installed_roots:package_set -> reinstall:package_set -> unit opam-1.1.1/src/client/opamRepositoryCommand.ml0000644000175000017500000004507412272210733017655 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) open OpamTypes open OpamState.Types let log fmt = OpamGlobals.log "REPOSITORY" fmt let print_updated_compilers updates = let print singular plural map = if not (OpamCompiler.Set.is_empty map) then ( if OpamCompiler.Set.cardinal map = 1 then OpamGlobals.msg "%s:\n" singular else OpamGlobals.msg "%s:\n" plural; OpamCompiler.Set.iter (fun comp -> OpamGlobals.msg " - %s\n" (OpamCompiler.to_string comp) ) map ) in print "The following NEW compiler is available" "The following NEW compilers are available" updates.created; print "The following compiler description has been UPDATED" "The following compiler descriptions have been UPDATED" updates.updated; print "The following compiler description has been DELETED" "The following compiler descriptions are been DELETED" updates.deleted let filter_compiler_checksums cs = let keep f = OpamFilename.check_suffix f ".comp" in List.filter keep cs let fix_compiler_descriptions t ~verbose = OpamGlobals.msg "Updating %s/ ...\n" (OpamFilename.prettify_dir (OpamPath.compilers_dir t.root)); let global_index = OpamState.compiler_state t in let repo_index = OpamState.compiler_repository_state t in let niet = String.concat ":" in log "global-index: %s" (OpamCompiler.Map.to_string niet global_index); log "repo-index : %s" (OpamCompiler.Map.to_string niet repo_index); let updated_compilers, new_compilers = let updated_compilers = OpamCompiler.Map.fold (fun comp state set -> if not (OpamCompiler.Map.mem comp global_index) || OpamCompiler.Map.find comp global_index <> state then OpamCompiler.Set.add comp set else set ) repo_index OpamCompiler.Set.empty in OpamCompiler.Set.partition (OpamState.is_compiler_installed t) updated_compilers in log "updated-compilers: %s" (OpamCompiler.Set.to_string updated_compilers); log "new-compilers : %s" (OpamCompiler.Set.to_string new_compilers); let deleted_compilers = OpamCompiler.Set.fold (fun comp map -> if comp = OpamCompiler.system (* system *) || OpamCompiler.Map.mem comp repo_index (* OR available *) then map else OpamCompiler.Set.add comp map ) t.compilers OpamCompiler.Set.empty in log "deleted-compilers: %s" (OpamCompiler.Set.to_string deleted_compilers); (* Delete compiler descritions (unless they are still installed) *) OpamCompiler.Set.iter (fun comp -> if not (OpamState.is_compiler_installed t comp) then let dir = OpamPath.compilers t.root comp in OpamFilename.rmdir dir; ) deleted_compilers; (* Update the compiler description *) OpamCompiler.Set.iter (fun comp -> match OpamState.repository_and_prefix_of_compiler t comp with | None -> () | Some (repo, prefix) -> let files = OpamRepository.compiler_files repo prefix comp in let dir = OpamPath.compilers t.root comp in if OpamFilename.exists_dir dir then OpamFilename.rmdir dir; OpamFilename.mkdir dir; List.iter (fun file -> OpamFilename.copy_in file dir ) files; ) (OpamCompiler.Set.union updated_compilers new_compilers); let updates = { created = new_compilers; updated = updated_compilers; deleted = deleted_compilers; changed = OpamCompiler.Set.empty; (* we don't reinstall compilers yet *) } in if verbose then print_updated_compilers updates; updates let print_updated_packages t updates = let print singular plural map fn = if not (OpamPackage.Set.is_empty map) then ( if OpamPackage.Set.cardinal map = 1 then OpamGlobals.msg "%s:\n" singular else OpamGlobals.msg "%s:\n" plural; OpamPackage.Set.iter (fun nv -> match fn nv with | None -> OpamGlobals.msg " - %s\n" (OpamPackage.to_string nv) | Some s -> OpamGlobals.msg " - %s [%s]\n" (OpamPackage.to_string nv) s ) map ) in let installed_switches nv = let installed = OpamState.installed_versions t (OpamPackage.name nv) in let installed = try OpamPackage.Map.find nv installed with Not_found -> [] in (* XXX: should never happen *) match installed with | [] -> None | _ -> Some ( Printf.sprintf "%s (%s)" (OpamPackage.Version.to_string (OpamPackage.version nv)) (OpamMisc.pretty_list (List.map OpamSwitch.to_string installed)) ) in let none _ = None in print "The following NEW package is available" "The following NEW packages are available" updates.created none; print "The following package has been CHANGED upstream and needs to be recompiled" "The following packages have been CHANGED upstream and need to be recompiled" updates.changed installed_switches; print "The following package has been UPDATED upstream" "The following packages have been UPDATED upstream" updates.updated none; print "The following package has been DELETED" "The following packages have been DELETED" updates.deleted none let print_updated_dev_packages pinned_packages = let print singular plural map = if not (OpamPackage.Set.is_empty map) then ( if OpamPackage.Set.cardinal map = 1 then OpamGlobals.msg "%s:\n" singular else OpamGlobals.msg "%s:\n" plural; OpamPackage.Set.iter (fun nv -> OpamGlobals.msg " - %s\n" (OpamPackage.to_string nv) ) map ) in print "The following DEV package needs to be upgraded" "The following DEV packages need to be upgraded" pinned_packages (* Check for updates in pinned packages *) let update_dev_packages t ~verbose packages = log "update-dev-packages updates %s" (OpamPackage.Set.to_string packages); let updates = OpamState.update_dev_packages t in if verbose then print_updated_dev_packages updates; updates let filter_package_checksums cs = let keep f = match OpamFilename.Base.to_string (OpamFilename.basename f) with | "opam" | "descr" -> false | _ -> true in List.filter keep cs (* Update the package contents, display the new packages and update reinstall *) let fix_package_descriptions t ~verbose = OpamGlobals.msg "Updating %s/ ...\n" (OpamFilename.prettify_dir (OpamPath.packages_dir t.root)); let global_index = OpamState.package_state t in let repo_index = OpamState.package_repository_state t in (* let niet = String.concat ":" in *) (* log "global-index: %s" (OpamPackage.Map.to_string niet global_index); *) (* log "repo-index : %s" (OpamPackage.Map.to_string niet repo_index); *) let updated_packages, new_packages = let updated_packages = OpamPackage.Map.fold (fun nv state set -> if not (OpamPackage.Map.mem nv global_index) || OpamPackage.Map.find nv global_index <> state then OpamPackage.Set.add nv set else set ) repo_index OpamPackage.Set.empty in OpamPackage.Set.partition (fun nv -> OpamPackage.Map.mem nv global_index ) updated_packages in let all_installed = OpamState.all_installed t in let changed_packages = OpamPackage.Set.inter all_installed updated_packages in let missing_installed_packages = OpamPackage.Set.filter (fun nv -> try match OpamPackage.Map.find nv global_index with | [] -> OpamPackage.Map.mem nv repo_index | _ -> false with Not_found -> true ) all_installed in log "new-packages : %s" (OpamPackage.Set.to_string new_packages); log "updated-packages : %s" (OpamPackage.Set.to_string updated_packages); log "changed-packages : %s" (OpamPackage.Set.to_string changed_packages); log "missing-installed: %s" (OpamPackage.Set.to_string missing_installed_packages); let deleted_packages = OpamPackage.Set.filter (fun nv -> not (OpamPackage.is_pinned nv (* pinned*) || OpamPackage.Map.mem nv repo_index) (* OR available *) ) t.packages in log "deleted-packages: %s" (OpamPackage.Set.to_string deleted_packages); (* Notify only about deleted packages that are installed or were just removed (ie ignore the one that were removed from upstream but still have data locally because they used to be installed) *) let upstream_deleted_packages = OpamPackage.Set.filter (fun nv -> OpamPackage.Set.mem nv all_installed || not (OpamFilename.exists (OpamPath.opam t.root nv))) deleted_packages in (* Remove the deleted packages' data (unless they are still installed) *) OpamPackage.Set.iter (fun nv -> if not (OpamPackage.Set.mem nv all_installed) then ( OpamFilename.rmdir (OpamPath.packages t.root nv); OpamFilename.remove (OpamPath.archive t.root nv); )) deleted_packages; (* that's not a good idea *at all* to enable this hook if you are not in a testing environment *) OpamPackage.Map.iter (fun nv _ -> if !OpamGlobals.sync_archives then ( log "download %s" (OpamFilename.to_string (OpamPath.archive t.root nv)); match OpamState.download_archive t nv with | None | Some _ -> () ) ) repo_index; (* Do not recompile a package if only only OPAM or descr files have changed. We recompile a package: - if both global and repo states have an archive file and the checksums of important files have changed; - if both global and repo states don't have an archive file and the checksums of important files have changed; - if only one of them have an archive file, if the checksums of the important files without the archive have changed. *) let changed_packages = OpamPackage.Set.filter (fun nv -> let archive_g, checksums_g = OpamState.package_partial_state t nv ~archive:true in let archive_r, checksums_r = OpamState.package_repository_partial_state t nv ~archive:true in if archive_g = archive_r then checksums_g <> checksums_r else let _, checksums_g = OpamState.package_partial_state t nv ~archive:false in let _, checksums_r = OpamState.package_repository_partial_state t nv ~archive:false in checksums_g <> checksums_r ) changed_packages in log "packages-to-reinstall: %s" (OpamPackage.Set.to_string changed_packages); (* Update the package descriptions *) OpamPackage.Set.iter (fun nv -> match OpamState.repository_and_prefix_of_package t nv with | None -> () | Some (repo, prefix) -> let dir = OpamPath.packages t.root nv in if OpamFilename.exists_dir dir then OpamFilename.rmdir dir; if OpamPackage.Set.mem nv all_installed then let root = OpamPath.Repository.packages repo prefix nv in let files = OpamRepository.package_files repo prefix nv ~archive:false in assert (files <> []); OpamFilename.mkdir dir; List.iter (fun file -> OpamFilename.copy_in ~root file dir ) files; OpamFilename.remove (OpamPath.archive t.root nv); OpamFilename.remove (OpamPath.Repository.archive repo nv); ) (OpamPackage.Set.union missing_installed_packages updated_packages); (* Display some warnings/errors *) OpamPackage.Set.iter (fun nv -> let file = OpamPath.Switch.Overlay.opam t.root t.switch nv in let file = if OpamFilename.exists file then file else OpamPath.opam t.root nv in if not (OpamFilename.exists file) then if OpamPackage.Map.mem nv repo_index then OpamGlobals.error_and_exit "fatal: %s is missing" (OpamFilename.prettify file) else let installed = OpamState.installed_versions t (OpamPackage.name nv) in let switches = OpamPackage.Map.find nv installed in let switches_string = OpamMisc.pretty_list (List.map OpamSwitch.to_string switches) in OpamGlobals.warning "%s is installed in %s but it does not have metadata." (OpamPackage.to_string nv) switches_string ) t.installed; let updates = { created = new_packages; updated = OpamPackage.Set.diff updated_packages changed_packages; deleted = upstream_deleted_packages; changed = changed_packages; } in if verbose then print_updated_packages t updates; (* update $opam/$oversion/reinstall for all installed switches *) OpamState.add_to_reinstall ~all:true t updates.changed; updates let compare_repo t r1 r2 = OpamRepository.compare (OpamState.find_repository t r1) (OpamState.find_repository t r2) let update_package_index t = let file = OpamPath.package_index t.root in OpamGlobals.msg "Updating %s ...\n" (OpamFilename.prettify file); let package_index = OpamState.package_index t in OpamFile.Package_index.write file package_index; { t with package_index } let update_compiler_index t = let file = OpamPath.compiler_index t.root in OpamGlobals.msg "Updating %s ...\n" (OpamFilename.prettify file); let compiler_index = OpamState.compiler_index t in OpamFile.Compiler_index.write file compiler_index; { t with compiler_index } (* update the repository config file: ~/.opam/repo//config *) let update_config t repos = log "update-config %s" (OpamMisc.pretty_list (List.map OpamRepositoryName.to_string repos)); let new_config = OpamFile.Config.with_repositories t.config repos in OpamFile.Config.write (OpamPath.config t.root) new_config let fix_descriptions ?(save_cache=true) t ~verbose = let t = update_compiler_index t in let _ = fix_compiler_descriptions t ~verbose in let t = update_package_index t in let _ = fix_package_descriptions t ~verbose in if save_cache then OpamState.rebuild_state_cache () let () = OpamState.fix_descriptions_hook := fix_descriptions (* Remove any remaining of [repo] from OPAM state *) let cleanup t repo = log "cleanup %s" (OpamRepositoryName.to_string repo.repo_name); let repos = OpamRepositoryName.Map.keys t.repositories in update_config t (List.filter ((<>) repo.repo_name) repos); OpamFilename.rmdir repo.repo_root; fix_descriptions t ~verbose:true let priority repo_name ~priority = log "repository-priority"; (* 1/ update the config file *) let t = OpamState.load_state ~save_cache:false "repository-priority" in let repo = OpamState.find_repository t repo_name in let config_f = OpamPath.Repository.config repo in let config = let config = OpamFile.Repo_config.read config_f in { config with repo_priority = priority } in OpamFile.Repo_config.write config_f config; (* relink the compiler and package descriptions *) fix_descriptions t ~verbose:true let add name kind address ~priority:prio = log "repository-add"; let t = OpamState.load_state "repository-add" in let repo = { repo_name = name; repo_kind = kind; repo_address = address; repo_priority = min_int; (* we initially put it as low-priority *) repo_root = OpamPath.Repository.create t.root name; } in if OpamState.mem_repository t name then OpamGlobals.error_and_exit "%s is already a remote repository" (OpamRepositoryName.to_string name) else ( try OpamRepository.init repo with | OpamRepository.Unknown_backend -> OpamGlobals.error_and_exit "\"%s\" is not a supported backend" (string_of_repository_kind repo.repo_kind) | e -> cleanup t repo; raise e ); if kind = `local then ( let repo_dir = OpamFilename.Dir.of_string (string_of_address address) in let pkgdir = OpamPath.packages_dir repo_dir in let compdir = OpamPath.compilers_dir repo_dir in if not (OpamFilename.exists_dir pkgdir) && not (OpamFilename.exists_dir compdir) then OpamGlobals.warning "%S doesn't contain a \"packages\" nor a \"compilers\" directory.\n\ Is it really the directory of your repo ? \ (\"opam remote remove %s\" to revert)" (OpamFilename.Dir.to_string repo_dir) (OpamRepositoryName.to_string name) ); log "Adding %s" (OpamRepository.to_string repo); update_config t (repo.repo_name :: OpamRepositoryName.Map.keys t.repositories); try let prio = match prio with | Some p -> p | None -> if OpamRepositoryName.Map.is_empty t.repositories then 0 else let max_prio = OpamRepositoryName.Map.fold (fun _ { repo_priority } m -> max repo_priority m) t.repositories min_int in 10 + max_prio in OpamState.remove_state_cache (); priority name ~priority:prio; with e -> cleanup t repo; raise e let remove name = log "repository-remove"; let t = OpamState.load_state "repository-remove" in let repo = OpamState.find_repository t name in cleanup t repo let list ~short = log "repository-list"; let t = OpamState.load_state "repository-list" in if short then ( let repos = List.map (fun r -> OpamRepositoryName.to_string r.repo_name) (OpamState.sorted_repositories t) in let pinned = List.map OpamPackage.Name.to_string (OpamPackage.Name.Map.keys t.pinned) in let all = repos @ pinned in OpamGlobals.msg "%s\n" (String.concat " " all) ) else ( let pretty_print r = OpamGlobals.msg "%4d %-7s %10s %s\n" r.repo_priority (Printf.sprintf "[%s]" (string_of_repository_kind r.repo_kind)) (OpamRepositoryName.to_string r.repo_name) (string_of_address r.repo_address) in let repos = OpamState.sorted_repositories t in List.iter pretty_print repos ) opam-1.1.1/src/client/opamRepositoryCommand.mli0000644000175000017500000000433212272210733020016 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) (** Repository sub-command functions. *) open OpamState.Types open OpamTypes (** Update the package index. *) val update_package_index: t -> t (** Update the compiler index. *) val update_compiler_index: t -> t (** Update the given dev packages. *) val update_dev_packages: t -> verbose:bool -> package_set -> package_set (** Fix the compiler descriptions and display the changes if [verbose] is set. *) val fix_compiler_descriptions: t -> verbose:bool -> compiler_set updates (** Fix the the package descriptions and display the changes if [verbose] is set. *) val fix_package_descriptions: t -> verbose:bool -> package_set updates (** Fix all the package and compiler descriptions. *) val fix_descriptions: ?save_cache:bool -> t -> verbose:bool -> unit (** List the available repositories. *) val list: short:bool -> unit (** Add a new repository. *) val add: repository_name -> repository_kind -> address -> priority:int option -> unit (** Remove a repository. *) val remove: repository_name -> unit (** Set a repository priority. *) val priority: repository_name -> priority:int -> unit opam-1.1.1/src/client/opamConfigCommand.ml0000644000175000017500000003124512272210733016676 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) let log fmt = OpamGlobals.log "CONFIG" fmt open OpamTypes open OpamState.Types let full_sections l = String.concat " " (List.map OpamVariable.Section.Full.to_string l) let string_of_config t = Printf.sprintf "rec=%b bytecode=%b link=%b options=%s" t.conf_is_rec t.conf_is_byte t.conf_is_link (full_sections t.conf_options) let need_globals ns = ns = [] || List.mem OpamPackage.Name.global_config ns || List.mem (OpamPackage.Name.of_string "global") ns (* Implicit variables *) let implicits t ns = let global_implicits = if need_globals ns then List.map (fun variable -> OpamVariable.Full.create_global OpamPackage.Name.global_config (OpamVariable.of_string variable) ) [ "ocaml-version"; "preinstalled" ] else [] in let names = OpamPackage.Name.Set.of_list ( if ns = [] then List.map OpamPackage.name (OpamPackage.Set.elements t.packages) else ns ) in (* keep only the existing packages *) let names = OpamPackage.Name.Set.filter (fun n -> OpamPackage.Set.exists (fun nv -> OpamPackage.name nv = n) t.packages ) names in List.fold_left (fun accu variable -> OpamPackage.Name.Set.fold (fun name accu -> OpamVariable.Full.create_global name (OpamVariable.of_string variable) :: accu ) names accu ) global_implicits [ "installed"; "enable" ] (* List all the available variables *) let list ns = log "config-list"; let t = OpamState.load_state "config-list" in let globals = if need_globals ns then [OpamPackage.Name.global_config, OpamState.dot_config t OpamPackage.Name.global_config] else [] in let configs = globals @ OpamPackage.Set.fold (fun nv l -> let name = OpamPackage.name nv in let file = OpamState.dot_config t (OpamPackage.name nv) in (name, file) :: l ) t.installed [] in let variables = implicits t ns @ List.fold_left (fun accu (name, config) -> (* add all the global variables *) let globals = List.fold_left (fun accu variable -> OpamVariable.Full.create_global name variable :: accu ) accu (OpamFile.Dot_config.variables config) in (* then add the local section variables *) List.fold_left (fun accu section -> let variables = OpamFile.Dot_config.Section.variables config section in List.fold_left (fun accu variable -> OpamVariable.Full.create_local name section variable :: accu ) accu variables ) globals (OpamFile.Dot_config.Section.available config) ) [] configs in let contents = List.map (fun v -> v, OpamState.contents_of_variable_exn t OpamVariable.Map.empty v) variables in List.iter (fun (variable, contents) -> OpamGlobals.msg "%-40s %s\n" (OpamVariable.Full.to_string variable) (OpamVariable.string_of_variable_contents contents) ) (List.rev contents) (* Return the transitive closure of dependencies sorted in topological order *) let get_transitive_dependencies t ?(depopts = false) names = let universe = OpamState.universe t Depends in (* Compute the transitive closure of dependencies *) let packages = OpamPackage.Set.of_list (List.map (OpamState.find_installed_package_by_name t) names) in OpamSolver.dependencies ~depopts universe packages let includes ~is_rec names = log "config-includes"; let t = OpamState.load_state "config-includes" in let deps = if is_rec then List.map OpamPackage.name (get_transitive_dependencies t ~depopts:true ~installed:true names) else names in log "deps: %s" (String.concat ", " (List.map OpamPackage.Name.to_string deps)); let includes = List.fold_left (fun accu n -> "-I" :: OpamFilename.Dir.to_string (OpamPath.Switch.lib t.root t.switch n) :: accu ) [] (List.rev deps) in OpamGlobals.msg "%s\n" (String.concat " " includes) let config c = log "config-options"; let t = OpamState.load_state "config-options" in let comp = OpamState.compiler_comp t t.compiler in let names = OpamMisc.filter_map (fun (n,_) -> if OpamPackage.Set.exists (fun nv -> OpamPackage.name nv = n) t.installed then Some n else None) (OpamFormula.atoms (OpamFile.Comp.packages comp)) @ List.map OpamVariable.Section.Full.package c.conf_options in (* Compute the transitive closure of package dependencies *) let package_deps = if c.conf_is_rec then List.map OpamPackage.name (get_transitive_dependencies t ~depopts:true ~installed:true names) else names in (* Map from libraries to package *) (* NOTES: we check that the set of packages/libraries given on the command line is consistent, ie. there isn't two libraries with the same name in the transitive closure of depedencies *) let library_map = List.fold_left (fun accu n -> let nv = OpamState.find_installed_package_by_name t n in let opam = OpamState.opam t nv in let sections = (OpamFile.OPAM.libraries opam) @ (OpamFile.OPAM.syntax opam) in List.iter (fun s -> if OpamVariable.Section.Map.mem s accu then OpamGlobals.error_and_exit "Conflict: the library %s appears in %s and %s" (OpamVariable.Section.to_string s) (OpamPackage.Name.to_string n) (OpamPackage.Name.to_string (OpamVariable.Section.Map.find s accu)) ) sections; List.fold_left (fun accu s -> OpamVariable.Section.Map.add s n accu) accu sections ) OpamVariable.Section.Map.empty package_deps in (* Compute the transitive closure of libraries dependencies *) let library_deps = let graph = OpamVariable.Section.G.create () in let todo = ref OpamVariable.Section.Set.empty in let add_todo s = if OpamVariable.Section.Map.mem s library_map then todo := OpamVariable.Section.Set.add s !todo else OpamGlobals.error_and_exit "Unbound section %S" (OpamVariable.Section.to_string s) in let seen = ref OpamVariable.Section.Set.empty in (* Init the graph with vertices from the command-line *) (* NOTES: we check that [todo] is initialized before the [loop] *) List.iter (fun s -> let name = OpamVariable.Section.Full.package s in let sections = match OpamVariable.Section.Full.section s with | None -> let config = OpamState.dot_config t name in OpamFile.Dot_config.Section.available config | Some s -> [s] in List.iter (fun s -> OpamVariable.Section.G.add_vertex graph s; add_todo s; ) sections ) c.conf_options; (* Also add the [requires] field of the compiler description *) List.iter (fun s -> OpamVariable.Section.G.add_vertex graph s; add_todo s ) (OpamFile.Comp.requires comp); (* Least fix-point to add edges and missing vertices *) let rec loop () = if not (OpamVariable.Section.Set.is_empty !todo) then let s = OpamVariable.Section.Set.choose !todo in todo := OpamVariable.Section.Set.remove s !todo; seen := OpamVariable.Section.Set.add s !seen; let name = OpamVariable.Section.Map.find s library_map in let config = OpamState.dot_config t name in let childs = OpamFile.Dot_config.Section.requires config s in (* keep only the build reqs which are in the package dependency list and the ones we haven't already seen *) List.iter (fun child -> OpamVariable.Section.G.add_vertex graph child; OpamVariable.Section.G.add_edge graph child s; ) childs; let new_childs = List.filter (fun s -> OpamVariable.Section.Map.mem s library_map && not (OpamVariable.Section.Set.mem s !seen) ) childs in todo := OpamVariable.Section.Set.union (OpamVariable.Section.Set.of_list new_childs) !todo; loop () in loop (); let nodes = ref [] in OpamVariable.Section.graph_iter (fun n -> nodes := n :: !nodes) graph; !nodes in let fn_comp = match c.conf_is_byte, c.conf_is_link with | true , true -> OpamFile.Comp.bytelink | true , false -> OpamFile.Comp.bytecomp | false, true -> OpamFile.Comp.asmlink | false, false -> OpamFile.Comp.asmcomp in let fn = match c.conf_is_byte, c.conf_is_link with | true , true -> OpamFile.Dot_config.Section.bytelink | true , false -> OpamFile.Dot_config.Section.bytecomp | false, true -> OpamFile.Dot_config.Section.asmlink | false, false -> OpamFile.Dot_config.Section.asmcomp in let strs = fn_comp comp :: List.fold_left (fun accu s -> let name = OpamVariable.Section.Map.find s library_map in let config = OpamState.dot_config t name in fn config s :: accu ) [] library_deps in let output = String.concat " " (List.flatten strs) in log "OUTPUT: %S" output; OpamGlobals.msg "%s\n" output let print_env env = List.iter (fun (k,v) -> OpamGlobals.msg "%s=%S; export %s;\n" k v k; ) env let print_csh_env env = List.iter (fun (k,v) -> OpamGlobals.msg "setenv %s %S;\n" k v; ) env let print_sexp_env env = OpamGlobals.msg "(\n"; List.iter (fun (k,v) -> OpamGlobals.msg " (%S %S)\n" k v; ) env; OpamGlobals.msg ")\n" let print_fish_env env = List.iter (fun (k,v) -> OpamGlobals.msg "set -x %s %s;\n" k (String.concat " " (OpamMisc.split v ':')); ) env let env ~csh ~sexp ~fish= log "config-env"; let t = OpamState.load_env_state "config-env" in let env = OpamState.get_opam_env t in if sexp then print_sexp_env env else if csh then print_csh_env env else if fish then print_fish_env env else print_env env let subst fs = log "config-substitute"; let t = OpamState.load_state "config-substitute" in List.iter (OpamState.substitute_file t OpamVariable.Map.empty) fs let quick_lookup v = let name = OpamVariable.Full.package v in let var = OpamVariable.Full.variable v in if name = OpamPackage.Name.global_config then ( let root = OpamPath.root () in let switch = match !OpamGlobals.switch with | `Command_line s | `Env s -> OpamSwitch.of_string s | `Not_set -> let config = OpamPath.config root in OpamFile.Config.switch (OpamFile.Config.read config) in let config = OpamPath.Switch.config root switch OpamPackage.Name.global_config in let config = OpamFile.Dot_config.read config in if OpamVariable.to_string var = "switch" then Some (S (OpamSwitch.to_string switch)) else match OpamVariable.Full.section v with | None -> OpamFile.Dot_config.variable config var | Some s -> OpamFile.Dot_config.Section.variable config s var ) else None let variable v = log "config-variable"; let contents = match quick_lookup v with | Some c -> c | None -> let t = OpamState.load_state "config-variable" in OpamState.contents_of_variable_exn t OpamVariable.Map.empty v in OpamGlobals.msg "%s\n" (OpamVariable.string_of_variable_contents contents) let setup user global = log "config-setup"; let t = OpamState.load_state "config-setup" in OpamState.update_setup t user global let setup_list shell dot_profile = log "config-setup-list"; let t = OpamState.load_state "config-setup-list" in OpamState.display_setup t shell dot_profile let exec command = log "config-exex command=%s" command; let t = OpamState.load_state "config-exec" in let cmd, args = match OpamMisc.split command ' ' with | [] -> OpamSystem.internal_error "Empty command" | h::_ as l -> h, Array.of_list l in let env = let env = OpamState.get_full_env t in let env = List.rev_map (fun (k,v) -> k^"="^v) env in Array.of_list env in Unix.execvpe cmd args env opam-1.1.1/src/client/opamState.mli0000644000175000017500000003223712272210733015425 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) (** OPAM client state *) open OpamTypes (** Client state *) module Types: sig type t = { (** Is the state partial ? TODO: split-up global vs. repository state *) partial: bool; (** The global OPAM root path *) root: OpamPath.t; (** The current active switch *) switch: switch; (** The current compiler name (corresponding to a .comp file) *) compiler: compiler; (** The current version of the compiler *) compiler_version: compiler_version lazy_t; (** The list of OPAM files *) opams: OpamFile.OPAM.t package_map; (** The list of repositories *) repositories: OpamFile.Repo_config.t repository_name_map; (** The list of packages *) packages: package_set; (** The list of packages, keeping the one available for the current compiler version *) available_packages: package_set Lazy.t; (** The association list between switch and compiler *) aliases: OpamFile.Aliases.t; (** The list of compiler available to install *) compilers: compiler_set; (** The list of pinned packages *) pinned: OpamFile.Pinned.t; (** The list of installed packages *) installed: OpamFile.Installed.t; (** The list of packages explicitly installed by the user *) installed_roots: OpamFile.Installed_roots.t; (** The list of packages which needs to be reinsalled *) reinstall: OpamFile.Reinstall.t; (** The main configuration file *) config: OpamFile.Config.t; (** Package index *) package_index: OpamFile.Package_index.t; (** Compiler index *) compiler_index: OpamFile.Compiler_index.t; } end type state = Types.t (** Load the client state. The string argument is to identify to call site. *) val load_state: ?save_cache:bool -> string -> state (** Rebuild the state cache. *) val rebuild_state_cache: unit -> unit (** Remove the state cache *) val remove_state_cache: unit -> unit (** Load state associated to env variables. All other fields are left empty. *) val load_env_state: string -> state (** Create a universe from the current state *) val universe: state -> user_action -> universe (** {2 Environment} *) (** Get the current environment. *) val get_full_env: state -> env (** Get only environment modified by OPAM. *) val get_opam_env: state -> env (** Update an environment. *) val add_to_env: state -> env -> (string * string * string) list -> env (** Print a warning if the environment is not set-up properly on init. *) val print_env_warning_at_init: state -> user_config -> unit (** Print a warning if the environment is not set-up properly on switch. *) val print_env_warning_at_switch: state -> unit (** {2 Initialisation} *) (** Update the global and user configuration by asking some questions. *) val update_setup_interactive: state -> shell -> filename -> bool (** Display the global and user configuration for OPAM. *) val display_setup: state -> shell -> filename -> unit (** Update the user configuration. *) val update_setup: state -> user_config option -> global_config option -> unit (** {2 Substitutions} *) (** Compute the value of a variable *) val contents_of_variable: state -> variable_map -> full_variable -> variable_contents option (** Compute the value of a variable. Raise [Exit] if the variable is not valid. *) val contents_of_variable_exn: state -> variable_map -> full_variable -> variable_contents (** Substitute a string *) val substitute_string: state -> variable_map -> string -> string (** Substitute file *) val substitute_file: state -> variable_map -> basename -> unit (** {2 Filters} *) (** Evaluate a filter *) val eval_filter: state -> variable_map -> filter option -> bool (** Filter a list of commands by: - evaluating the substitution strings; and - removing the commands with a filter evaluating to "false" *) val filter_commands: state -> variable_map -> command list -> string list list (** {2 Helpers} *) (** Return the OPAM file for the given package *) val opam: state -> package -> OpamFile.OPAM.t (** Return the OPAM file for the given package *) val opam_opt: state -> package -> OpamFile.OPAM.t option (** Return the URL file for the given package *) val url: state -> package -> OpamFile.URL.t option (** Return the Descr file for the given package *) val descr: state -> package -> OpamFile.Descr.t (** Return the Descr file for the given package *) val descr_opt: state -> package -> OpamFile.Descr.t option (** Return the files/ directory overlay for the given package *) val files: state -> package -> dirname option (** Return the compiler description *) val compiler_comp: state -> compiler -> OpamFile.Comp.t (** {2 Repositories} *) (** Pretty print a map of repositories *) val string_of_repositories: OpamFile.Repo_config.t repository_name_map -> string (** Builds a map which says in which repository the latest metadata for a given package are. The function respect the bustom priorities given by the order of [priorities]. *) val package_index: state -> (repository_name * string option) package_map (** Build a map which says in which repository the latest metadata for a given compiler is. *) val compiler_index: state -> (repository_name * string option) compiler_map (** Sort repositories by priority. *) val sorted_repositories: state -> repository list (** Check whether a repository exists. *) val mem_repository: state -> repository_name -> bool (** Find a given repostiory. Exit the program if no such repository name exists. *) val find_repository: state -> repository_name -> repository (** Find a given repostiory. *) val find_repository_opt: state -> repository_name -> repository option (** Check the redirections. *) val redirect: state -> repository -> (repository * filter option) option (** {2 Compilers} *) (** (Re-)install the configuration for a given root and switch *) val install_global_config: dirname -> switch -> unit (** Install the given compiler *) val install_compiler: state -> quiet:bool -> switch -> compiler -> unit (** Write the right compiler switch in ~/.opam/config *) val update_switch_config: state -> switch -> unit (** Get the packages associated with the given compiler *) val get_compiler_packages: state -> compiler -> atom list (** Is a compiler installed ? *) val is_compiler_installed: state -> compiler -> bool (** Is a switch installed ? *) val is_switch_installed: state -> switch -> bool (** Global compiler state *) val compiler_state: state -> checksums compiler_map (** Repository state *) val compiler_repository_state: state -> checksums compiler_map (** Return the active repository for a given compiler *) val repository_and_prefix_of_compiler: state -> compiler -> (repository * string option) option (** {2 Packages} *) (** Check whether a package name is installed *) val is_name_installed: state -> name -> bool (** Return whether a package is installed *) val is_package_installed: state -> package -> bool (** Return the installed package with the right name *) val find_installed_package_by_name: state -> name -> package (** Return all the packages with the given name *) val find_packages_by_name: state -> name -> package_set option (** Return a map from package names to package installed version *) val installed_map: state -> version name_map (** Return the base packages *) val base_packages: name list (** Return all the collection of installed packages, for all the available packages *) val all_installed: state -> package_set (** Return a map containing the switch where a given package is installed. *) val installed_versions: state -> name -> switch list package_map (** Download the OPAM-package archive ($name.$version+opam.tar.gz) *) val download_archive: state -> package -> filename option (** Download the upstream archive, add the eventual additional files and return the directory.. *) val download_upstream: state -> package -> dirname -> generic_file option (** Global package state. *) val package_state: state -> checksums package_map (** Global & partial package state. *) val package_partial_state: state -> package -> archive:bool -> bool * checksums (** Repository state *) val package_repository_state: state -> checksums package_map (** Repository & partial package state. *) val package_repository_partial_state: state -> package -> archive:bool -> bool * checksums (** Get the active repository for a given package *) val repository_of_package: state -> package -> repository option (** Get the active repository for a given package *) val repository_and_prefix_of_package: state -> package -> (repository * string option) option (** Add the given packages to the set of package to reinstall. If [all] is set, this is done for ALL the switches (useful when a package change upstream for instance). If not, only the reinstall state of the current switch is changed. *) val add_to_reinstall: state -> all:bool -> package_set -> unit (** Return the files for a given package *) val copy_files: state -> package -> dirname -> unit (** Copy the repository metadata into the global state. *) val install_metadata: state -> package -> unit (** Remove some metadata from the global state if they are not used anymore. *) val remove_metadata: state -> package_set -> unit (** {2 Development packages} *) (** Get all the development packages. This include the one locally pinned (for the current switch) and the global dev packages. *) val dev_packages: state -> package_set (** [update_dev_packages t] checks for upstream changes for packages first in the switch cache and then in the global cache. Return the packages whose contents have changed upstream. Side-effect: update the reinstall files. *) val update_dev_packages: state -> package_set (** Check whether a package is a development package *) val is_dev_package: state -> package -> bool (** {2 Configuration files} *) (** Return the .config file for the given package *) val dot_config: state -> name -> OpamFile.Dot_config.t (** {2 Locks} *) (** Apply a function while taking the right locks *) val check: lock -> unit (** {2 Pinned packages} *) (** Is the package name pinned ? *) val is_pinned: state -> name -> bool (** Is the package locally pinned ? (ie. not a version pinning) *) val is_locally_pinned: state -> name -> bool (** Returns the versionned package corresponding to the version the package has been pinned to. If not pinned, returns [package] unchanged *) val pinning_version: state -> package -> package (** Return the URL file associated with a locally pinned package. *) val url_of_locally_pinned_package: state -> name -> OpamFile.URL.t (** Return the repository associtated with a locally pinned package. *) val repository_of_locally_pinned_package: state -> name -> repository (** {2 Overlays} *) (** Compute the overlay package for a given name. It return the higher package available with this name. *) val overlay_of_name: state -> name -> package (** Cache an OPAM file *) val add_opam_overlay: state -> package -> OpamFile.OPAM.t -> unit (** Cache an URL file *) val add_url_overlay: state -> package -> OpamFile.URL.t -> unit (** Cache a descr file *) val add_descr_overlay: state -> package -> OpamFile.Descr.t -> unit (** Cache additional files *) val add_files_overlay: state -> package -> dirname -> filename list -> unit (** Add overlay files for a pinned package *) val add_pinned_overlay: state -> name -> unit (** Remove all overlay files *) val remove_overlay: state -> package -> unit (** {2 System compilers} *) (** Create {i $opam/compilers/system.com}. Take the global root and the new system compiler version as arguments. *) val create_system_compiler_description: dirname -> compiler_version option -> unit (** {2 Jobs} *) val jobs: state -> int (** {2 Misc} *) (** Ask the user to press Y/y/N/n to continue *) val confirm: ('a, unit, string, bool) format4 -> 'a (** Consistency checks: do the base package for the current compiler are installed ? *) val check_base_packages: state -> unit (** / **) (** Switch reinstall hook. *) val switch_reinstall_hook: (switch -> unit) ref (** Update hook *) val fix_descriptions_hook: (?save_cache:bool -> state -> verbose:bool -> unit) ref opam-1.1.1/src/client/opamPinCommand.ml0000644000175000017500000001543412272210733016221 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) open OpamTypes open OpamState.Types let log fmt = OpamGlobals.log "COMMAND" fmt let string_of_pin_kind_o o = match kind_of_pin_option o with | Some k -> string_of_pin_kind k | None -> "none" let pin ~force action = log "pin %s" (string_of_pin action); let t = OpamState.load_state "pin" in let pin_f = OpamPath.Switch.pinned t.root t.switch in let pins = OpamFile.Pinned.safe_read pin_f in let name = action.pin_package in let update_set set old cur save = if OpamPackage.Set.mem old set then save (OpamPackage.Set.add cur (OpamPackage.Set.remove old set)) in let update_config pins = let packages = OpamPackage.packages_of_name t.packages name in OpamPackage.Set.iter (fun nv -> OpamFilename.rmdir (OpamPath.Switch.build t.root t.switch nv); OpamFilename.rmdir (OpamPath.Switch.dev_package t.root t.switch nv); ) packages; if force then OpamState.add_to_reinstall t ~all:false packages; OpamFile.Pinned.write pin_f pins in match action.pin_option with | Edit -> if not (OpamState.is_pinned t name) then OpamGlobals.error_and_exit "%s is not pinned." (OpamPackage.Name.to_string name); let editor = try OpamMisc.getenv "OPAM_EDITOR" with Not_found -> try OpamMisc.getenv "VISUAL" with Not_found -> try OpamMisc.getenv "EDITOR" with Not_found -> "nano" in let nv = OpamPackage.pinned name in let file = OpamPath.Switch.Overlay.opam t.root t.switch nv in if not (OpamFilename.exists file) then OpamState.add_pinned_overlay t name; ignore (Sys.command (Printf.sprintf "%s %s" editor (OpamFilename.to_string file))) | Unpin -> if not (OpamPackage.Name.Map.mem name pins) then OpamGlobals.error_and_exit "%s is not pinned." (OpamPackage.Name.to_string name); begin match OpamPackage.Name.Map.find name pins with | Version _ -> () | _ -> if not force && OpamState.is_name_installed t name then OpamGlobals.error_and_exit "You must remove the package before unpinning it (or use --force)."; end; let nv_pin = OpamPackage.pinned name in let nv_v = OpamState.pinning_version t nv_pin in update_set t.installed nv_pin nv_v (OpamFile.Installed.write (OpamPath.Switch.installed t.root t.switch)); update_set t.installed_roots nv_pin nv_v (OpamFile.Installed_roots.write (OpamPath.Switch.installed_roots t.root t.switch)); update_config (OpamPackage.Name.Map.remove name pins); OpamState.remove_overlay t nv_pin | _ -> if not force && OpamPackage.Name.Map.mem name pins then ( let current = OpamPackage.Name.Map.find name pins in if current = action.pin_option then OpamGlobals.error_and_exit "Package %s is already pinned to %s." (OpamPackage.Name.to_string name) (string_of_pin_option current) else OpamGlobals.error_and_exit "Cannot pin %s to %s as it is already associated to %s. Use 'opam pin %s \ none' and retry (or use --force)." (OpamPackage.Name.to_string name) (string_of_pin_option action.pin_option) (string_of_pin_option current) (OpamPackage.Name.to_string name); ); let pins = OpamPackage.Name.Map.remove name pins in begin match action.pin_option with | Edit | Unpin -> assert false | Version version -> if OpamState.is_name_installed t name then let nv = OpamState.find_installed_package_by_name t name in if not force && OpamPackage.version nv <> version then OpamGlobals.error_and_exit "Cannot pin %s as its current version is %s. You must install the \ version %s first (or use --force)." (OpamPackage.Name.to_string name) (OpamPackage.Version.to_string (OpamPackage.version nv)) (OpamPackage.Version.to_string version); | Git _ | Darcs _ | Local _ | Hg _ -> if not force && OpamState.is_name_installed t name then OpamGlobals.error_and_exit "Cannot pin %s to a dev version as it is already installed. You must \ remove it first (or use --force)." (OpamPackage.Name.to_string name); end; match OpamState.find_packages_by_name t name with | None -> OpamGlobals.error_and_exit "%s is not a valid package name." (OpamPackage.Name.to_string name) | Some _ -> log "Adding %s(%s) => %s" (string_of_pin_option action.pin_option) (string_of_pin_kind_o action.pin_option) (OpamPackage.Name.to_string name); let pinned = OpamPackage.Name.Map.add name action.pin_option pins in update_config pinned; let t = { t with pinned } in OpamState.add_pinned_overlay t name; (* In case the package is installed (current version or --force) *) let nv_pin = OpamPackage.pinned name in let nv_v = OpamState.pinning_version t nv_pin in update_set t.installed nv_v nv_pin (OpamFile.Installed.write (OpamPath.Switch.installed t.root t.switch)); update_set t.installed_roots nv_v nv_pin (OpamFile.Installed_roots.write (OpamPath.Switch.installed_roots t.root t.switch)) let list () = log "pin_list"; let t = OpamState.load_state "pin-list" in let pins = OpamFile.Pinned.safe_read (OpamPath.Switch.pinned t.root t.switch) in let print n a = let kind = match kind_of_pin_option a with | None -> "" | Some k -> string_of_pin_kind k in OpamGlobals.msg "%-20s %-8s %s\n" (OpamPackage.Name.to_string n) kind (string_of_pin_option a) in OpamPackage.Name.Map.iter print pins opam-1.1.1/src/client/opamSwitchCommand.mli0000644000175000017500000000363012272210733017100 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) (** Switch commands. *) open OpamTypes (** Install a new switch. *) val install: quiet:bool -> warning:bool -> update_config:bool -> switch -> compiler -> unit (** Import a file which contains the packages to install. *) val import: filename option -> unit (** Export a file which contains the installed packages. *) val export: filename option -> unit (** Remove the given compiler switch. *) val remove: switch -> unit (** Switch to the given compiler switch. *) val switch: quiet:bool -> warning:bool -> switch -> unit (** Reinstall the given compiler switch. *) val reinstall: switch -> unit (** Display the current compiler switch. *) val show: unit -> unit (** List all the available compiler switches. *) val list: print_short:bool -> installed:bool -> all:bool -> unit opam-1.1.1/src/client/opamPinCommand.mli0000644000175000017500000000244712272210733016372 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) (** Pin subcommand. *) open OpamTypes (** Manage pinned packages. *) val pin: force:bool -> pin -> unit (** List the pinned packages. *) val list: unit -> unit opam-1.1.1/src/client/client.ocp0000644000175000017500000000074412272210733014744 0ustar i33173i33173comp += [ "-warn-error" "A" ] begin library "opam-client" files = [ "opamState.ml" "opamAction.ml" "opamSolution.ml" "opamSwitchCommand.ml" "opamConfigCommand.ml" "opamRepositoryCommand.ml" "opamPinCommand.ml" "opamClient.ml" "opamArg.ml" ] requires = [ "opam-core" "opam-solver" "opam-repositories" "cmdliner" ] end begin program "opam" files = [ "opamMain.ml" ] requires = [ "opam-client" ] end opam-1.1.1/src/client/opamMain.ml0000644000175000017500000000260512272210733015054 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) open OpamArg let () = at_exit (fun () -> flush stderr; flush stdout; if !OpamGlobals.print_stats then ( OpamFile.print_stats (); OpamSystem.print_stats (); ); OpamJson.output () ); run default commands opam-1.1.1/src/client/opamArg.mli0000644000175000017500000001022312272210733015045 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) (** OPAM command-line arguments *) open OpamTypes open Cmdliner (** {2 Commands} *) (** Type of commands *) type command = unit Term.t * Term.info (** [run default commdands at_exit] build a binary which takes [commands] as subcommand and [default] as default argument (ie. which will be executed when no subcommand is given). [at_exit] is executed before the program exits. *) val run:command -> command list -> unit (** The default list of commands *) val commands: command list (** opam *) val default: command (** opam init *) val init: command (** opam list *) val list: command (** opam show *) val show: command (** opam search *) val search: command (** opam install *) val install: command (** opam remove *) val remove: command (** opam reinstall *) val reinstall: command (** opam update *) val update: command (** opam upgrade *) val upgrade: command (** opam config *) val config: command (** opam repository *) val repository: command (** opam switch *) val switch: command (** opam pin *) val pin: command (** opam help *) val help: command (** {2 Flags} *) (** --short *) val print_short_flag: bool Term.t (** --installed *) val installed_flag: bool Term.t (** --installed-root *) val installed_roots_flag: bool Term.t (** --fish *) val fish_flag: bool Term.t (** --zsh *) val zsh_flag: bool Term.t (** --csh *) val csh_flag: bool Term.t (** --sh *) val sh_flag: bool Term.t (** --dot-profile *) val dot_profile_flag: filename option Term.t (** --http/ --git/ --local *) val repo_kind_flag: repository_kind option Term.t (** --jobs *) val jobs_flag: int option Term.t (** --json *) val json_flag: string option Term.t (** patterns *) val pattern_list: string list Term.t (** package names *) val name_list: name list Term.t (** repositories *) val repository_list: repository_name list Term.t (** parameters *) val param_list: string list Term.t (** {3 Global options} *) (** Abstract type for global options *) type global_options (** Global options *) val global_options: global_options Term.t (** Apply global options *) val apply_global_options: global_options -> unit (** {3 Build options} *) (** Abstract type for build options *) type build_options (** Build options *) val build_options: build_options Term.t (** Applly build options *) val apply_build_options: build_options -> unit (** {3 Converters} *) (** Repository name converter *) val repository_name: repository_name Arg.converter (** Repository address converter *) val address: address Arg.converter (** Filename converter *) val filename: filename Arg.converter (** Dirnam converter *) val dirname: dirname Arg.converter (** Compiler converter *) val compiler: compiler Arg.converter (** Package name converter *) val package_name: name Arg.converter (** {2 Misc} *) (** Enumeration with a default command *) val enum_with_default: (string * ([> `default of string] as 'a)) list -> 'a Arg.converter (** Create an alias for an existing command *) val make_command_alias: unit Term.t * Term.info -> string -> unit Term.t * Term.info opam-1.1.1/src/client/opamSolution.ml0000644000175000017500000004712712272210733016014 0ustar i33173i33173(**************************************************************************) (* *) (* Copyright 2012-2013 OCamlPro *) (* Copyright 2012 INRIA *) (* *) (* All rights reserved.This file is distributed under the terms of the *) (* GNU Lesser General Public License version 3.0 with linking *) (* exception. *) (* *) (* OPAM 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 General Public *) (* License for more details. *) (* *) (**************************************************************************) let log fmt = OpamGlobals.log "SOLUTION" fmt open OpamTypes open OpamState.Types open OpamMisc.OP let post_message ?(failed=false) state action = let pkg = action_contents action in let opam = OpamState.opam state pkg in let messages = OpamFile.OPAM.post_messages opam in let print_message message = if failed then (OpamGlobals.header_msg "%s troobleshooting" (OpamPackage.to_string pkg); OpamGlobals.msg "%s.\n" message) else (OpamGlobals.header_msg "%s information" (OpamPackage.to_string pkg); OpamGlobals.msg "%s.\n" message) in let local_variables = OpamVariable.Map.empty in let local_variables = OpamVariable.Map.add (OpamVariable.of_string "success") (B (not failed)) local_variables in let local_variables = OpamVariable.Map.add (OpamVariable.of_string "failure") (B failed) local_variables in List.iter (fun (message,filter) -> if OpamState.eval_filter state local_variables filter then print_message message) messages let check_solution state = function | No_solution -> OpamGlobals.exit 3 | Error (success, failed, _remaining) -> List.iter (post_message state) success; List.iter (post_message ~failed:true state) failed; OpamGlobals.exit 4 | OK actions -> List.iter (post_message state) actions | Nothing_to_do | Aborted -> () let sum stats = stats.s_install + stats.s_reinstall + stats.s_remove + stats.s_upgrade + stats.s_downgrade let eq_atom name version = name, Some (`Eq, version) let eq_atoms_of_packages set = List.rev_map (fun nv -> eq_atom (OpamPackage.name nv) (OpamPackage.version nv)) (OpamPackage.Set.elements set) let atom_of_package nv = OpamPackage.name nv, None let atoms_of_packages set = List.rev_map atom_of_package (OpamPackage.Set.elements set) let atom_of_name name = name, None let check_availability t atoms = let available = OpamPackage.to_map (Lazy.force t.available_packages) in let check_atom (name, version) = try let versions = OpamPackage.Name.Map.find name available in match version with | Some (`Eq, v) when not (OpamPackage.Version.Set.mem v versions) -> raise Not_found | _ -> () with Not_found -> let version = match version with Some (_, v) -> Some v | None -> None in if OpamPackage.Name.Map.mem name t.pinned then OpamPackage.unavailable_because_pinned name version else OpamPackage.unavailable name version in List.iter check_atom atoms (* transform a name into: - package - <$n,$v> package when name = $n.$v *) let atoms_of_names ?(permissive=false) t names = let packages = OpamPackage.to_map (OpamPackage.Set.union t.packages t.installed) in (* gets back the original capitalization of the package name *) let realname name = let lc_name name = String.lowercase (OpamPackage.Name.to_string name) in let m = OpamPackage.Name.Map.filter (fun p _ -> lc_name name = lc_name p) packages in match OpamPackage.Name.Map.keys m with [name] -> name | _ -> name in let exists name version = OpamPackage.Name.Map.mem name packages && match version with | None -> true | Some v -> let versions = OpamPackage.Name.Map.find name packages in OpamPackage.Version.Set.mem v versions in let atoms = List.rev_map (fun name -> let name = realname name in if exists name None then atom_of_name name else ( (* consider 'name' to be 'name.version' *) let nv = try OpamPackage.of_string (OpamPackage.Name.to_string name) with Not_found -> OpamPackage.unknown name None in let sname = realname (OpamPackage.name nv) in let sversion = OpamPackage.version nv in log "The raw name %S not found, looking for package %s version %s" (OpamPackage.Name.to_string name) (OpamPackage.Name.to_string sname) (OpamPackage.Version.to_string sversion); if exists sname (Some sversion) then eq_atom sname sversion else if exists sname None then OpamPackage.unknown sname (Some sversion) else OpamPackage.unknown sname None )) (OpamPackage.Name.Set.elements names) in if not permissive then check_availability t atoms; atoms (* Pretty-print errors *) let display_error (n, error) = let f action nv = let disp = OpamGlobals.header_error "while %s %s" action (OpamPackage.to_string nv) in match error with | OpamParallel.Process_error r -> disp "%s" (OpamProcess.string_of_result ~color:`red r) | OpamParallel.Internal_error s -> disp "Internal error:\n %s" s | OpamParallel.Package_error s -> disp "%s" s in match n with | To_change (Some o, nv) -> if OpamPackage.Version.compare (OpamPackage.version o) (OpamPackage.version nv) < 0 then f "upgrading to" nv else f "downgrading to" nv | To_change (None, nv) -> f "installing" nv | To_recompile nv -> f "recompiling" nv | To_delete nv -> f "removing" nv (* Prettify errors *) let string_of_errors errors = let actions = List.rev_map fst errors in let packages = List.rev_map action_contents actions in match packages with | [] -> assert false | [h] -> OpamPackage.to_string h | l -> OpamPackage.Set.to_string (OpamPackage.Set.of_list l) let new_variables e = let e = List.filter (fun (_,s,_) -> s="=") e in let e = List.rev_map (fun (v,_,_) -> v) e in OpamMisc.StringSet.of_list e let variable_warnings = ref false let print_variable_warnings t = let variables = ref [] in if not !variable_warnings then ( let warn w = let is_defined s = try let _ = OpamMisc.getenv s in true with Not_found -> false in if is_defined w then variables := w :: !variables in (* 1. Warn about OCAMLFIND variables if it is installed *) let ocamlfind_vars = [ "OCAMLFIND_DESTDIR"; "OCAMLFIND_CONF"; "OCAMLFIND_METADIR"; "OCAMLFIND_COMMANDS"; "OCAMLFIND_LDCONF"; ] in if OpamPackage.Set.exists ( fun nv -> OpamPackage.Name.to_string (OpamPackage.name nv) = "ocamlfind" ) t.installed then List.iter warn ocamlfind_vars; (* 2. Warn about variables possibly set by other compilers *) let new_variables comp = let comp_f = OpamPath.compiler_comp t.root comp in let env = OpamFile.Comp.env (OpamFile.Comp.safe_read comp_f) in new_variables env in let vars = ref OpamMisc.StringSet.empty in OpamSwitch.Map.iter (fun _ comp -> vars := OpamMisc.StringSet.union !vars (new_variables comp) ) t.aliases; vars := OpamMisc.StringSet.diff !vars (new_variables t.compiler); OpamMisc.StringSet.iter warn !vars; if !variables <> [] then ( OpamGlobals.msg "The following variables are set in your environment, \ you should better unset it if you want OPAM to work \ correctly.\n"; List.iter (OpamGlobals.msg " - %s\n") !variables; if not (OpamState.confirm "Do you want to continue ?") then OpamGlobals.exit 1; ); variable_warnings := true; ) (* Is a recovery possible ? *) let can_try_to_recover_from_error l = List.exists (function (n,_) -> match n with | To_change(Some _,_) -> true | To_recompile _ | To_change _ | To_delete _ -> false ) l (* Try to recover from errors by installing either the old packages or by reinstalling the current ones. This can also fail but if it succeeds OPAM should remains in a consistent state. *) let recover_from_error = function | To_delete _ -> () | To_recompile nv | To_change (Some nv, _) | To_change (None, nv) -> let t = OpamState.load_state "recover-from-error" in try OpamAction.build_and_install_package t ~metadata:true nv with _ -> () (* Transient state (not flushed to disk) *) type state = { mutable s_installed : package_set; mutable s_installed_roots: package_set; mutable s_reinstall : package_set; } let output_json_solution solution = let to_remove = List.map OpamPackage.to_json solution.PackageActionGraph.to_remove in let to_proceed = ref [] in PackageActionGraph.Topological.iter (function | To_change(o,p) -> let json = match o with | None -> `O ["install", OpamPackage.to_json p] | Some o -> if OpamPackage.Version.compare (OpamPackage.version o) (OpamPackage.version p) < 0 then `O ["upgrade", `A [OpamPackage.to_json o; OpamPackage.to_json p]] else `O ["downgrade", `A [OpamPackage.to_json o; OpamPackage.to_json p]] in to_proceed := json :: !to_proceed | To_recompile p -> let json = `O ["recompile", OpamPackage.to_json p] in to_proceed := json :: !to_proceed | To_delete _ -> () ) solution.PackageActionGraph.to_process; let json = `O [ "to-remove" , `A to_remove; "to-proceed", `A (List.rev !to_proceed); ] in OpamJson.add json let output_json_actions action_errors = let open OpamParallel in let open OpamProcess in let json_error = function | Process_error r -> `O [ ("process-error", `O [ ("code", `String (string_of_int r.r_code)); ("duration", `Float r.r_duration); ("info", `O (List.map (fun (k,v) -> (k, `String v)) r.r_info)); ("stdout", `A (List.map (fun s -> `String s) r.r_stdout)); ("stderr", `A (List.map (fun s -> `String s) r.r_stderr)); ])] | Internal_error s -> `O [ ("internal-error", `String s) ] | Package_error s -> `O [ ("package-error", `String s) ] in let json_action (a, e) = `O [ ("package", `String (OpamPackage.to_string (action_contents a))); ("error" , json_error e) ] in List.iter (fun a -> let json = json_action a in OpamJson.add json ) action_errors (* Mean function for applying solver solutions. One main process is deleting the packages and updating the global state of OPAM. Children processes are spawned to deal with parallele builds and installations. *) let parallel_apply t action solution = let open PackageActionGraph in let state = { s_installed = t.installed; s_installed_roots = t.installed_roots; s_reinstall = t.reinstall; } in let update_state () = let installed = state.s_installed in let installed_roots = state.s_installed_roots in let reinstall = state.s_reinstall in OpamAction.update_metadata t ~installed ~installed_roots ~reinstall in let root_installs = let names = List.rev_map OpamPackage.name (OpamPackage.Set.elements t.installed_roots) in OpamPackage.Name.Set.of_list names in let root_installs = match action with | Init r | Install r | Import r | Switch r -> OpamPackage.Name.Set.union root_installs r | Upgrade _ | Reinstall -> root_installs | Depends | Remove -> OpamPackage.Name.Set.empty in (* flush the contents of installed and installed.root to disk. This should be called as often as possible to keep the global state of OPAM consistent (as the user is free to kill OPAM at every moment). We are not guaranteed to always be consistent, but we try hard to be.*) let add_to_install nv = state.s_installed <- OpamPackage.Set.add nv state.s_installed; state.s_reinstall <- OpamPackage.Set.remove nv state.s_reinstall; if OpamPackage.Name.Set.mem (OpamPackage.name nv) root_installs then state.s_installed_roots <- OpamPackage.Set.add nv state.s_installed_roots; update_state (); OpamState.install_metadata t nv in let remove_from_install deleted = state.s_installed <- OpamPackage.Set.diff state.s_installed deleted; state.s_installed_roots <- OpamPackage.Set.diff state.s_installed_roots deleted; state.s_reinstall <- OpamPackage.Set.diff state.s_reinstall deleted in (* Installation and recompilation are done by child the processes *) let child n = (* We are guaranteed to load the state when all the dependencies have been correctly updated. Thus [t.installed] should be up-to-date. XXX: do we really need to load the state again here ? *) let t = OpamState.load_state "child" in match n with | To_change (_, nv) | To_recompile nv -> OpamAction.build_and_install_package ~metadata:false t nv | To_delete _ -> assert false in (* Not pre-condition (yet ?) *) let pre _ = () in (* Post-condition on the parent process: we modify of the global OPAM state to keep the list of installed packages up-to-date. *) let post = function | To_delete _ -> assert false | To_recompile nv | To_change (_, nv) -> add_to_install nv in try (* 1/ We remove all installed packages appearing in the solution. *) let deleted = OpamAction.remove_all_packages t ~metadata:true solution in remove_from_install deleted; (* 2/ We install the new packages *) PackageActionGraph.Parallel.iter (OpamState.jobs t) solution.to_process ~pre ~child ~post; if !OpamGlobals.fake then OpamGlobals.msg "Simulation complete.\n"; (* XXX: we might want to output the sucessful actions as well. *) output_json_actions []; OK (PackageActionGraph.fold_vertex (fun a b -> a::b) solution.to_process []) with | PackageActionGraph.Parallel.Cyclic actions -> let packages = List.map (List.map action_contents) actions in let strings = List.map (List.map OpamPackage.to_string) packages in let mk l = Printf.sprintf " - %s" (String.concat ", " l) in OpamGlobals.error "Aborting, as the following packages have a cyclic dependency:\n%s" (String.concat "\n" (List.map mk strings)); Aborted | PackageActionGraph.Parallel.Errors (errors, remaining) -> OpamGlobals.msg "\n"; if remaining <> [] then ( OpamGlobals.error "Due to some errors while processing %s, the following actions will NOT \ proceed:\n%s" (string_of_errors errors) (String.concat "\n" (List.map PackageAction.string_of_action remaining)) ); if can_try_to_recover_from_error errors then ( let pkgs = List.map (fst ++ action_contents ++ OpamPackage.to_string) errors in OpamGlobals.header_msg "%s [%s]" (OpamGlobals.colorise `yellow "ERROR RECOVERY") (String.concat ", " pkgs); List.iter recover_from_error (List.map fst errors); List.iter recover_from_error remaining; ); List.iter display_error errors; output_json_actions errors; let errpkgs = List.map fst errors in let successful = PackageActionGraph.fold_vertex (fun pkg successful -> if not (List.mem pkg errpkgs) && not (List.mem pkg remaining) then pkg::successful else successful) solution.to_process [] in Error (successful, errpkgs, remaining) let simulate_new_state state t = let installed = List.fold_left (fun installed p -> OpamPackage.Set.remove p installed) state.installed t.PackageActionGraph.to_remove in let installed = PackageActionGraph.Topological.fold (fun action installed -> match action with | To_change(_,p) | To_recompile p -> OpamPackage.Set.add p installed | To_delete p -> OpamPackage.Set.remove p installed ) t.PackageActionGraph.to_process installed in { state with installed } (* Apply a solution *) let apply ?(force = false) t action solution = log "apply"; if !OpamGlobals.debug then PackageActionGraph.dump_solution solution; if OpamSolver.solution_is_empty solution then (* The current state satisfies the request contraints *) Nothing_to_do else ( (* Otherwise, compute the actions to perform *) let stats = OpamSolver.stats solution in let show_solution = (!OpamGlobals.external_tags = []) in if show_solution then ( OpamGlobals.msg "The following actions will be %s:\n" (if !OpamGlobals.fake then "simulated" else "performed"); let new_state = simulate_new_state t solution in let messages p = let opam = OpamState.opam new_state p in let messages = OpamFile.OPAM.messages opam in OpamMisc.filter_map (fun (s,f) -> if OpamState.eval_filter new_state OpamVariable.Map.empty f then Some s else None ) messages in let rewrite nv = let name = OpamPackage.name nv in if not (OpamState.is_locally_pinned t name) then nv else OpamPackage.pinned name in OpamSolver.print_solution ~messages ~rewrite solution; OpamGlobals.msg "%s\n" (OpamSolver.string_of_stats stats); output_json_solution solution; ); let continue = if !OpamGlobals.dryrun then ( OpamGlobals.msg "Dry run: exiting now.\n"; false ) else if !OpamGlobals.external_tags <> [] then ( let packages = OpamSolver.new_packages solution in let external_tags = OpamMisc.StringSet.of_list !OpamGlobals.external_tags in let values = OpamPackage.Set.fold (fun nv accu -> let opam = OpamState.opam t nv in match OpamFile.OPAM.depexts opam with | None -> accu | Some alltags -> OpamMisc.StringSetMap.fold (fun tags values accu -> if OpamMisc.StringSet.( (* A \subseteq B <=> (A U B) / B = 0 *) is_empty (diff (union external_tags tags) external_tags) ) then OpamMisc.StringSet.union values accu else accu ) alltags accu ) packages OpamMisc.StringSet.empty in let values = OpamMisc.StringSet.elements values in if values <> [] then OpamGlobals.msg "%s\n" (String.concat " " values); false ) else if force || !OpamGlobals.fake || !OpamGlobals.yes || sum stats <= 1 then true else OpamState.confirm "Do you want to continue ?" in if continue then ( print_variable_warnings t; parallel_apply t action solution ) else Aborted ) let resolve ?(verbose=true) t action request = OpamSolver.resolve ~verbose (OpamState.universe t action) request let resolve_and_apply ?(force=false) t action request = match resolve t action request with | Conflicts cs -> log "conflict!"; OpamGlobals.msg "%s\n" (cs ()); No_solution | Success solution -> apply ~force t action solution opam-1.1.1/src/debug.ocp0000644000175000017500000000004012272210733013263 0ustar i33173i33173comp += [ "-g"] link += [ "-g"] opam-1.1.1/m4/0000755000175000017500000000000012272210733011231 5ustar i33173i33173opam-1.1.1/m4/ax_compare_version.m40000644000175000017500000001465212272210733015366 0ustar i33173i33173# =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_compare_version.html # =========================================================================== # # SYNOPSIS # # AX_COMPARE_VERSION(VERSION_A, OP, VERSION_B, [ACTION-IF-TRUE], [ACTION-IF-FALSE]) # # DESCRIPTION # # This macro compares two version strings. Due to the various number of # minor-version numbers that can exist, and the fact that string # comparisons are not compatible with numeric comparisons, this is not # necessarily trivial to do in a autoconf script. This macro makes doing # these comparisons easy. # # The six basic comparisons are available, as well as checking equality # limited to a certain number of minor-version levels. # # The operator OP determines what type of comparison to do, and can be one # of: # # eq - equal (test A == B) # ne - not equal (test A != B) # le - less than or equal (test A <= B) # ge - greater than or equal (test A >= B) # lt - less than (test A < B) # gt - greater than (test A > B) # # Additionally, the eq and ne operator can have a number after it to limit # the test to that number of minor versions. # # eq0 - equal up to the length of the shorter version # ne0 - not equal up to the length of the shorter version # eqN - equal up to N sub-version levels # neN - not equal up to N sub-version levels # # When the condition is true, shell commands ACTION-IF-TRUE are run, # otherwise shell commands ACTION-IF-FALSE are run. The environment # variable 'ax_compare_version' is always set to either 'true' or 'false' # as well. # # Examples: # # AX_COMPARE_VERSION([3.15.7],[lt],[3.15.8]) # AX_COMPARE_VERSION([3.15],[lt],[3.15.8]) # # would both be true. # # AX_COMPARE_VERSION([3.15.7],[eq],[3.15.8]) # AX_COMPARE_VERSION([3.15],[gt],[3.15.8]) # # would both be false. # # AX_COMPARE_VERSION([3.15.7],[eq2],[3.15.8]) # # would be true because it is only comparing two minor versions. # # AX_COMPARE_VERSION([3.15.7],[eq0],[3.15]) # # would be true because it is only comparing the lesser number of minor # versions of the two values. # # Note: The characters that separate the version numbers do not matter. An # empty string is the same as version 0. OP is evaluated by autoconf, not # configure, so must be a string, not a variable. # # The author would like to acknowledge Guido Draheim whose advice about # the m4_case and m4_ifvaln functions make this macro only include the # portions necessary to perform the specific comparison specified by the # OP argument in the final configure script. # # LICENSE # # Copyright (c) 2008 Tim Toolan # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. #serial 11 dnl ######################################################################### AC_DEFUN([AX_COMPARE_VERSION], [ AC_REQUIRE([AC_PROG_AWK]) # Used to indicate true or false condition ax_compare_version=false # Convert the two version strings to be compared into a format that # allows a simple string comparison. The end result is that a version # string of the form 1.12.5-r617 will be converted to the form # 0001001200050617. In other words, each number is zero padded to four # digits, and non digits are removed. AS_VAR_PUSHDEF([A],[ax_compare_version_A]) A=`echo "$1" | sed -e 's/\([[0-9]]*\)/Z\1Z/g' \ -e 's/Z\([[0-9]]\)Z/Z0\1Z/g' \ -e 's/Z\([[0-9]][[0-9]]\)Z/Z0\1Z/g' \ -e 's/Z\([[0-9]][[0-9]][[0-9]]\)Z/Z0\1Z/g' \ -e 's/[[^0-9]]//g'` AS_VAR_PUSHDEF([B],[ax_compare_version_B]) B=`echo "$3" | sed -e 's/\([[0-9]]*\)/Z\1Z/g' \ -e 's/Z\([[0-9]]\)Z/Z0\1Z/g' \ -e 's/Z\([[0-9]][[0-9]]\)Z/Z0\1Z/g' \ -e 's/Z\([[0-9]][[0-9]][[0-9]]\)Z/Z0\1Z/g' \ -e 's/[[^0-9]]//g'` dnl # In the case of le, ge, lt, and gt, the strings are sorted as necessary dnl # then the first line is used to determine if the condition is true. dnl # The sed right after the echo is to remove any indented white space. m4_case(m4_tolower($2), [lt],[ ax_compare_version=`echo "x$A x$B" | sed 's/^ *//' | sort -r | sed "s/x${A}/false/;s/x${B}/true/;1q"` ], [gt],[ ax_compare_version=`echo "x$A x$B" | sed 's/^ *//' | sort | sed "s/x${A}/false/;s/x${B}/true/;1q"` ], [le],[ ax_compare_version=`echo "x$A x$B" | sed 's/^ *//' | sort | sed "s/x${A}/true/;s/x${B}/false/;1q"` ], [ge],[ ax_compare_version=`echo "x$A x$B" | sed 's/^ *//' | sort -r | sed "s/x${A}/true/;s/x${B}/false/;1q"` ],[ dnl Split the operator from the subversion count if present. m4_bmatch(m4_substr($2,2), [0],[ # A count of zero means use the length of the shorter version. # Determine the number of characters in A and B. ax_compare_version_len_A=`echo "$A" | $AWK '{print(length)}'` ax_compare_version_len_B=`echo "$B" | $AWK '{print(length)}'` # Set A to no more than B's length and B to no more than A's length. A=`echo "$A" | sed "s/\(.\{$ax_compare_version_len_B\}\).*/\1/"` B=`echo "$B" | sed "s/\(.\{$ax_compare_version_len_A\}\).*/\1/"` ], [[0-9]+],[ # A count greater than zero means use only that many subversions A=`echo "$A" | sed "s/\(\([[0-9]]\{4\}\)\{m4_substr($2,2)\}\).*/\1/"` B=`echo "$B" | sed "s/\(\([[0-9]]\{4\}\)\{m4_substr($2,2)\}\).*/\1/"` ], [.+],[ AC_WARNING( [illegal OP numeric parameter: $2]) ],[]) # Pad zeros at end of numbers to make same length. ax_compare_version_tmp_A="$A`echo $B | sed 's/./0/g'`" B="$B`echo $A | sed 's/./0/g'`" A="$ax_compare_version_tmp_A" # Check for equality or inequality as necessary. m4_case(m4_tolower(m4_substr($2,0,2)), [eq],[ test "x$A" = "x$B" && ax_compare_version=true ], [ne],[ test "x$A" != "x$B" && ax_compare_version=true ],[ AC_WARNING([illegal OP parameter: $2]) ]) ]) AS_VAR_POPDEF([A])dnl AS_VAR_POPDEF([B])dnl dnl # Execute ACTION-IF-TRUE / ACTION-IF-FALSE. if test "$ax_compare_version" = "true" ; then m4_ifvaln([$4],[$4],[:])dnl m4_ifvaln([$5],[else $5])dnl fi ]) dnl AX_COMPARE_VERSION opam-1.1.1/m4/ocaml.m40000644000175000017500000001352512272210733012574 0ustar i33173i33173dnl autoconf macros for OCaml dnl dnl Copyright © 2009 Richard W.M. Jones dnl Copyright © 2009 Stefano Zacchiroli dnl Copyright © 2000-2005 Olivier Andrieu dnl Copyright © 2000-2005 Jean-Christophe Filliâtre dnl Copyright © 2000-2005 Georges Mariano dnl dnl For documentation, please read the ocaml.m4 man page. AC_DEFUN([AC_PROG_OCAML], [dnl # checking for ocamlc AC_CHECK_TOOL([OCAMLC],[ocamlc],[no]) if test "$OCAMLC" != "no"; then OCAMLVERSION=`$OCAMLC -v | sed -n -e 's|.*version* *\(.*\)$|\1|p'` AC_MSG_RESULT([OCaml version is $OCAMLVERSION]) # If OCAMLLIB is set, use it if test "$OCAMLLIB" = ""; then OCAMLLIB=`$OCAMLC -where 2>/dev/null || $OCAMLC -v|tail -1|cut -d ' ' -f 4` else AC_MSG_RESULT([OCAMLLIB previously set; preserving it.]) fi AC_MSG_RESULT([OCaml library path is $OCAMLLIB]) AC_SUBST([OCAMLVERSION]) AC_SUBST([OCAMLLIB]) # checking for ocamlopt AC_CHECK_TOOL([OCAMLOPT],[ocamlopt],[no]) OCAMLBEST=byte if test "$OCAMLOPT" = "no"; then AC_MSG_WARN([Cannot find ocamlopt; bytecode compilation only.]) else TMPVERSION=`$OCAMLOPT -v | sed -n -e 's|.*version* *\(.*\)$|\1|p' ` if test "$TMPVERSION" != "$OCAMLVERSION" ; then AC_MSG_RESULT([versions differs from ocamlc $TMPVERSION != $OCAMLVERSION; ocamlopt discarded.]) OCAMLOPT=no else OCAMLBEST=opt fi fi AC_SUBST([OCAMLBEST]) # checking for ocamlc.opt AC_CHECK_TOOL([OCAMLCDOTOPT],[ocamlc.opt],[no]) if test "$OCAMLCDOTOPT" != "no"; then TMPVERSION=`$OCAMLCDOTOPT -v | sed -n -e 's|.*version* *\(.*\)$|\1|p' ` if test "$TMPVERSION" != "$OCAMLVERSION" ; then AC_MSG_RESULT([versions differs from ocamlc $TMPVERSION != $OCAMLVERSION; ocamlc.opt discarded.]) else OCAMLC=$OCAMLCDOTOPT fi fi # checking for ocamlopt.opt if test "$OCAMLOPT" != "no" ; then AC_CHECK_TOOL([OCAMLOPTDOTOPT],[ocamlopt.opt],[no]) if test "$OCAMLOPTDOTOPT" != "no"; then TMPVERSION=`$OCAMLOPTDOTOPT -v | sed -n -e 's|.*version* *\(.*\)$|\1|p' ` if test "$TMPVERSION" != "$OCAMLVERSION" ; then AC_MSG_RESULT([versions differs from ocamlc $TMPVERSION != $OCAMLVERSION; ocamlopt.opt discarded.]) else OCAMLOPT=$OCAMLOPTDOTOPT fi fi fi AC_SUBST([OCAMLOPT]) fi AC_SUBST([OCAMLC]) # checking for ocaml toplevel AC_CHECK_TOOL([OCAML],[ocaml],[no]) # checking for ocamldep AC_CHECK_TOOL([OCAMLDEP],[ocamldep],[no]) # checking for ocamlmktop AC_CHECK_TOOL([OCAMLMKTOP],[ocamlmktop],[no]) # checking for ocamlmklib AC_CHECK_TOOL([OCAMLMKLIB],[ocamlmklib],[no]) # checking for ocamldoc AC_CHECK_TOOL([OCAMLDOC],[ocamldoc],[no]) # checking for ocamlbuild AC_CHECK_TOOL([OCAMLBUILD],[ocamlbuild],[no]) ]) AC_DEFUN([AC_PROG_OCAMLLEX], [dnl # checking for ocamllex AC_CHECK_TOOL([OCAMLLEX],[ocamllex],[no]) if test "$OCAMLLEX" != "no"; then AC_CHECK_TOOL([OCAMLLEXDOTOPT],[ocamllex.opt],[no]) if test "$OCAMLLEXDOTOPT" != "no"; then OCAMLLEX=$OCAMLLEXDOTOPT fi fi AC_SUBST([OCAMLLEX]) ]) AC_DEFUN([AC_PROG_OCAMLYACC], [dnl AC_CHECK_TOOL([OCAMLYACC],[ocamlyacc],[no]) AC_SUBST([OCAMLYACC]) ]) AC_DEFUN([AC_PROG_CAMLP4], [dnl AC_REQUIRE([AC_PROG_OCAML])dnl # checking for camlp4 AC_CHECK_TOOL([CAMLP4],[camlp4],[no]) if test "$CAMLP4" != "no"; then TMPVERSION=`$CAMLP4 -v 2>&1| sed -n -e 's|.*version *\(.*\)$|\1|p'` if test "$TMPVERSION" != "$OCAMLVERSION" ; then AC_MSG_RESULT([versions differs from ocamlc $TMPVERSION != $OCAMLVERSION.]) CAMLP4=no fi fi AC_SUBST([CAMLP4]) # checking for companion tools AC_CHECK_TOOL([CAMLP4O],[camlp4o],[no]) AC_CHECK_TOOL([CAMLP4OF],[camlp4of],[no]) AC_CHECK_TOOL([CAMLP4OOF],[camlp4oof],[no]) AC_CHECK_TOOL([CAMLP4ORF],[camlp4orf],[no]) AC_CHECK_TOOL([CAMLP4PROF],[camlp4prof],[no]) AC_CHECK_TOOL([CAMLP4R],[camlp4r],[no]) AC_CHECK_TOOL([CAMLP4RF],[camlp4rf],[no]) AC_SUBST([CAMLP4O]) AC_SUBST([CAMLP4OF]) AC_SUBST([CAMLP4OOF]) AC_SUBST([CAMLP4ORF]) AC_SUBST([CAMLP4PROF]) AC_SUBST([CAMLP4R]) AC_SUBST([CAMLP4RF]) ]) AC_DEFUN([AC_PROG_FINDLIB], [dnl AC_REQUIRE([AC_PROG_OCAML])dnl # checking for ocamlfind AC_CHECK_TOOL([OCAMLFIND],[ocamlfind],[no]) AC_SUBST([OCAMLFIND]) ]) dnl Thanks to Jim Meyering for working this next bit out for us. dnl XXX We should define AS_TR_SH if it's not defined already dnl (eg. for old autoconf). AC_DEFUN([AC_CHECK_OCAML_PKG], [dnl AC_REQUIRE([AC_PROG_FINDLIB])dnl AC_MSG_CHECKING([for OCaml findlib package $1]) unset found unset pkg found=no for pkg in $1 $2 ; do if $OCAMLFIND query $pkg >/dev/null 2>/dev/null; then AC_MSG_RESULT([found]) AS_TR_SH([OCAML_PKG_$1])=$pkg found=yes break fi done if test "$found" = "no" ; then AC_MSG_RESULT([not found]) AS_TR_SH([OCAML_PKG_$1])=no fi AC_SUBST(AS_TR_SH([OCAML_PKG_$1])) ]) AC_DEFUN([AC_CHECK_OCAML_MODULE], [dnl AC_MSG_CHECKING([for OCaml module $2]) cat > conftest.ml <&5 2>&5 ; then found=yes break fi done if test "$found" ; then AC_MSG_RESULT([$$1]) else AC_MSG_RESULT([not found]) $1=no fi AC_SUBST([$1]) ]) dnl XXX Cross-compiling AC_DEFUN([AC_CHECK_OCAML_WORD_SIZE], [dnl AC_REQUIRE([AC_PROG_OCAML])dnl AC_MSG_CHECKING([for OCaml compiler word size]) cat > conftest.ml < conftest.ml < Anil Madhavapeddy Fabrice Le Fessant Frederic Tuong Louis Gesbert Guillem Rieu Vincent Bernardoff opam-1.1.1/jenkins/0000755000175000017500000000000012272210733012352 5ustar i33173i33173opam-1.1.1/jenkins/10-opam-prepare.sh0000755000175000017500000000370712272210733015526 0ustar i33173i33173#!/bin/sh BASE="ocaml ocaml-compiler-libs" add () { BASE="${BASE} $1"; } # riakc add protobuf-compiler # frei0r add frei0r-plugins-dev # voaacenc add camlidl # svm add libsvm-dev # buddy add libbdd-dev # libvirt add libvirt-dev # ffmpeg add libswscale-dev # dssi add dssi-dev # spf add libspf2-dev # oqamldebug add libqt4-dev # milter add libmilter-dev # lzo add liblzo2-dev # magic add libmagic-dev # mpi add mpi-default-dev # snappy add libsnappy-dev # alt-ergo add autoconf # yajl add cmake # cairo add libcairo2-dev # lapack add libatlas-dev add liblapack-dev # ocaml-sdl add libsdl-dev # dbm add libgdbm-dev # ocamlfuse add libfuse-dev # ffmpeg add libavutil-dev # ladspa add ladspa-sdk # gstreamer add libgstreamer0.10-dev # opus add libavutil-dev # frei0r add frei0r-plugins-dev # liquidsoap add libao-dev add portaudio19-dev add libsamplerate-dev add libgstreamer0.10-dev add libgstreamer-plugins-base0.10-dev add libgstreamer0.10-dev add libgstreamer-plugins-base0.10-dev add libgstreamer1.0-dev add libmp3lame-dev add libogg-dev add libvorbis-dev add libspeex-dev add libtheora-dev add libschroedinger-dev add libvo-aacenc-dev add libfaad-dev add libflac-dev add libsoundtouch-dev add libgavl-dev add liblo-dev # lablgtk2 add libgtk2.0-dev add libgtksourceview2.0-dev add libglade2-dev add libgnomecanvas2-dev # oqamldebug add qt4-qmake # lwt-zmq add libzmq-dev # postgresql-ocaml add libpq-dev # camlbz2 add libbz2-dev # imagemagick add libgraphicsmagick1-dev add libmagickcore-dev # sqlite3 add libsqlite3-dev # ocaml-glpk add libglpk-dev # lablgl add mesa-common-dev add libglu1-mesa-dev add freeglut3-dev # ocamlgsl add gawk # mlgmp add libmpfr-dev # ocaml-lua add liblua5.1-0-dev # ocurl add libcurl4-gnutls-dev # gpr add libgsl0-dev # planets add tcl8.5-dev tk8.5-dev # ocaml-mysql add libmysqlclient-dev # odepack # lbfgs add gfortran # fftw-ocaml add libfftw3-dev # ocaml-taglib add libtag1-dev # ocaml-mad add libmad0-dev sudo apt-get -y install ${BASE} opam-1.1.1/jenkins/31-opam-mirage-packages.sh0000755000175000017500000000065312272210733017110 0ustar i33173i33173#!/bin/sh -ex PREFIX=$1 OPAM=$HOME/opam-bin/$PREFIX/bin/opam ROOT=`echo /x/${JOB_NAME} | sed -e "s,=,_,g" -e "s/,/-/g"` rm -rf ${ROOT} export OPAMROOT=$ROOT export OPAMYES=1 export OPAMVERBOSE=1 $OPAM init . $OPAM remote add dev git://github.com/mirage/opam-repo-dev if [ "${compiler}" != "system" ]; then $OPAM switch ${compiler} fi if [ "${packages}" = "all" ]; then packages=`$OPAM list -s` fi $OPAM install ${packages} opam-1.1.1/jenkins/30-opam-packages.sh0000755000175000017500000000065412272210733015646 0ustar i33173i33173#!/bin/sh -ex PREFIX=$1 OPAM=$HOME/opam-bin/$PREFIX/bin/opam ROOT=`echo /x/${JOB_NAME} | sed -e "s,=,_,g" -e "s/,/-/g"` rm -rf ${ROOT} case "${compiler}" in system4) export PATH=/x/ocaml-4.00.1/bin:$PATH ;; esac export OPAMROOT=$ROOT export OPAMYES=1 export OPAMVERBOSE=1 $OPAM init $2 $OPAM config list case "${compiler}" in system) ;; system4) ;; *) $OPAM switch ${compiler} ;; esac $OPAM install ${packages} opam-1.1.1/jenkins/20-opam-init.sh0000755000175000017500000000030712272210733015025 0ustar i33173i33173#!/bin/sh -ex PREFIX=$1 if [ "$PREFIX" = "" ]; then echo Need prefix as first arg; exit 1; fi cd src_ext make distclean cd .. ./configure --prefix=$HOME/opam-bin/$PREFIX make make install make tests opam-1.1.1/jenkins/10-opam-source-install.sh0000755000175000017500000000064212272210733017027 0ustar i33173i33173#!/bin/sh -ex rm -f nlopt-2.3.tar.gz curl -OL http://ab-initio.mit.edu/nlopt/nlopt-2.3.tar.gz tar -zxvf nlopt-2.3.tar.gz cd nlopt-2.3 env CFLAGS="-fPIC" ./configure && make sudo make install cd .. rm -rf nlopt-2.3 rm -f libsrs2-1.0.18.tar.gz curl -OL http://www.libsrs2.org/srs/libsrs2-1.0.18.tar.gz tar -zxvf libsrs2-1.0.18.tar.gz cd libsrs2-1.0.18 ./configure && make sudo make install cd .. rm -rf libsrs2-1.0.18 opam-1.1.1/jenkins/11-ocaml-install.sh0000755000175000017500000000040612272210733015667 0ustar i33173i33173#!/bin/sh -ex if [ ! -e ocaml-4.00.1.tar.bz2 ]; then wget http://caml.inria.fr/pub/distrib/ocaml-4.00/ocaml-4.00.1.tar.bz2 fi rm -rf ocaml-4.00.1 tar -jxvf ocaml-4.00.1.tar.bz2 cd ocaml-4.00.1 ./configure -prefix /x/ocaml-4.00.1 make world world.opt install opam-1.1.1/CHANGES0000644000175000017500000003444612272210733011717 0ustar i33173i331731.1.1 * Fix `opam-admin make -r` (#990) * Explicitly prettyprint list of lists, to fix `opam-admin depexts` (#997) * Tell the user which fields is invalid in a configuration file (#1016) * Add `OpamSolver.empty_universe` for flexible universe instantiation (#1033) * Add `OpamFormula.eval_relop` and `OpamFormula.check_relop` (#1042) * Change `OpamCompiler.compare` to match `Pervasives.compare` (#1042) * Add `OpamCompiler.eval_relop` (#1042) * Add `OpamPackage.Name.compare` (#1046) * Add types `version_constraint` and `version_formula` to `OpamFormula` (#1046) * Clearer command aliases. Made `info` an alias for `show` and added the alias `uninstall` (#944) * Fixed `opam init --root=` (#1047) * Display OS constraints in `opam info` (#1052) * Add a new 'opam-installer' script to make `.install` files usable outside of opam (#1026) * Add a `--resolve` option to `opam-admin make` that builds just the archives you need for a specific installation (#1031) * Fixed handling of spaces in filenames in internal files (#1014) * Replace calls to `which` by a more portable call (#1061) * Fixed generation of the init scripts in some cases (#1011) * Better reports on package patch errors (#987, #988) * More accurate warnings for unknown package dependencies (#1079) * Added `opam config report` to help with bug reports (#1034) * Do not reinstall dev packages with `opam upgrade ` (#1001) * Be more careful with `opam init` to a non-empty root directory (#974) * Cleanup build-dir after successful compiler installation to save on space (#1006) * Improved OSX compatibility in the external solver tools (#1074) * Fixed messages printed on update that were plain wrong (#1030) * Improved detection of meaningful changes from upstream packages to trigger recompilation 1.1.0 [Oct 2013] * Fix update of dev packages (#962) * Add support for zip source archives (#958) * Add `OPAMCURL` environment variable to control invocation of curl (#960) * Ensure repository redirects only happen for http remotes (#955) * Turn malformed package files into warnings instead of hard errors (#957) * Improve robustness of pinned package update (#949) * Finish conversion of default repository to (#948) * Fix regression in handling archives with no extension (treat them as tar again) (#972) * Fixed stale archives causing packages to be marked as NEW when they weren't (#945) 1.1.0RC1 [Oct 2013] * Add `make cold` target to build OPAM without a system OCaml installed (#910) * More informative error messages from `curl` (#905) * Document use of `OPAMCOLOR` for optional ANSI coloring * Add `opam-admin depexts` utility to rewrite OPAM files with external dependencies * Added `repo` files for repository meta-information * Added support for repo redirections * Added scripts for automated testing in Travis * Fixed bug in opam-admin that could keep not up-to-date archives * Added an `opam-admin depexts` script to ease handling of external dependencies * Added the `--deps-only` option to `opam install` * Fixed upgrade with corner-cases of orphan packages * Added a `note` display form * Better handling of external solver failures, and added a `--no-aspcud` option * Fixed unpinning of some installed packages * Fixed upgrade of metadata from 1.0 when there are orphan custom compilers 1.1.0-beta [Sept 2013] * Automatic backup before any operation which might alter the list of installed packages * Support for arbitrary sub-directories for metadata repositories * Lots of colors * New option `opam update -u` equivalent to `opam update && opam upgrade --yes` * New `opam-admin` tool, bundling the features of `opam-mk-repo` and `opam-repo-check` + new 'opam-admin stats' tool * New `available`: field in opam files, superseding `ocaml-version` and `os` fields * Package names specified on the command-line are now understood case-insensitively (#705) * Fixed parsing of malformed opam files (#696) * Fixed recompilation of a package when uninstalling its optional dependencies (#692) * Added conditional post-messages support, to help users when a package fails to install for a known reason (#662) * Rewrite the code which updates pin et dev packages to be quicker and more reliable * Add {opam,url,desc,files/} overlay for all packages * `opam config env` now detects the current shell and outputs a sensible default if no override is provided. * Improve `opam pin` stability and start display information about dev revisions * Add a new `man` field in `.install` files * Support hierarchical installation in `.install` files * Add a new `stublibs` field in `.install` files * OPAM works even when the current directory has been deleted * speed-up invocation of `opam config var VARIABLE` when variable is simple (eg. `prefix`, `lib`, ...) * `opam list` now display only the installed packages. Use `opam list -a` to get the previous behavior. * Inverse the depext tag selection (useful for `ocamlot`) * Add a `--sexp` option to `opam config env` to load the configuration under emacs * Purge `~/.opam/log` on each invocation of OPAM * System compiler with versions such as `version+patches` are now handled as if this was simply `version` * New `OpamVCS` functor to generate OPAM backends * More efficient `opam update` * Switch license to LGPL with linking exception * `opam search` now also searches through the tags * minor API chanages for `API.list` and `API.SWITCH.list` * Improve the syntax of filters * Add a `messages` field * Add a `--jobs` command line option and add `%{jobs}%` to be used in OPAM files * Various improvments in the solver heuristics * By default, turn-on checking of certificates for downloaded dependency archives: use `./configure --disable-certificate-check` to go back to the previous behavior * Check the md5sum of downloaded archives when compiling OPAM * Improved `opam info` command (more information, non-zero error code when no patterns match) * Display OS and OPAM version on internal errors to ease error reporting * Fix `opam reinstall` when reinstalling a package wich is a dependency of installed packages (regression introduced in 0.9.5) * Export and read `OPAMSWITCH` to be able to call OPAM in different switches * `opam-client` can now be used in a toplevel * `-n` now means `--no-setup` and not `--no-checksums` anymore * Fix support for FreeBSD * Fix installation of local compilers with local paths endings with `.../ocaml/` * Fix the contents of `~/.opam/opam-init/variable.sh` after a switch 1.0.0 [Mar 2013] * Improve the lexer performance (thx to @oandrieu) * Fix various typos (thx to @chaudhuri) * Fix build issue (thx to @avsm) 0.9.6 [Mar 2013] * Fix installation of pinned packages on BSD (thx to @smondet) * Fix configuration for zsh users (thx to @AltGr) * Fix loading of `~/.profile` when using dash (eg. in Debian/Ubuntu) * Fix installation of packages with symbolic links (regression introduced in 0.9.5) 0.9.5 [Mar 2013] * If necessary, apply patches and substitute files before removing a package * Fix `opam remove --keep-build-dir` keeps the folder if a source archive is extracted * Add build and install rules using ocamlbuild to help distro packagers * Support arbitrary level of nested subdirectories in packages repositories * Add `opam config exec "CMD ARG1 ... ARGn" --switch=SWITCH` to execute a command in a subshell * Improve the behaviour of `opam update` wrt. pinned packages * Change the default external solver criteria (only useful if you have aspcud installed on your machine) * Add support for global and user configuration for OPAM (`opam config setup`) * Stop yelling when OPAM is not up-to-date * Update or generate `~/.ocamlinit` when running `opam init` * Fix tests on *BSD (thx Arnaud Degroote) * Fix compilation for the source archive 0.9.4 [Feb 2013] * Disable auto-removal of unused dependencies. This can now be enabled on-demand using `-a` * Fix compilation and basic usage on Cygwin * Fix BSD support (use `type` instead of `which` to detect existing commands) * Add a way to tag external dependencies in OPAM files * Better error messages when trying to upgrade pinned packages * Display `depends` and `depopts` fields in `opam info` * `opam info pkg.version` shows the metadata for this given package version * Add missing `doc` fields in `.install` files * `opam list` now only shows installable packages 0.9.3 [Feb 2013] * Add system compiler constraints in OPAM files * Better error messages in case of conflicts * Cleaner API to install/uninstall packages * On upgrade, OPAM now perform all the remove action first * Use a cache for main storing OPAM metadata: this greatly speed-up OPAM invocations * after an upgrade, propose to reinstall a pinned package only if there were some changes * improvements to the solver heuristics * better error messages on cyclic dependencies 0.9.2 [Jan 2013] * Install all the API files * Fix `opam repo remove repo-name` * speed-up `opam config env` * support for `opam-foo` scripts (which can be called using `opam foo`) * 'opam update pinned-package' works * Fix 'opam-mk-repo -a' * Fix 'opam-mk-repo -i' * clean-up pinned cache dir when a pinned package fails to install 0.9.1 [Jan 2013] * Use ocaml-re 1.2.0 0.9.0 [Jan 2013] * add a new `--fake` option to simulate build and installation of packages. Use this option this care, it can easily corrupt the state of OPAM. * Better messages in case of error * OPAM proposes better solutions to the user * support for installed roots and auto-clean of unused packages * rename `--cores` to `--jobs` * better error messages for wrong argument of 'opam init' * show the root causes of actions done by OPAM * opam import and export now uses -f to specify the filename, and uses stdin and stdout if no filename is specified * Fix environment initialisation for some corner-cases * Add a way to specify how to run tests and build documentation for the packages * Display homepage, authors, doc link, license with 'opam info' * Improve `opam remove` efficiency when using `ocamlfind` command(s) only * Git pinning now works with commits/tags/branches * `opam init` works without preinstalled compiler * Support for DARCS backends * Each global command-line flag `xxx` as can be set using the `OPAMxxx` environment variable instead * Better display of compiler switch (+ read compiler descriptions) * Clearer error message when trying to pin a non-existing package * Fix issue with pinning to version number * Add a `shared` location to be used in OPAM files * Improve (but break) the command-line interface by using cmdliner 0.8.2 [Dec 2012] * Fix an issue with `opam reinstall` where packages were reinstalled in reverse order 0.8.1 [Nov 2012] * Simplify string substitution in OPAM files * Recompile the installed packages when the system compiler is upgraded * Fix various regressions in pinned and dev packages introduced in 0.8.0 0.8.0 [Nov 2012] * Improvements in the solver interface and API * The solver now use an external SAT-solver (aspcud) if found in the path * More expressive constraints in optional dependencies * Clean-up the build directory when build succeeds 0.7.7 [Oct 2012] * Add an `--alias` global command-line argument to overwrite the default alias value * Allow more concurrency between no conflicting opam commands * Upgrade to the latest version of DOSE and CUDF (solver libraries) * Add repository priorities * Create the default directories (`bin/`, `lib/` ...) when installing a new compiler 0.7.6 [Oct 2012] * major internal API refactoring * repositories are now versionned, and we try to auto-update when possible * more expressive compiler constraints in opam files 0.7.5 [Oct 2012] * dependencies can now be expressed by any formula (instead of just CNF) * It's easier to compose the value of environment variable (ie. to write `%{lwt+ssl:enable}%`) * Fix regression on init for rsync repositories 0.7.4 [Oct 2012] * improve `opam pin`: the code is more robust and it is now possible to pin a package to a git repository * add support for patches per package * add `opam switch -import file` and `opam switch -export file` 0.7.3 [Sep 2012] * Better user-message when no solution is found * Improve the minimality of installed packages 0.7.2 [Sep 2012] * Fix regression in init introcuced in 0.7.0 * Fix regression in update introduced in 0.7.0 0.7.1 [Sep 2012] * Remove forgotten debug statement 0.7.0 [Sep 2012] * report upgrade statistic on update * do no ask y/n when installing compiler's base packages * improve opam-mk-repo * fix `opam search` to be caseless * ability to filter some commands (depending on some predicates) in opam file * improvments when packages disapear upstream * check for ocaml 3.12.1 on configure * tell the user to unset some potentially dangerous variables when running opam * fix few git backend issues 0.6.0 [Sep 2012] * semantics changes in `opam switch` * solver improvements in case of install and remove * better error reporting * fix caching of package archives * fix `~/.opam/repo/index` priorities 0.5.0 [Sep 2012] * add opam search * add opam reinstall * ability to upgrade only a subset of packages * lot of bug fixes in the rsync and curl backend * better `--help` messages * better information displayed to the user 0.4.0 [Aug 2012] * better layout of repository files * (partial) possibility to specify archive checksums * if the archive is not on ocamlpro.com, download it upstream * suffix +opam to the versions of archives available on ocamlpro.com * prompt the user to evaluate `opam config -env` more often * changes in meta-data aren't picked up by the CURL backen * more modulare repository system: the 'kind' of repository is no more linked to the kind of package archives 0.3.2 [Aug 2012] * fix regression for `opam switch` introduced in 0.3 * fix deletion of optional dependencies * support for pinned packages * fix compilation for ocaml 4.00 * fix compilation for *BSD 0.3.1 [Jul 2012] * fix regression for `opam install` introduced in 0.3 0.3.0 [Jul 2012] * improve parallel compilation of packages * better recovery on compilation/installation errors * first draft of version pinnig * fix`'opam config -env` for old shells * install the latest version of packages when possible * more robust `opam update` (ie. old files are gc-ed) * add a (more or less) generic way to install and use topfind 0.2.0 [Jul 2012] * more robust switch command * more robust parallel build (not yet activated by default) * support for compiler-constraints in packages * new solver heuristics * improved performance on init with the rsync backend 0.1.0 [Jun 2012] * Initial version opam-1.1.1/.travis.yml0000644000175000017500000000030412272210733013017 0ustar i33173i33173language: c script: bash -ex .travis-ci.sh env: - OCAML_VERSION=4.01.0 OPAM_TEST=1 - OCAML_VERSION=4.01.0 OPAM_TEST=0 - OCAML_VERSION=4.00.1 OPAM_TEST=0 - OCAML_VERSION=3.12.1 OPAM_TEST=0 opam-1.1.1/depends.ocp.in0000644000175000017500000000201712272210733013443 0ustar i33173i33173begin library "re" dirname = "%{lib}%/re" generated = true end begin library "re_perl" dirname = "%{lib}%/re" generated = true requires = [ "re" ] end begin library "re_glob" dirname = "%{lib}%/re" generated = true requires = [ "re" ] end begin library "re_pcre" dirname = "%{lib}%/re" generated = true requires = [ "re_perl" ] end begin library "re_emacs" dirname = "%{lib}%/re" generated = true requires = [ "re" ] end begin library "re_str" dirname = "%{lib}%/re" generated = true requires = [ "re_emacs" ] end begin library "graph" dirname = "%{lib}%/ocamlgraph" generated = true end begin library "cudf" dirname = "%{lib}%/cudf" generated = true requires = [ "extLib" ] end begin library "dose" dirname = "%{lib}%/dose" generated = true requires = [ "re_pcre" "extLib" "cudf" "graph" "unix" "str" ] end begin library "extLib" dirname = "%{lib}%/extlib" generated = true end begin library "cmdliner" dirname = "%{lib}%/cmdliner" generated = true end opam-1.1.1/README.md0000644000175000017500000000706612272210733012201 0ustar i33173i33173# OPAM - A package manager for OCaml OPAM is a source-based package manager for OCaml. It supports multiple simultaneous compiler installations, flexible package constraints, and a Git-friendly development workflow. OPAM is created and maintained by [OCamlPro](http://www.ocamlpro.com). To get started, checkout the [Quick Install](http://opam.ocaml.org/doc/Quick_Install.html) guide. ## Versioning For transparency and insight into our release cycle, and for striving to maintain backward compatibility, OPAM will be maintained under the Semantic Versioning guidelines as much as possible. Releases will be numbered with the following format: ``` .. ``` And constructed with the following guidelines: * Breaking backward compatibility bumps the major (and resets the minor and patch) * New additions without breaking backward compatibility bumps the minor (and resets the patch) * Bug fixes and misc changes bumps the patch For more information on SemVer, please visit http://semver.org/. It is expected than upgrade work transparently between minor releases: an OPAM binary with version `x.y.z` should be able to use the OCaml packages and compilers created with OPAM version `x.(y-1).0` ## Bug tracker Have a bug or a feature request ? [Please open a new issue](https://github.com/OCamlPro/opam/issues). Before opening any issue, please search for existing issues. ## Community Keep track of development and community news. * Have a question that's not a feature request or bug report? [Ask on the mailing list](http://lists.ocaml.org/listinfo/infrastructure). * Chat with fellow OPAMers in IRC. On the `irc.freenode.net` server, in the `#ocaml` or the `#opam` channel. ## Contributing Please submit all pull requests against the `master` branch. ## Documentation #### User Manual The main documentation entry point to OPAM is the user manual, available using `opam --help`. To get help for a specific command, use `opam --help`. #### Tutorials A collection of tutorials are available online at . These tutorials are automatically generated from the [wiki](https://github.com/OCamlPro/opam/wiki/_pages) and are also available in PDF format in the `doc/tutorials` directory. #### API, Code Documentation and Developer Manual The API documentation is available [online](http://htmlpreview.github.com/?https://github.com/OCamlPro/opam/blob/master/doc/html/index.html) and under the `doc/html/` directory; the developer manual is in the `doc/dev-manual/` directory. ### Related repositories - [OCamlPro/opam-repository](https://github.com/OCamlPro/opam-repository) is the official repository for OPAM packages and compilers. A number of non-official repositories are also available on the interwebs, for instance on [Github](https://github.com/search?q=opam-repo&type=Repositories). - [opam2web](https://github.com/OCamlPro/opam2web) generates a collection of browsable HTML files for a given repository. It is used to generate http://opam.ocaml.org. - [opam-rt](https://github.com/OCamlPro/opam-rt) is the regression framework for OPAM. - [opamlot](https://github.com/ocamllabs/ocamlot) is the automated QA environment for OPAM. ## Copyright and license Copyright 2012-2013 OCamlPro Copyright 2012 INRIA All rights reserved. OPAM is distributed under the terms of the GNU Lesser General Public License version 3.0. OPAM 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 General Public License for more details. opam-1.1.1/Makefile.config.in0000644000175000017500000000014412272210733014221 0ustar i33173i33173datarootdir = @datarootdir@ prefix=@prefix@ mandir=@mandir@ version=@PACKAGE_VERSION@ FETCH=@fetch@ opam-1.1.1/.gitignore0000644000175000017500000000104112272210733012675 0ustar i33173i33173_obuild/ bootstrap/ .*.swp src_ext/cudf/ src_ext/dose/ src_ext/cmdliner/ src_ext/extlib/ src_ext/ocaml-re/ src_ext/ocamlgraph/ src_ext/ocaml-arg/ src_ext/*.stamp src_ext/*.tbz src/lexer.ml src/linelexer.ml src/parser.ml src/parser.mli *.tar.bz2 *.annot *.tar.gz *~ ocp-build.root ocp-build.root.old ocp-get ocp-get-server ocp-build.root.old.old # Generated files: META Makefile.config config.log config.status doc/man-ext/opam-check.md src/core/opamGitVersion.ml src/core/opamScript.ml src/core/opamVersion.ml src/globals.ml src_ext/depends.ocp opam-1.1.1/configure.ac0000644000175000017500000000340612272210733013202 0ustar i33173i33173AC_INIT(opam,1.1.1) AC_COPYRIGHT(Copyright 2012-2014 OcamlPro SAS) AC_CONFIG_MACRO_DIR([m4]) AC_PROG_CC AC_PROG_OCAML if test "$OCAMLC" = "no"; then AC_MSG_ERROR([You must install the OCaml compiler]) fi AC_PROG_CAMLP4 if test "$CAMLP4" = "no"; then AC_MSG_ERROR([You must install the Camlp4 pre-processor. On some operating systems, these are separate packages from the main OCaml compiler, such as camlp4-extra on Debian.]) fi AC_ARG_ENABLE([version_check], AS_HELP_STRING([--disable-version-check], [Do not check OCaml version]) ) # Check that OCaml version is greater or equal to 3.12.1 AS_IF([test "x${enable_version_check}" != "xno"], [ AX_COMPARE_VERSION( [$OCAMLVERSION], [lt], [3.12.1], AC_MSG_ERROR([Your version of OCaml: $OCAMLVERSION is not supported])) ]) AC_ARG_ENABLE([certificate_check], AS_HELP_STRING([--disable-certificate-check], [Do not check the certificate of OPAM's dependency archives]) ) AS_IF([test "x${enable_certificate_check}" = "xno"], [ curl_certificate_check=--insecure wget_certificate_check=--no-check-certificate ]) AC_CHECK_PROGS(FETCH,[curl wget],no) if test x"$FETCH" = x"curl" ; then AC_SUBST(fetch, "curl $curl_certificate_check -OL") elif test x"$FETCH" = x"wget" ; then AC_SUBST(fetch, "wget $wget_certificate_check") else AC_MSG_ERROR([You must have either curl or wget installed.]) fi AC_CONFIG_FILES( Makefile.config src/core/opamVersion.ml doc/man-ext/opam-check.md ) AC_OUTPUT if test "$prefix" = "NONE"; then prefix=$ac_default_prefix fi bindir="`eval echo ${bindir}`" bindir="`eval echo ${bindir}`" mandir="`eval echo ${mandir}`" mandir="`eval echo ${mandir}`" echo echo Executables will be installed in ${bindir} echo Manual pages will be installed in ${mandir} opam-1.1.1/opam.install0000644000175000017500000000014512272210733013235 0ustar i33173i33173bin: [ "_obuild/opam/opam.asm" { "opam" } "_obuild/opam-admin/opam-admin.asm" { "opam-admin" } ] opam-1.1.1/META.in0000644000175000017500000000114212272210733011765 0ustar i33173i33173version = "@VERSION@" description = "OCaml Package Manager base API" requires = "dose, cudf, ocamlgraph, unix, re, re.str, re.glob" archive(byte) = "opam-core.cma" archive(native) = "opam-core.cmxa" package "repositories" ( archive(byte) = "opam-repositories.cma" archive(native) = "opam-repositories.cmxa" requires = "opam" ) package "solver" ( archive(byte) = "opam-solver.cma" archive(native) = "opam-solver.cmxa" requires = "opam" ) package "client" ( archive(byte) = "opam-client.cma" archive(native) = "opam-client.cmxa" requires = "opam, opam.solver, opam.repositories, cmdliner" ) opam-1.1.1/.ocp-indent0000644000175000017500000000000612272210733012746 0ustar i33173i33173normalopam-1.1.1/shell/0000755000175000017500000000000012272210733012020 5ustar i33173i33173opam-1.1.1/shell/bootstrap-ocaml.sh0000755000175000017500000000036312272210733015467 0ustar i33173i33173#!/bin/sh -ex rm -rf bootstrap mkdir bootstrap cd bootstrap curl -OL http://caml.inria.fr/pub/distrib/ocaml-4.01/ocaml-4.01.0.tar.gz tar -zxvf ocaml-4.01.0.tar.gz cd ocaml-4.01.0 ./configure -prefix `pwd`/../ocaml make world opt make install opam-1.1.1/shell/make_opam_binary.sh0000755000175000017500000000307212272210733015656 0ustar i33173i33173#!/bin/sh # (c) Copyright Fabrice Le Fessant INRIA/OCamlPro 2013 # (c) Copyright Thomas Gazagnaire OCamlPro 2013 set -e usage() { cat <&2 exit 1 } if [ $# = 0 ]; then echo "OPAM binary builder." usage fi VERSION=$1 BUILDDIR=tmp-opam-$VERSION CURRENTDIR=`pwd` UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown target="opam-${VERSION}-${UNAME_MACHINE}-${UNAME_SYSTEM}" if which wget >/dev/null; then WGETOPTS="--passive-ftp -q -O" else WGETOPTS="-OL -o" wget() { shift curl -OL $* } fi # Download the source archive from the web download() { url="$1" mkdir -p $BUILDDIR cd $BUILDDIR file=opam-full-$VERSION.tar.gz echo "Downloading ${url}/${file} ..." wget $WGETOPTS $file "$url/$file" || error "Couldn't download $url/$file" } # Extract the source archive extract() { tar xfvz opam-full-$VERSION.tar.gz cd opam-full-$VERSION } # Build the binary build() { ./configure pwd make cd $CURRENTDIR ln -sf $BUILDDIR/opam-full-$VERSION/_obuild/opam/opam.asm $target } { download "http://www.ocamlpro.com/pub" extract build } 1>&2 echo $target opam-1.1.1/shell/opam_completion.sh0000644000175000017500000000435312272210733015546 0ustar i33173i33173_opam_add() { _opam_reply="$_opam_reply $1" } _opam_global_options() { local res res="$( opam --help=plain 2>/dev/null | grep '^ -' | sed 's/ *//;s/[ ,\[\=].*//' )" _opam_add "$res" } _opam_commands() { local res res="$( opam help topics )" _opam_add "$res" } _opam_flags() { local res cmd cmd="$1" res="$( opam $cmd --help=plain 2>/dev/null | grep '^ -' | sed 's/ *//;s/[ ,\[\=].*//' )" _opam_add "$res" } _opam_packages() { local res res="$( opam list -a -s )" _opam_add "$res" } _opam_installed_packages() { local res res="$( opam list -i -s )" _opam_add "$res" } _opam_compilers() { local res res="$( opam switch -s )" _opam_add "$res" } _opam_config_subcommands() { _opam_add "env var list subst includes bytecomp asmcomp bytelink asmlink" } _opam_config_vars() { local res res="$( opam config list 2>/dev/null | sed 's/ *//;s/ .*//' )" _opam_reply="$res" } _opam_repository_subcommands() { _opam_add "add remove list priority" } _opam_repositories() { local res res="$( opam remote -s )" _opam_add "$res" } _opam_repositories_only() { _opam_reply="$( opam remote -s )" } _opam() { local cmd cur prev COMPREPLY=() cmd=${COMP_WORDS[1]} subcmd=${COMP_WORDS[2]} cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} _opam_reply="" _opam_global_options if [ $COMP_CWORD -eq 1 ]; then _opam_commands elif [ $COMP_CWORD -gt 1 ]; then _opam_flags "$cmd" case "$cmd" in install|info) _opam_packages ;; reinstall|remove) _opam_installed_packages ;; switch) _opam_compilers ;; config) _opam_config_subcommands if [ "$prev" = "var" ]; then _opam_config_vars; fi ;; repository) _opam_repository_subcommands case "$subcmd" in remove) _opam_repositories_only ;; esac ;; update) _opam_repositories ;; esac fi COMPREPLY=( $(compgen -W "$_opam_reply" -- $cur) ) unset _opam_reply return 0 } complete -F _opam opam opam-1.1.1/shell/get-git-id.ml0000644000175000017500000000213412272210733014304 0ustar i33173i33173let file = if Array.length Sys.argv <> 2 then ( Printf.eprintf "usage: ocaml %s \n" Sys.argv.(0); exit 1 ) else Sys.argv.(1) let read file = if Sys.file_exists file then let ic = open_in_bin file in Some (input_line ic) else None let write file contents = let write () = let oc = open_out file in output_string oc contents; output_char oc '\n'; close_out oc in match read file with | None -> write () | Some actual -> if actual <> contents then write () let (/) = Filename.concat let git file = ".git" / file let () = let opamGitVersion = "src" / "core" / "opamGitVersion.ml" in let version_none () = write opamGitVersion "let version = None" in match read (git "HEAD") with | None -> version_none () | Some s -> let reference = try let c = String.rindex s ' ' in String.sub s (c+1) (String.length s -c-1) with Not_found -> s in match read (git reference) with | None -> version_none () | Some sha1 -> write opamGitVersion (Printf.sprintf "let version = Some %S" sha1) opam-1.1.1/shell/crunch.ml0000644000175000017500000000061212272210733013633 0ustar i33173i33173let add_stdin buf = try while true do let line = input_line stdin in Buffer.add_string buf line; Buffer.add_char buf '\n' done with End_of_file -> () let () = let name = Sys.argv.(1) in let buf = Buffer.create 1024 in add_stdin buf; let contents = Buffer.contents buf in Printf.printf "let %s =\n\"%s\"\n\n" name (String.escaped contents) opam-1.1.1/shell/opam_completion_zsh.sh0000644000175000017500000000366612272210733016440 0ustar i33173i33173_opam_add() { _opam_reply="$_opam_reply $1" } _opam_global_options() { local res res="$( opam --help=plain 2>/dev/null | grep '^ -' | sed 's/ *//;s/[ ,\[\=].*//' )" _opam_add "$res" } _opam_commands() { local res res="$( opam help topics )" _opam_add "$res" } _opam_flags() { local res cmd cmd="$1" res="$( opam $cmd --help=plain 2>/dev/null | grep '^ -' | sed 's/ *//;s/[ ,\[\=].*//' )" _opam_add "$res" } _opam_packages() { local res res="$( opam list -s -a)" _opam_add "$res" } _opam_installed_packages() { local res res="$( opam list -i -s )" _opam_add "$res" } _opam_compilers() { local res count res="$( opam switch -s )" _opam_add "$res" } _opam_config_subcommands() { _opam_add "env var list subst includes bytecomp asmcomp bytelink asmlink" } _opam_config_vars() { local res res="$( opam config list 2>/dev/null | sed 's/ *//;s/ .*//' )" _opam_reply="$res" } _opam_repository_subcommands() { _opam_add "add remove list priority" } _opam_repositories() { local res res="$( opam remote -s )" _opam_add "$res" } _opam_repositories_only() { _opam_reply="$( opam remote -s )" } _opam() { local cmd cur prev COMPREPLY=() cmd=${COMP_WORDS[1]} subcmd=${COMP_WORDS[2]} cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} _opam_reply="" _opam_global_options if [ $COMP_CWORD -eq 1 ]; then _opam_commands elif [ $COMP_CWORD -gt 1 ]; then _opam_flags "$cmd" case "$cmd" in install) _opam_packages ;; remove) _opam_installed_packages ;; switch) _opam_compilers ;; config) if [ "$prev" = "-var" ]; then _opam_config_vars; fi ;; esac fi COMPREPLY=( $(compgen -W "$_opam_reply" -- $cur) ) unset _opam_reply return 0 } autoload bashcompinit bashcompinit complete -F _opam opam opam-1.1.1/shell/dot_ocamlinit0000644000175000017500000000014112272210733014564 0ustar i33173i33173let () = try Topdirs.dir_directory (Sys.getenv "OCAML_TOPLEVEL_PATH") with Not_found -> () ;;opam-1.1.1/shell/opam_switch_eval.sh0000644000175000017500000000013712272210733015701 0ustar i33173i33173function opam-switch-eval () { opam switch "$@" --no-warning eval $(opam config env) } opam-1.1.1/shell/opam_installer.sh0000644000175000017500000000521012272210733015363 0ustar i33173i33173#!/bin/sh set -e # (c) Copyright Fabrice Le Fessant INRIA/OCamlPro 2013 VERSION='1.1.0' default_ocaml=4.01.0 usage() { cat <&2 exit 1 } SYSTEM=`uname -s` if which wget >/dev/null; then WGETOPTS="--passive-ftp -q -O" else WGETOPTS="-OL -o" wget() { shift curl -OL $* } fi # # Download a file from the web, unzip it, and extract the # files we want getopam() { url="$1" opamfile="$2" wget $WGETOPTS $opamfile "$url/$opamfile" || error "Couldn't download $url/$opamfile" chmod +x $opamfile } if [ $# = 0 ]; then echo "OPAM binary installer v. $VERSION" usage fi BINDIR=$1 COMP=$2 UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown # Note: order is significant - the case branches are not exclusive. case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in x86_64:Linux:*:*) file="opam-${VERSION}-${UNAME_MACHINE}-${UNAME_SYSTEM}" ;; x86_64:Darwin:*:*) file="opam-${VERSION}-${UNAME_MACHINE}-${UNAME_SYSTEM}" ;; i686:Linux:*:*) file="opam-${VERSION}-${UNAME_MACHINE}-${UNAME_SYSTEM}" ;; *) echo "No file yet for ${UNAME_MACHINE}:${UNAME_SYSTEM}" exit 1 ;; esac echo Downloading OPAM... getopam "http://www.ocamlpro.com/pub" $file if [ $(id -ru) -ne 0 ]; then echo "Do you need to use sudo to write to $BINDIR (y/N) ?" read rep if test "$rep" = "y"; then echo "[sudo is probably going to ask for your password]" sudo mv $file $BINDIR/opam else mv $file $BINDIR/opam fi else mv $file $BINDIR/opam fi PATH=$BINDIR:$PATH export PATH if test "$COMP" = ""; then COMPOPT="--comp ${default_ocaml}" else if test "$COMP" = "system"; then COMPOPT= else COMPOPT="--comp ${COMP}" fi fi if test -d $HOME/.opam; then echo 'You already have a ~/.opam directory' echo 'If you have problems, you should consider removing it' echo ' and run:' echo "opam init $COMPOPT" else echo Initializing with compiler $COMP opam init $COMPOPT fi echo 'To use OCaml installed by OPAM, use' echo 'eval `opam config env`' opam-1.1.1/shell/md5check.ml0000644000175000017500000000073212272210733014037 0ustar i33173i33173let file, md5 = if Array.length Sys.argv <> 3 then ( Printf.eprintf "usage: ocaml %s \n" Sys.argv.(0); exit 1 ) else Sys.argv.(1), Sys.argv.(2) let md5_of_file = Digest.to_hex (Digest.file file) let () = if md5 <> md5_of_file then ( Printf.eprintf "MD5 for %s differ:\n\ \ expected: %s\n\ \ actual: %s\n" file md5 md5_of_file; Sys.remove file ) else Printf.printf "%s has the expected MD5.\n" file opam-1.1.1/.travis-ci.sh0000755000175000017500000000263712272210733013237 0ustar i33173i33173# Git should be configured properely to run the tests git config --global user.email "travis@example.com" git config --global user.name "Travis CI" # Install OCaml and OPAM PPAs case "$OCAML_VERSION" in 3.12.1) ppa=avsm/ocaml312+opam11 ;; 4.00.1) ppa=avsm/ocaml40+opam11 ;; 4.01.0) ppa=avsm/ocaml41+opam11 ;; *) echo Unknown $OCAML_VERSION; exit 1 ;; esac # Install OCaml echo "yes" | sudo add-apt-repository ppa:$ppa sudo apt-get update -qq sudo apt-get install -qq ocaml ocaml-native-compilers camlp4-extra time echo OCaml version ocaml -version export OPAMYES=1 if [ "$OPAM_TEST" = "1" ]; then # Compile OPAM using the system libraries (install them using OPAM) sudo apt-get install opam aspcud opam init eval `opam config env` opam install lwt cohttp ssl cmdliner ocamlgraph dose cudf re ./configure make prepare make compile # overwrite the previous install of OPAM with the new binary # and libraries sudo make install make libinstall # Compile and run opam-rt wget https://github.com/ocaml/opam-rt/archive/master.tar.gz tar xvfz master.tar.gz cd opam-rt-master make make KINDS="local git" run else # Compile OPAM from sources and run the basic tests ./configure make make tests > tests.log 2>&1 || (tail -1000 tests.log && exit 1) # Let's see basic tasks works sudo make install opam init opam install lwt opam list fi opam-1.1.1/CONTRIBUTING.md0000644000175000017500000000100612272210733013137 0ustar i33173i33173Bug reports and feature requests for **the OPAM tool** should be reported on: * http://github.com/ocaml/opam/issues (please include the output of `opam config report` whenever possible) **Packaging issues** or requests for a new package should be reported on: * http://github.com/ocaml/opam-repository/issues **General queries** can be addressed at: * http://lists.ocaml.org/listinfo/platform (for the both the tool & packages) * http://lists.ocaml.org/listinfo/opam-devel (for the tool and its evolution) opam-1.1.1/configure0000755000175000017500000050361512272210733012632 0ustar i33173i33173#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69 for opam 1.1.1. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. # # Copyright 2012-2014 OcamlPro SAS ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 as_fn_exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, $0: including any error possibly output before this $0: message. Then install a modern shell, or manually run $0: the script under such a shell if you do have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='opam' PACKAGE_TARNAME='opam' PACKAGE_VERSION='1.1.1' PACKAGE_STRING='opam 1.1.1' PACKAGE_BUGREPORT='' PACKAGE_URL='' ac_subst_vars='LTLIBOBJS LIBOBJS fetch FETCH AWK CAMLP4RF CAMLP4R CAMLP4PROF CAMLP4ORF CAMLP4OOF CAMLP4OF CAMLP4O CAMLP4 OCAMLBUILD OCAMLDOC OCAMLMKLIB OCAMLMKTOP OCAMLDEP OCAML OCAMLOPTDOTOPT OCAMLCDOTOPT OCAMLBEST OCAMLOPT OCAMLLIB OCAMLVERSION OCAMLC OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking enable_version_check enable_certificate_check ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures opam 1.1.1 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/opam] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of opam 1.1.1:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --disable-version-check Do not check OCaml version --disable-certificate-check Do not check the certificate of OPAM's dependency archives Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to the package provider. _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF opam configure 1.1.1 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. Copyright 2012-2014 OcamlPro SAS _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by opam $as_me 1.1.1, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo $as_echo "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo $as_echo "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then $as_echo "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then $as_echo "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then # We do not want a PATH search for config.site. case $CONFIG_SITE in #(( -*) ac_site_file1=./$CONFIG_SITE;; */*) ac_site_file1=$CONFIG_SITE;; *) ac_site_file1=./$CONFIG_SITE;; esac elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See \`config.log' for more details" "$LINENO" 5; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if ${ac_cv_objext+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # checking for ocamlc if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ocamlc", so it can be a program name with args. set dummy ${ac_tool_prefix}ocamlc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OCAMLC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OCAMLC"; then ac_cv_prog_OCAMLC="$OCAMLC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OCAMLC="${ac_tool_prefix}ocamlc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OCAMLC=$ac_cv_prog_OCAMLC if test -n "$OCAMLC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OCAMLC" >&5 $as_echo "$OCAMLC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OCAMLC"; then ac_ct_OCAMLC=$OCAMLC # Extract the first word of "ocamlc", so it can be a program name with args. set dummy ocamlc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OCAMLC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OCAMLC"; then ac_cv_prog_ac_ct_OCAMLC="$ac_ct_OCAMLC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OCAMLC="ocamlc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OCAMLC=$ac_cv_prog_ac_ct_OCAMLC if test -n "$ac_ct_OCAMLC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OCAMLC" >&5 $as_echo "$ac_ct_OCAMLC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OCAMLC" = x; then OCAMLC="no" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OCAMLC=$ac_ct_OCAMLC fi else OCAMLC="$ac_cv_prog_OCAMLC" fi if test "$OCAMLC" != "no"; then OCAMLVERSION=`$OCAMLC -v | sed -n -e 's|.*version* *\(.*\)$|\1|p'` { $as_echo "$as_me:${as_lineno-$LINENO}: result: OCaml version is $OCAMLVERSION" >&5 $as_echo "OCaml version is $OCAMLVERSION" >&6; } # If OCAMLLIB is set, use it if test "$OCAMLLIB" = ""; then OCAMLLIB=`$OCAMLC -where 2>/dev/null || $OCAMLC -v|tail -1|cut -d ' ' -f 4` else { $as_echo "$as_me:${as_lineno-$LINENO}: result: OCAMLLIB previously set; preserving it." >&5 $as_echo "OCAMLLIB previously set; preserving it." >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: OCaml library path is $OCAMLLIB" >&5 $as_echo "OCaml library path is $OCAMLLIB" >&6; } # checking for ocamlopt if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ocamlopt", so it can be a program name with args. set dummy ${ac_tool_prefix}ocamlopt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OCAMLOPT+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OCAMLOPT"; then ac_cv_prog_OCAMLOPT="$OCAMLOPT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OCAMLOPT="${ac_tool_prefix}ocamlopt" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OCAMLOPT=$ac_cv_prog_OCAMLOPT if test -n "$OCAMLOPT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OCAMLOPT" >&5 $as_echo "$OCAMLOPT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OCAMLOPT"; then ac_ct_OCAMLOPT=$OCAMLOPT # Extract the first word of "ocamlopt", so it can be a program name with args. set dummy ocamlopt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OCAMLOPT+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OCAMLOPT"; then ac_cv_prog_ac_ct_OCAMLOPT="$ac_ct_OCAMLOPT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OCAMLOPT="ocamlopt" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OCAMLOPT=$ac_cv_prog_ac_ct_OCAMLOPT if test -n "$ac_ct_OCAMLOPT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OCAMLOPT" >&5 $as_echo "$ac_ct_OCAMLOPT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OCAMLOPT" = x; then OCAMLOPT="no" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OCAMLOPT=$ac_ct_OCAMLOPT fi else OCAMLOPT="$ac_cv_prog_OCAMLOPT" fi OCAMLBEST=byte if test "$OCAMLOPT" = "no"; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Cannot find ocamlopt; bytecode compilation only." >&5 $as_echo "$as_me: WARNING: Cannot find ocamlopt; bytecode compilation only." >&2;} else TMPVERSION=`$OCAMLOPT -v | sed -n -e 's|.*version* *\(.*\)$|\1|p' ` if test "$TMPVERSION" != "$OCAMLVERSION" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: versions differs from ocamlc $TMPVERSION != $OCAMLVERSION; ocamlopt discarded." >&5 $as_echo "versions differs from ocamlc $TMPVERSION != $OCAMLVERSION; ocamlopt discarded." >&6; } OCAMLOPT=no else OCAMLBEST=opt fi fi # checking for ocamlc.opt if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ocamlc.opt", so it can be a program name with args. set dummy ${ac_tool_prefix}ocamlc.opt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OCAMLCDOTOPT+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OCAMLCDOTOPT"; then ac_cv_prog_OCAMLCDOTOPT="$OCAMLCDOTOPT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OCAMLCDOTOPT="${ac_tool_prefix}ocamlc.opt" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OCAMLCDOTOPT=$ac_cv_prog_OCAMLCDOTOPT if test -n "$OCAMLCDOTOPT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OCAMLCDOTOPT" >&5 $as_echo "$OCAMLCDOTOPT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OCAMLCDOTOPT"; then ac_ct_OCAMLCDOTOPT=$OCAMLCDOTOPT # Extract the first word of "ocamlc.opt", so it can be a program name with args. set dummy ocamlc.opt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OCAMLCDOTOPT+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OCAMLCDOTOPT"; then ac_cv_prog_ac_ct_OCAMLCDOTOPT="$ac_ct_OCAMLCDOTOPT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OCAMLCDOTOPT="ocamlc.opt" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OCAMLCDOTOPT=$ac_cv_prog_ac_ct_OCAMLCDOTOPT if test -n "$ac_ct_OCAMLCDOTOPT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OCAMLCDOTOPT" >&5 $as_echo "$ac_ct_OCAMLCDOTOPT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OCAMLCDOTOPT" = x; then OCAMLCDOTOPT="no" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OCAMLCDOTOPT=$ac_ct_OCAMLCDOTOPT fi else OCAMLCDOTOPT="$ac_cv_prog_OCAMLCDOTOPT" fi if test "$OCAMLCDOTOPT" != "no"; then TMPVERSION=`$OCAMLCDOTOPT -v | sed -n -e 's|.*version* *\(.*\)$|\1|p' ` if test "$TMPVERSION" != "$OCAMLVERSION" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: versions differs from ocamlc $TMPVERSION != $OCAMLVERSION; ocamlc.opt discarded." >&5 $as_echo "versions differs from ocamlc $TMPVERSION != $OCAMLVERSION; ocamlc.opt discarded." >&6; } else OCAMLC=$OCAMLCDOTOPT fi fi # checking for ocamlopt.opt if test "$OCAMLOPT" != "no" ; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ocamlopt.opt", so it can be a program name with args. set dummy ${ac_tool_prefix}ocamlopt.opt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OCAMLOPTDOTOPT+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OCAMLOPTDOTOPT"; then ac_cv_prog_OCAMLOPTDOTOPT="$OCAMLOPTDOTOPT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OCAMLOPTDOTOPT="${ac_tool_prefix}ocamlopt.opt" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OCAMLOPTDOTOPT=$ac_cv_prog_OCAMLOPTDOTOPT if test -n "$OCAMLOPTDOTOPT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OCAMLOPTDOTOPT" >&5 $as_echo "$OCAMLOPTDOTOPT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OCAMLOPTDOTOPT"; then ac_ct_OCAMLOPTDOTOPT=$OCAMLOPTDOTOPT # Extract the first word of "ocamlopt.opt", so it can be a program name with args. set dummy ocamlopt.opt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OCAMLOPTDOTOPT+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OCAMLOPTDOTOPT"; then ac_cv_prog_ac_ct_OCAMLOPTDOTOPT="$ac_ct_OCAMLOPTDOTOPT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OCAMLOPTDOTOPT="ocamlopt.opt" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OCAMLOPTDOTOPT=$ac_cv_prog_ac_ct_OCAMLOPTDOTOPT if test -n "$ac_ct_OCAMLOPTDOTOPT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OCAMLOPTDOTOPT" >&5 $as_echo "$ac_ct_OCAMLOPTDOTOPT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OCAMLOPTDOTOPT" = x; then OCAMLOPTDOTOPT="no" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OCAMLOPTDOTOPT=$ac_ct_OCAMLOPTDOTOPT fi else OCAMLOPTDOTOPT="$ac_cv_prog_OCAMLOPTDOTOPT" fi if test "$OCAMLOPTDOTOPT" != "no"; then TMPVERSION=`$OCAMLOPTDOTOPT -v | sed -n -e 's|.*version* *\(.*\)$|\1|p' ` if test "$TMPVERSION" != "$OCAMLVERSION" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: versions differs from ocamlc $TMPVERSION != $OCAMLVERSION; ocamlopt.opt discarded." >&5 $as_echo "versions differs from ocamlc $TMPVERSION != $OCAMLVERSION; ocamlopt.opt discarded." >&6; } else OCAMLOPT=$OCAMLOPTDOTOPT fi fi fi fi # checking for ocaml toplevel if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ocaml", so it can be a program name with args. set dummy ${ac_tool_prefix}ocaml; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OCAML+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OCAML"; then ac_cv_prog_OCAML="$OCAML" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OCAML="${ac_tool_prefix}ocaml" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OCAML=$ac_cv_prog_OCAML if test -n "$OCAML"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OCAML" >&5 $as_echo "$OCAML" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OCAML"; then ac_ct_OCAML=$OCAML # Extract the first word of "ocaml", so it can be a program name with args. set dummy ocaml; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OCAML+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OCAML"; then ac_cv_prog_ac_ct_OCAML="$ac_ct_OCAML" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OCAML="ocaml" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OCAML=$ac_cv_prog_ac_ct_OCAML if test -n "$ac_ct_OCAML"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OCAML" >&5 $as_echo "$ac_ct_OCAML" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OCAML" = x; then OCAML="no" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OCAML=$ac_ct_OCAML fi else OCAML="$ac_cv_prog_OCAML" fi # checking for ocamldep if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ocamldep", so it can be a program name with args. set dummy ${ac_tool_prefix}ocamldep; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OCAMLDEP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OCAMLDEP"; then ac_cv_prog_OCAMLDEP="$OCAMLDEP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OCAMLDEP="${ac_tool_prefix}ocamldep" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OCAMLDEP=$ac_cv_prog_OCAMLDEP if test -n "$OCAMLDEP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OCAMLDEP" >&5 $as_echo "$OCAMLDEP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OCAMLDEP"; then ac_ct_OCAMLDEP=$OCAMLDEP # Extract the first word of "ocamldep", so it can be a program name with args. set dummy ocamldep; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OCAMLDEP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OCAMLDEP"; then ac_cv_prog_ac_ct_OCAMLDEP="$ac_ct_OCAMLDEP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OCAMLDEP="ocamldep" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OCAMLDEP=$ac_cv_prog_ac_ct_OCAMLDEP if test -n "$ac_ct_OCAMLDEP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OCAMLDEP" >&5 $as_echo "$ac_ct_OCAMLDEP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OCAMLDEP" = x; then OCAMLDEP="no" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OCAMLDEP=$ac_ct_OCAMLDEP fi else OCAMLDEP="$ac_cv_prog_OCAMLDEP" fi # checking for ocamlmktop if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ocamlmktop", so it can be a program name with args. set dummy ${ac_tool_prefix}ocamlmktop; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OCAMLMKTOP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OCAMLMKTOP"; then ac_cv_prog_OCAMLMKTOP="$OCAMLMKTOP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OCAMLMKTOP="${ac_tool_prefix}ocamlmktop" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OCAMLMKTOP=$ac_cv_prog_OCAMLMKTOP if test -n "$OCAMLMKTOP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OCAMLMKTOP" >&5 $as_echo "$OCAMLMKTOP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OCAMLMKTOP"; then ac_ct_OCAMLMKTOP=$OCAMLMKTOP # Extract the first word of "ocamlmktop", so it can be a program name with args. set dummy ocamlmktop; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OCAMLMKTOP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OCAMLMKTOP"; then ac_cv_prog_ac_ct_OCAMLMKTOP="$ac_ct_OCAMLMKTOP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OCAMLMKTOP="ocamlmktop" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OCAMLMKTOP=$ac_cv_prog_ac_ct_OCAMLMKTOP if test -n "$ac_ct_OCAMLMKTOP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OCAMLMKTOP" >&5 $as_echo "$ac_ct_OCAMLMKTOP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OCAMLMKTOP" = x; then OCAMLMKTOP="no" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OCAMLMKTOP=$ac_ct_OCAMLMKTOP fi else OCAMLMKTOP="$ac_cv_prog_OCAMLMKTOP" fi # checking for ocamlmklib if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ocamlmklib", so it can be a program name with args. set dummy ${ac_tool_prefix}ocamlmklib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OCAMLMKLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OCAMLMKLIB"; then ac_cv_prog_OCAMLMKLIB="$OCAMLMKLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OCAMLMKLIB="${ac_tool_prefix}ocamlmklib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OCAMLMKLIB=$ac_cv_prog_OCAMLMKLIB if test -n "$OCAMLMKLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OCAMLMKLIB" >&5 $as_echo "$OCAMLMKLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OCAMLMKLIB"; then ac_ct_OCAMLMKLIB=$OCAMLMKLIB # Extract the first word of "ocamlmklib", so it can be a program name with args. set dummy ocamlmklib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OCAMLMKLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OCAMLMKLIB"; then ac_cv_prog_ac_ct_OCAMLMKLIB="$ac_ct_OCAMLMKLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OCAMLMKLIB="ocamlmklib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OCAMLMKLIB=$ac_cv_prog_ac_ct_OCAMLMKLIB if test -n "$ac_ct_OCAMLMKLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OCAMLMKLIB" >&5 $as_echo "$ac_ct_OCAMLMKLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OCAMLMKLIB" = x; then OCAMLMKLIB="no" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OCAMLMKLIB=$ac_ct_OCAMLMKLIB fi else OCAMLMKLIB="$ac_cv_prog_OCAMLMKLIB" fi # checking for ocamldoc if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ocamldoc", so it can be a program name with args. set dummy ${ac_tool_prefix}ocamldoc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OCAMLDOC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OCAMLDOC"; then ac_cv_prog_OCAMLDOC="$OCAMLDOC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OCAMLDOC="${ac_tool_prefix}ocamldoc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OCAMLDOC=$ac_cv_prog_OCAMLDOC if test -n "$OCAMLDOC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OCAMLDOC" >&5 $as_echo "$OCAMLDOC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OCAMLDOC"; then ac_ct_OCAMLDOC=$OCAMLDOC # Extract the first word of "ocamldoc", so it can be a program name with args. set dummy ocamldoc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OCAMLDOC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OCAMLDOC"; then ac_cv_prog_ac_ct_OCAMLDOC="$ac_ct_OCAMLDOC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OCAMLDOC="ocamldoc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OCAMLDOC=$ac_cv_prog_ac_ct_OCAMLDOC if test -n "$ac_ct_OCAMLDOC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OCAMLDOC" >&5 $as_echo "$ac_ct_OCAMLDOC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OCAMLDOC" = x; then OCAMLDOC="no" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OCAMLDOC=$ac_ct_OCAMLDOC fi else OCAMLDOC="$ac_cv_prog_OCAMLDOC" fi # checking for ocamlbuild if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ocamlbuild", so it can be a program name with args. set dummy ${ac_tool_prefix}ocamlbuild; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OCAMLBUILD+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OCAMLBUILD"; then ac_cv_prog_OCAMLBUILD="$OCAMLBUILD" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OCAMLBUILD="${ac_tool_prefix}ocamlbuild" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OCAMLBUILD=$ac_cv_prog_OCAMLBUILD if test -n "$OCAMLBUILD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OCAMLBUILD" >&5 $as_echo "$OCAMLBUILD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OCAMLBUILD"; then ac_ct_OCAMLBUILD=$OCAMLBUILD # Extract the first word of "ocamlbuild", so it can be a program name with args. set dummy ocamlbuild; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OCAMLBUILD+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OCAMLBUILD"; then ac_cv_prog_ac_ct_OCAMLBUILD="$ac_ct_OCAMLBUILD" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OCAMLBUILD="ocamlbuild" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OCAMLBUILD=$ac_cv_prog_ac_ct_OCAMLBUILD if test -n "$ac_ct_OCAMLBUILD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OCAMLBUILD" >&5 $as_echo "$ac_ct_OCAMLBUILD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OCAMLBUILD" = x; then OCAMLBUILD="no" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OCAMLBUILD=$ac_ct_OCAMLBUILD fi else OCAMLBUILD="$ac_cv_prog_OCAMLBUILD" fi if test "$OCAMLC" = "no"; then as_fn_error $? "You must install the OCaml compiler" "$LINENO" 5 fi # checking for camlp4 if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}camlp4", so it can be a program name with args. set dummy ${ac_tool_prefix}camlp4; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CAMLP4+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CAMLP4"; then ac_cv_prog_CAMLP4="$CAMLP4" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CAMLP4="${ac_tool_prefix}camlp4" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CAMLP4=$ac_cv_prog_CAMLP4 if test -n "$CAMLP4"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CAMLP4" >&5 $as_echo "$CAMLP4" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CAMLP4"; then ac_ct_CAMLP4=$CAMLP4 # Extract the first word of "camlp4", so it can be a program name with args. set dummy camlp4; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CAMLP4+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CAMLP4"; then ac_cv_prog_ac_ct_CAMLP4="$ac_ct_CAMLP4" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CAMLP4="camlp4" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CAMLP4=$ac_cv_prog_ac_ct_CAMLP4 if test -n "$ac_ct_CAMLP4"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CAMLP4" >&5 $as_echo "$ac_ct_CAMLP4" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CAMLP4" = x; then CAMLP4="no" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CAMLP4=$ac_ct_CAMLP4 fi else CAMLP4="$ac_cv_prog_CAMLP4" fi if test "$CAMLP4" != "no"; then TMPVERSION=`$CAMLP4 -v 2>&1| sed -n -e 's|.*version *\(.*\)$|\1|p'` if test "$TMPVERSION" != "$OCAMLVERSION" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: versions differs from ocamlc $TMPVERSION != $OCAMLVERSION." >&5 $as_echo "versions differs from ocamlc $TMPVERSION != $OCAMLVERSION." >&6; } CAMLP4=no fi fi # checking for companion tools if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}camlp4o", so it can be a program name with args. set dummy ${ac_tool_prefix}camlp4o; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CAMLP4O+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CAMLP4O"; then ac_cv_prog_CAMLP4O="$CAMLP4O" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CAMLP4O="${ac_tool_prefix}camlp4o" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CAMLP4O=$ac_cv_prog_CAMLP4O if test -n "$CAMLP4O"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CAMLP4O" >&5 $as_echo "$CAMLP4O" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CAMLP4O"; then ac_ct_CAMLP4O=$CAMLP4O # Extract the first word of "camlp4o", so it can be a program name with args. set dummy camlp4o; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CAMLP4O+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CAMLP4O"; then ac_cv_prog_ac_ct_CAMLP4O="$ac_ct_CAMLP4O" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CAMLP4O="camlp4o" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CAMLP4O=$ac_cv_prog_ac_ct_CAMLP4O if test -n "$ac_ct_CAMLP4O"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CAMLP4O" >&5 $as_echo "$ac_ct_CAMLP4O" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CAMLP4O" = x; then CAMLP4O="no" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CAMLP4O=$ac_ct_CAMLP4O fi else CAMLP4O="$ac_cv_prog_CAMLP4O" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}camlp4of", so it can be a program name with args. set dummy ${ac_tool_prefix}camlp4of; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CAMLP4OF+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CAMLP4OF"; then ac_cv_prog_CAMLP4OF="$CAMLP4OF" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CAMLP4OF="${ac_tool_prefix}camlp4of" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CAMLP4OF=$ac_cv_prog_CAMLP4OF if test -n "$CAMLP4OF"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CAMLP4OF" >&5 $as_echo "$CAMLP4OF" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CAMLP4OF"; then ac_ct_CAMLP4OF=$CAMLP4OF # Extract the first word of "camlp4of", so it can be a program name with args. set dummy camlp4of; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CAMLP4OF+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CAMLP4OF"; then ac_cv_prog_ac_ct_CAMLP4OF="$ac_ct_CAMLP4OF" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CAMLP4OF="camlp4of" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CAMLP4OF=$ac_cv_prog_ac_ct_CAMLP4OF if test -n "$ac_ct_CAMLP4OF"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CAMLP4OF" >&5 $as_echo "$ac_ct_CAMLP4OF" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CAMLP4OF" = x; then CAMLP4OF="no" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CAMLP4OF=$ac_ct_CAMLP4OF fi else CAMLP4OF="$ac_cv_prog_CAMLP4OF" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}camlp4oof", so it can be a program name with args. set dummy ${ac_tool_prefix}camlp4oof; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CAMLP4OOF+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CAMLP4OOF"; then ac_cv_prog_CAMLP4OOF="$CAMLP4OOF" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CAMLP4OOF="${ac_tool_prefix}camlp4oof" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CAMLP4OOF=$ac_cv_prog_CAMLP4OOF if test -n "$CAMLP4OOF"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CAMLP4OOF" >&5 $as_echo "$CAMLP4OOF" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CAMLP4OOF"; then ac_ct_CAMLP4OOF=$CAMLP4OOF # Extract the first word of "camlp4oof", so it can be a program name with args. set dummy camlp4oof; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CAMLP4OOF+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CAMLP4OOF"; then ac_cv_prog_ac_ct_CAMLP4OOF="$ac_ct_CAMLP4OOF" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CAMLP4OOF="camlp4oof" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CAMLP4OOF=$ac_cv_prog_ac_ct_CAMLP4OOF if test -n "$ac_ct_CAMLP4OOF"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CAMLP4OOF" >&5 $as_echo "$ac_ct_CAMLP4OOF" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CAMLP4OOF" = x; then CAMLP4OOF="no" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CAMLP4OOF=$ac_ct_CAMLP4OOF fi else CAMLP4OOF="$ac_cv_prog_CAMLP4OOF" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}camlp4orf", so it can be a program name with args. set dummy ${ac_tool_prefix}camlp4orf; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CAMLP4ORF+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CAMLP4ORF"; then ac_cv_prog_CAMLP4ORF="$CAMLP4ORF" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CAMLP4ORF="${ac_tool_prefix}camlp4orf" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CAMLP4ORF=$ac_cv_prog_CAMLP4ORF if test -n "$CAMLP4ORF"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CAMLP4ORF" >&5 $as_echo "$CAMLP4ORF" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CAMLP4ORF"; then ac_ct_CAMLP4ORF=$CAMLP4ORF # Extract the first word of "camlp4orf", so it can be a program name with args. set dummy camlp4orf; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CAMLP4ORF+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CAMLP4ORF"; then ac_cv_prog_ac_ct_CAMLP4ORF="$ac_ct_CAMLP4ORF" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CAMLP4ORF="camlp4orf" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CAMLP4ORF=$ac_cv_prog_ac_ct_CAMLP4ORF if test -n "$ac_ct_CAMLP4ORF"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CAMLP4ORF" >&5 $as_echo "$ac_ct_CAMLP4ORF" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CAMLP4ORF" = x; then CAMLP4ORF="no" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CAMLP4ORF=$ac_ct_CAMLP4ORF fi else CAMLP4ORF="$ac_cv_prog_CAMLP4ORF" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}camlp4prof", so it can be a program name with args. set dummy ${ac_tool_prefix}camlp4prof; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CAMLP4PROF+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CAMLP4PROF"; then ac_cv_prog_CAMLP4PROF="$CAMLP4PROF" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CAMLP4PROF="${ac_tool_prefix}camlp4prof" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CAMLP4PROF=$ac_cv_prog_CAMLP4PROF if test -n "$CAMLP4PROF"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CAMLP4PROF" >&5 $as_echo "$CAMLP4PROF" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CAMLP4PROF"; then ac_ct_CAMLP4PROF=$CAMLP4PROF # Extract the first word of "camlp4prof", so it can be a program name with args. set dummy camlp4prof; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CAMLP4PROF+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CAMLP4PROF"; then ac_cv_prog_ac_ct_CAMLP4PROF="$ac_ct_CAMLP4PROF" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CAMLP4PROF="camlp4prof" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CAMLP4PROF=$ac_cv_prog_ac_ct_CAMLP4PROF if test -n "$ac_ct_CAMLP4PROF"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CAMLP4PROF" >&5 $as_echo "$ac_ct_CAMLP4PROF" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CAMLP4PROF" = x; then CAMLP4PROF="no" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CAMLP4PROF=$ac_ct_CAMLP4PROF fi else CAMLP4PROF="$ac_cv_prog_CAMLP4PROF" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}camlp4r", so it can be a program name with args. set dummy ${ac_tool_prefix}camlp4r; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CAMLP4R+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CAMLP4R"; then ac_cv_prog_CAMLP4R="$CAMLP4R" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CAMLP4R="${ac_tool_prefix}camlp4r" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CAMLP4R=$ac_cv_prog_CAMLP4R if test -n "$CAMLP4R"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CAMLP4R" >&5 $as_echo "$CAMLP4R" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CAMLP4R"; then ac_ct_CAMLP4R=$CAMLP4R # Extract the first word of "camlp4r", so it can be a program name with args. set dummy camlp4r; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CAMLP4R+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CAMLP4R"; then ac_cv_prog_ac_ct_CAMLP4R="$ac_ct_CAMLP4R" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CAMLP4R="camlp4r" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CAMLP4R=$ac_cv_prog_ac_ct_CAMLP4R if test -n "$ac_ct_CAMLP4R"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CAMLP4R" >&5 $as_echo "$ac_ct_CAMLP4R" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CAMLP4R" = x; then CAMLP4R="no" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CAMLP4R=$ac_ct_CAMLP4R fi else CAMLP4R="$ac_cv_prog_CAMLP4R" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}camlp4rf", so it can be a program name with args. set dummy ${ac_tool_prefix}camlp4rf; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CAMLP4RF+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CAMLP4RF"; then ac_cv_prog_CAMLP4RF="$CAMLP4RF" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CAMLP4RF="${ac_tool_prefix}camlp4rf" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CAMLP4RF=$ac_cv_prog_CAMLP4RF if test -n "$CAMLP4RF"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CAMLP4RF" >&5 $as_echo "$CAMLP4RF" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CAMLP4RF"; then ac_ct_CAMLP4RF=$CAMLP4RF # Extract the first word of "camlp4rf", so it can be a program name with args. set dummy camlp4rf; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CAMLP4RF+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CAMLP4RF"; then ac_cv_prog_ac_ct_CAMLP4RF="$ac_ct_CAMLP4RF" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CAMLP4RF="camlp4rf" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CAMLP4RF=$ac_cv_prog_ac_ct_CAMLP4RF if test -n "$ac_ct_CAMLP4RF"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CAMLP4RF" >&5 $as_echo "$ac_ct_CAMLP4RF" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CAMLP4RF" = x; then CAMLP4RF="no" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CAMLP4RF=$ac_ct_CAMLP4RF fi else CAMLP4RF="$ac_cv_prog_CAMLP4RF" fi if test "$CAMLP4" = "no"; then as_fn_error $? "You must install the Camlp4 pre-processor. On some operating systems, these are separate packages from the main OCaml compiler, such as camlp4-extra on Debian." "$LINENO" 5 fi # Check whether --enable-version_check was given. if test "${enable_version_check+set}" = set; then : enableval=$enable_version_check; fi # Check that OCaml version is greater or equal to 3.12.1 for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AWK+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AWK="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 $as_echo "$AWK" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AWK" && break done if test "x${enable_version_check}" != "xno"; then : # Used to indicate true or false condition ax_compare_version=false # Convert the two version strings to be compared into a format that # allows a simple string comparison. The end result is that a version # string of the form 1.12.5-r617 will be converted to the form # 0001001200050617. In other words, each number is zero padded to four # digits, and non digits are removed. ax_compare_version_A=`echo "$OCAMLVERSION" | sed -e 's/\([0-9]*\)/Z\1Z/g' \ -e 's/Z\([0-9]\)Z/Z0\1Z/g' \ -e 's/Z\([0-9][0-9]\)Z/Z0\1Z/g' \ -e 's/Z\([0-9][0-9][0-9]\)Z/Z0\1Z/g' \ -e 's/[^0-9]//g'` ax_compare_version_B=`echo "3.12.1" | sed -e 's/\([0-9]*\)/Z\1Z/g' \ -e 's/Z\([0-9]\)Z/Z0\1Z/g' \ -e 's/Z\([0-9][0-9]\)Z/Z0\1Z/g' \ -e 's/Z\([0-9][0-9][0-9]\)Z/Z0\1Z/g' \ -e 's/[^0-9]//g'` ax_compare_version=`echo "x$ax_compare_version_A x$ax_compare_version_B" | sed 's/^ *//' | sort -r | sed "s/x${ax_compare_version_A}/false/;s/x${ax_compare_version_B}/true/;1q"` if test "$ax_compare_version" = "true" ; then as_fn_error $? "Your version of OCaml: $OCAMLVERSION is not supported" "$LINENO" 5 fi fi # Check whether --enable-certificate_check was given. if test "${enable_certificate_check+set}" = set; then : enableval=$enable_certificate_check; fi if test "x${enable_certificate_check}" = "xno"; then : curl_certificate_check=--insecure wget_certificate_check=--no-check-certificate fi for ac_prog in curl wget do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_FETCH+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$FETCH"; then ac_cv_prog_FETCH="$FETCH" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_FETCH="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi FETCH=$ac_cv_prog_FETCH if test -n "$FETCH"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $FETCH" >&5 $as_echo "$FETCH" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$FETCH" && break done test -n "$FETCH" || FETCH="no" if test x"$FETCH" = x"curl" ; then fetch="curl $curl_certificate_check -OL" elif test x"$FETCH" = x"wget" ; then fetch="wget $wget_certificate_check" else as_fn_error $? "You must have either curl or wget installed." "$LINENO" 5 fi ac_config_files="$ac_config_files Makefile.config src/core/opamVersion.ml doc/man-ext/opam-check.md" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' # Transform confdefs.h into DEFS. # Protect against shell expansion while executing Makefile rules. # Protect against Makefile macro expansion. # # If the first sed substitution is executed (which looks for macros that # take arguments), then branch to the quote section. Otherwise, # look for a macro that doesn't take arguments. ac_script=' :mline /\\$/{ N s,\\\n,, b mline } t clear :clear s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g t quote s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g t quote b any :quote s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g s/\[/\\&/g s/\]/\\&/g s/\$/$$/g H :any ${ g s/^\n// s/\n/ /g p } ' DEFS=`sed -n "$ac_script" confdefs.h` ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by opam $as_me 1.1.1, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE Configuration files: $config_files Report bugs to the package provider." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ opam config.status 1.1.1 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" Copyright (C) 2012 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' AWK='$AWK' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --he | --h | --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "Makefile.config") CONFIG_FILES="$CONFIG_FILES Makefile.config" ;; "src/core/opamVersion.ml") CONFIG_FILES="$CONFIG_FILES src/core/opamVersion.ml" ;; "doc/man-ext/opam-check.md") CONFIG_FILES="$CONFIG_FILES doc/man-ext/opam-check.md" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" eval set X " :F $CONFIG_FILES " shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi if test "$prefix" = "NONE"; then prefix=$ac_default_prefix fi bindir="`eval echo ${bindir}`" bindir="`eval echo ${bindir}`" mandir="`eval echo ${mandir}`" mandir="`eval echo ${mandir}`" echo echo Executables will be installed in ${bindir} echo Manual pages will be installed in ${mandir} opam-1.1.1/tests/0000755000175000017500000000000012272210733012053 5ustar i33173i33173opam-1.1.1/tests/Makefile0000644000175000017500000002074112272210733013517 0ustar i33173i33173TMP_DIR = $(realpath .)/tmp OPAM_ROOT = $(TMP_DIR)/OPAM.ROOT OPAM_REPO = $(TMP_DIR)/OPAM.REPO # repositoy name REPO = test REPOKIND ?= local # To test GIT repo OPAM_GIT = $(TMP_DIR)/OPAM.GIT PACKAGES = P1-1 P1-2 P2 P3 P4 P5 _OPAM = $(realpath ../_obuild/opam/opam.asm) ENV = PATH=$(PATH) $(DEBUG) OPAMKEEPBUILDDIR=1 OPAMROOT=$(OPAM_ROOT) OPAMYES=1 OPAM=$(_OPAM) OPAM = $(ENV) $(_OPAM) CHECK = $(ENV) $(realpath ../_obuild/opam-check/opam-check.asm) ifeq ($(OPAMTESTQUIET), 1) DEBUG = else DEBUG = OPAMDEBUG=2 OCAMLRUNPARAM=b endif ARCHIVES = $(PACKAGES:%=packages/%.tar.gz) .PHONY: all local git all: local git @ quiet: $(MAKE) OPAMTESTQUIET=1 all run: $(MAKE) init && \ $(MAKE) list && \ $(MAKE) upload && \ $(MAKE) install-remove && \ $(MAKE) list && \ $(MAKE) install-opt && \ $(MAKE) list && \ $(MAKE) install && \ $(MAKE) list && \ $(MAKE) reinstall && \ $(MAKE) list && \ $(MAKE) upload-new && \ $(MAKE) list && \ $(MAKE) upgrade && \ $(MAKE) list && \ $(MAKE) downgrade && \ $(MAKE) list && \ $(MAKE) switch-alias && \ $(MAKE) list && \ $(MAKE) switch-env-packages && \ $(MAKE) repo && \ $(MAKE) list @echo "SUCCESS!" local: $(MAKE) clean $(MAKE) REPOKIND=local run git: $(MAKE) clean $(MAKE) REPOKIND=git run init: rm -rf $(OPAM_REPO) mkdir -p $(OPAM_REPO) ifeq ($(REPOKIND), git) cd $(OPAM_REPO) && git init && \ touch README && git add README && \ git commit -a -m "Initial commit" endif $(OPAM) init --no-setup --no-base-packages $(REPO) $(OPAM_REPO) -k $(REPOKIND) upload: $(ARCHIVES) mkdir -p $(OPAM_REPO)/packages/P1.1 cp packages/P1-1.opam $(OPAM_REPO)/packages/P1.1/opam cp packages/P1-1/README $(OPAM_REPO)/packages/P1.1/descr mkdir -p $(OPAM_REPO)/packages/P2.1 cp packages/P2/README $(OPAM_REPO)/packages/P2.1/descr cp packages/P2.opam $(OPAM_REPO)/packages/P2.1/opam mkdir -p $(OPAM_REPO)/packages/P3.1~weird-version.test cp packages/P3.opam $(OPAM_REPO)/packages/P3.1~weird-version.test/opam cp packages/P3/README $(OPAM_REPO)/packages/P3.1~weird-version.test/descr mkdir -p $(OPAM_REPO)/packages/P4.1 cp packages/P4-1.opam $(OPAM_REPO)/packages/P4.1/opam cp packages/P4/README $(OPAM_REPO)/packages/P4.1/descr mkdir -p $(OPAM_REPO)/packages/P5.1 cp packages/P5.opam $(OPAM_REPO)/packages/P5.1/opam cp packages/P5/README $(OPAM_REPO)/packages/P5.1/descr mkdir -p $(OPAM_REPO)/compilers cp compilers/* $(OPAM_REPO)/compilers/ ifeq ($(REPOKIND), git) echo 'git: "$(OPAM_GIT)/P1-1"' > $(OPAM_REPO)/packages/P1.1/url cd $(OPAM_REPO)/packages/P1.1/ && git add * && git commit -a -m "Adding P1" echo 'git: "$(OPAM_GIT)/P2"' > $(OPAM_REPO)/packages/P2.1/url cd $(OPAM_REPO)/packages/P2.1/ && git add * && git commit -a -m "Adding P2" echo 'git: "$(OPAM_GIT)/P3"' > $(OPAM_REPO)/packages/P3.1~weird-version.test/url cd $(OPAM_REPO)/packages/P3.1~weird-version.test/ && git add * && git commit -a -m "Adding P3" echo 'git: "$(OPAM_GIT)/P4"' > $(OPAM_REPO)/packages/P4.1/url cd $(OPAM_REPO)/packages/P4.1/ && git add * && git commit -a -m "Adding P4" echo 'git: "$(OPAM_GIT)/P5"' > $(OPAM_REPO)/packages/P5.1/url cd $(OPAM_REPO)/packages/P5.1/ && git add * && git commit -a -m "Adding P5" cd $(OPAM_REPO)/compilers && git add * && git commit -a -m "Adding compilers" rm -rf $(OPAM_GIT) && mkdir -p $(OPAM_GIT) mkdir $(OPAM_GIT)/P1-1 && cp packages/P1-1/* $(OPAM_GIT)/P1-1/ mkdir $(OPAM_GIT)/P2 && cp packages/P2/* $(OPAM_GIT)/P2/ mkdir $(OPAM_GIT)/P3 && cp packages/P3/* $(OPAM_GIT)/P3/ mkdir $(OPAM_GIT)/P4 && cp packages/P4/* $(OPAM_GIT)/P4/ mkdir $(OPAM_GIT)/P5 && cp packages/P5/* $(OPAM_GIT)/P5/ cd $(OPAM_GIT)/P1-1 && git init && git add * && git commit -a -m "initial commit" cd $(OPAM_GIT)/P2 && git init && git add * && git commit -a -m "initial commit" cd $(OPAM_GIT)/P3 && git init && git add * && git commit -a -m "initial commit" cd $(OPAM_GIT)/P4 && git init && git add * && git commit -a -m "initial commit" cd $(OPAM_GIT)/P5 && git init && git add * && git commit -a -m "initial commit" else mkdir -p $(OPAM_REPO)/archives cp packages/P1-1.tar.gz $(OPAM_REPO)/archives/P1.1+opam.tar.gz cp packages/P2.tar.gz $(OPAM_REPO)/archives/P2.1+opam.tar.gz cp packages/P3.tar.gz $(OPAM_REPO)/archives/P3.1~weird-version.test+opam.tar.gz cp packages/P4.tar.gz $(OPAM_REPO)/archives/P4.1+opam.tar.gz cp packages/P5.tar.gz $(OPAM_REPO)/archives/P5.1+opam.tar.gz endif $(OPAM) update list: $(OPAM) list -a install-remove: $(CHECK) -l install-remove-1 $(OPAM) install P1 $(CHECK) -l install-remove-2 P1.1 $(OPAM) remove P1 $(CHECK) -l install-remove-3 install-opt: $(CHECK) -l install-opt-1 $(OPAM) install P5 test -f $(OPAM_ROOT)/system/lib/p5/p2_absent $(CHECK) -l install-opt-2 P1.1 P5.1 $(OPAM) remove P5 $(CHECK) -l install-opt-3 P1.1 $(OPAM) install P5 $(CHECK) -l install-opt-4 P1.1 P5.1 $(OPAM) remove P5 -a $(CHECK) -l install-opt-5 $(OPAM) install P5 $(CHECK) -l install-opt-6 P1.1 P5.1 $(OPAM) install P2 test -f $(OPAM_ROOT)/system/lib/p5/p2_present $(CHECK) -l install-opt-7 P1.1 P2.1 P5.1 $(OPAM) remove P5 -a $(CHECK) -l install-opt-8 P1.1 P2.1 $(OPAM) remove P2 -a $(CHECK) -l install-opt-9 $(OPAM) install P1 P2 P5 test -f $(OPAM_ROOT)/system/lib/p5/p2_present $(CHECK) -l install-opt-10 P1.1 P2.1 P5.1 $(OPAM) remove P2 -a test -f $(OPAM_ROOT)/system/lib/p5/p2_absent $(CHECK) -l install-opt-11 P1.1 P5.1 $(OPAM) remove P1 $(CHECK) -l install-opt-12 install: $(CHECK) -l install-1 $(OPAM) install P1 $(CHECK) -l install-2 P1.1 $(OPAM) install P2 $(CHECK) -l install-3 P1.1 P2.1 $(OPAM) install P3 $(CHECK) -l install-4 P1.1 P2.1 P3.1~weird-version.test $(OPAM) install P4 $(CHECK) -l install-5 P1.1 P2.1 P3.1~weird-version.test P4.1 reinstall: $(CHECK) -l reinstall-1 P1.1 P2.1 P3.1~weird-version.test P4.1 $(OPAM) reinstall P1 $(CHECK) -l reinstall-2 P1.1 P2.1 P3.1~weird-version.test P4.1 upload-new: mkdir $(OPAM_REPO)/packages/P4.2 cp packages/P4-2.opam $(OPAM_REPO)/packages/P4.2/opam cp packages/P4/README $(OPAM_REPO)/packages/P4.2/descr mkdir $(OPAM_REPO)/packages/P4.3 cp packages/P4-3.opam $(OPAM_REPO)/packages/P4.3/opam cp packages/P4/README $(OPAM_REPO)/packages/P4.3/descr ifeq ($(REPOKIND), git) echo "(* new line *)" >> $(OPAM_GIT)/P1-1/p1.ml cd $(OPAM_GIT)/P1-1 && git commit -a -m "a small change" echo 'git: "$(OPAM_GIT)/P4"' > $(OPAM_REPO)/packages/P4.2/url echo 'git: "$(OPAM_GIT)/P4"' > $(OPAM_REPO)/packages/P4.3/url cd $(OPAM_REPO) && git add * && git commit -a -m "Adding P4.2 and P4.3" else mkdir $(OPAM_REPO)/packages/P1.2 cp packages/P1-2.opam $(OPAM_REPO)/packages/P1.2/opam cp packages/P1-2/README $(OPAM_REPO)/packages/P1.2/descr cp packages/P1-2.tar.gz $(OPAM_REPO)/archives/P1.2+opam.tar.gz cp packages/P4.tar.gz $(OPAM_REPO)/archives/P4.2+opam.tar.gz cp packages/P4.tar.gz $(OPAM_REPO)/archives/P4.3+opam.tar.gz endif $(OPAM) update upgrade: $(CHECK) -l upgrade-1 P1.1 P2.1 P3.1~weird-version.test P4.1 $(OPAM) upgrade ifeq ($(REPOKIND), git) $(CHECK) -l upgrade-2 P1.1 P2.1 P3.1~weird-version.test P4.3 else $(CHECK) -l upgrade-2 P1.2 P2.1 P3.1~weird-version.test P4.3 endif downgrade: ifeq ($(REPOKIND), git) $(CHECK) -l downgrade-1 P1.1 P2.1 P3.1~weird-version.test P4.3 else $(CHECK) -l downgrade-1 P1.2 P2.1 P3.1~weird-version.test P4.3 endif $(OPAM) install P4.2 $(CHECK) -l downgrade-2 P1.1 P2.1 P3.1~weird-version.test P4.2 switch-alias: $(CHECK) -l switch-alias-1 P1.1 P2.1 P3.1~weird-version.test P4.2 $(OPAM) remove P3.1~weird-version.test P4.2 $(CHECK) -l switch-alias-2 P1.1 P2.1 $(OPAM) switch export -f $(TMP_DIR)/export $(OPAM) switch install test --alias-of system --no-base-packages $(CHECK) -l switch-alias-3 $(OPAM) switch import -f $(TMP_DIR)/export $(CHECK) -l switch-alias-4 P1.1 P2.1 $(OPAM) switch install test2 --alias-of 20 $(CHECK) -l switch-alias-5 $(OPAM) install P1 $(CHECK) -l switch-alias-6 P1.1 $(OPAM) switch system $(CHECK) -l switch-alias-7 P1.1 P2.1 $(OPAM) switch remove test test2 switch-env-packages: $(CHECK) -l switch-env-packages-1 P1.1 P2.1 $(OPAM) switch 10+a+b ifeq ($(REPOKIND), git) $(CHECK) -l switch-env-packages-2 P1.1 P2.1 P3.1~weird-version.test P4.3 else $(CHECK) -l switch-env-packages-2 P1.2 P2.1 P3.1~weird-version.test P4.3 endif ./test-TEST.sh $(wildcard $(OPAM_ROOT)/10+a+b/build/P4.3/P4*.env) "1" repo: $(OPAM) repo add $(REPO)2 $(OPAM_REPO) -k $(REPOKIND) $(OPAM) repo remove $(REPO)2 $(OPAM) repo remove $(REPO) packages/%.tar.gz: packages/% cd packages && tar czf $*.tar.gz $* clean: rm -f $(ARCHIVES) rm -rf $(TMP_DIR) opam-1.1.1/tests/test-TEST.sh0000755000175000017500000000020312272210733014141 0ustar i33173i33173#!/bin/sh if [ -f $1 ]; then . $1 fi if [ x${TEST} != x$2 ]; then echo "Error: TEST=${TEST} instead of $2" exit 2 fi opam-1.1.1/tests/compilers/0000755000175000017500000000000012272210733014050 5ustar i33173i33173opam-1.1.1/tests/compilers/10+a+b.comp0000644000175000017500000000013512272210733015600 0ustar i33173i33173opam-version: "1" version: "10" preinstalled: true env: [ [ TEST="1" ] ] packages: [ "P4" ]opam-1.1.1/tests/compilers/20.comp0000644000175000017500000000011312272210733015144 0ustar i33173i33173opam-version: "1" version: "20" preinstalled: true env: [ [ TEST="1" ] ] opam-1.1.1/tests/README.unittest0000644000175000017500000000122012272210733014604 0ustar i33173i33173 # to create a new unit test * clean the test repository : ./init-repo.sh -c * init the test repository : ./init-repo.sh -i * load a inital scenario (this command can be invoked multiple times): ./init-repo.sh -s 1 ./init-repo.sh -s 2 * install/remove/upgrade : OPAM_ROOT=/tmp/OPAM.ROOT PATH=/tmp/OPAM.BIN:$PATH opam --yes --root /tmp/OPAM.ROOT install P4 * crearte a new expected result file in as OPAM_ROOT=/tmp/OPAM.ROOT PATH=/tmp/OPAM.BIN:$PATH \ opam --yes --root /tmp/OPAM.ROOT list > results/new-expected-result * Make sure that the result correct ! * Add a new test case in the file tests.py opam-1.1.1/tests/packages/0000755000175000017500000000000012272210733013631 5ustar i33173i33173opam-1.1.1/tests/packages/P4/0000755000175000017500000000000012272210733014114 5ustar i33173i33173opam-1.1.1/tests/packages/P4/README0000644000175000017500000000003312272210733014770 0ustar i33173i33173Testing transitive closure opam-1.1.1/tests/packages/P4/P4.install0000644000175000017500000000007112272210733015765 0ustar i33173i33173bin: [ "_build/p4.native" { "p4" } "_build/p4.native" ]opam-1.1.1/tests/packages/P4/build.sh0000755000175000017500000000044112272210733015551 0ustar i33173i33173#! /bin/sh -e echo "Building P4 with ${OPAM}" COMP0="`${OPAM} config -R asmcomp P2 P3`" LINK0="`${OPAM} config -R asmlink P2 P3`" COMP=$(echo ${COMP0} | sed -e 's| |,|g') LINK=$(echo ${LINK0} | sed -e 's| |,|g') ocamlbuild -cflags ${COMP} -lflags ${LINK} p4.native echo "TEST=${TEST}" opam-1.1.1/tests/packages/P4/p4.ml0000644000175000017500000000024412272210733014771 0ustar i33173i33173let f = try P3_bar.f (); P1.x () with _ -> P3.z () let () = let t = try Sys.getenv "TEST" with _ -> "" in Printf.printf "TEST=%s\n%!" t opam-1.1.1/tests/packages/P4/_tags0000644000175000017500000000007012272210733015131 0ustar i33173i33173<*.{byte,native}>: use_p2, use_p3 <*.ml>: use_p2, use_p3opam-1.1.1/tests/packages/P1-2/0000755000175000017500000000000012272210733014250 5ustar i33173i33173opam-1.1.1/tests/packages/P1-2/README0000644000175000017500000000002612272210733015126 0ustar i33173i33173A very useful package opam-1.1.1/tests/packages/P1-2/P1.install0000644000175000017500000000012012272210733016111 0ustar i33173i33173lib: [ "_build/p1.cma" "_build/p1.cmxa" "_build/p1.a" "_build/p1.cmi" ] opam-1.1.1/tests/packages/P1-2/P1.config.in0000644000175000017500000000036512272210733016330 0ustar i33173i33173opam-version: "1" library "p1" { asmcomp: [ "-I" "%{lib}%/P1" ] bytelink: [ "-I" "${lib}%/P1" ] asmlink: [ "-I" "%{lib}%/P1" "p1.cmxa" ] bytelink: [ "-I" "%{lib}%/P1" "p1.cma" ] LOCAL: "local" l: "L" } FOO: "foo" bar: trueopam-1.1.1/tests/packages/P1-2/build.sh0000755000175000017500000000005212272210733015703 0ustar i33173i33173#! /bin/sh -eu ocamlbuild p1.cma p1.cmxa opam-1.1.1/tests/packages/P1-2/p1.ml0000644000175000017500000000007112272210733015120 0ustar i33173i33173let x () = failwith "the new version is not very good" opam-1.1.1/tests/packages/P5/0000755000175000017500000000000012272210733014115 5ustar i33173i33173opam-1.1.1/tests/packages/P5/README0000644000175000017500000000003612272210733014774 0ustar i33173i33173Testing optional dependencies opam-1.1.1/tests/packages/P5/build.sh0000755000175000017500000000026612272210733015557 0ustar i33173i33173#! /bin/sh -eu FLAGS="`${OPAM} config includes P1`" echo "Bytecode Compilation" ocamlopt ${FLAGS} -a p5.ml -o p5.cmxa echo "Native Compilation" ocamlc ${FLAGS} -a p5.ml -o p5.cma opam-1.1.1/tests/packages/P5/p5.ml0000644000175000017500000000002512272210733014770 0ustar i33173i33173let g () = P1.x () opam-1.1.1/tests/packages/P4-2.opam0000644000175000017500000000023212272210733015126 0ustar i33173i33173opam-version: "1" name: "P4" version: "2" maintainer: "contact@ocamlpro.com" depends: [ "P1" { = "1" } "P2" "P3" ] build: [ "./build.sh" ] opam-1.1.1/tests/packages/P3.opam0000644000175000017500000000027612272210733014776 0ustar i33173i33173opam-version: "1" name: "P3" version: "1~weird-version.test" maintainer: "contact@ocamlpro.com" depends: [ "P1" ] substs: [ "P3.config" ] libraries: [ "p3" "p3_bar" ] build: [ "./build.sh" ]opam-1.1.1/tests/packages/P4-3.opam0000644000175000017500000000020212272210733015124 0ustar i33173i33173opam-version: "1" name: "P4" version: "3" maintainer: "contact@ocamlpro.com" depends: [ "P2" "P3" ] build: [ "./build.sh" ] opam-1.1.1/tests/packages/P1-2.opam0000644000175000017500000000026012272210733015124 0ustar i33173i33173opam-version: "1" name: "P1" version: "2" ocaml-version: [ < "20" ] maintainer: "contact@ocamlpro.com" substs: [ "P1.config" ] libraries: [ "p1" ] build: [ "./build.sh" ] opam-1.1.1/tests/packages/P5.opam0000644000175000017500000000054112272210733014773 0ustar i33173i33173(* API version *) opam-version: "1" name: "P5" version: "1" maintainer: "contact@ocamlpro.com" depends: [ "P1" ] depopts: [ "P2" ] build: [ [ "./build.sh" ] [ "mkdir" "-p" "%{lib}%/p5" ] [ "touch" "%{lib}%/p5/p2_present" ] {P2:installed} [ "touch" "%{lib}%/p5/p2_absent" ] {!P2:installed} ] remove: [ "rm" "-rf" "%{lib}/p5" ] opam-1.1.1/tests/packages/P3/0000755000175000017500000000000012272210733014113 5ustar i33173i33173opam-1.1.1/tests/packages/P3/README0000644000175000017500000000002612272210733014771 0ustar i33173i33173Testing version names opam-1.1.1/tests/packages/P3/P3.config.in0000644000175000017500000000057312272210733016176 0ustar i33173i33173library "p3" { asmcomp : ["-I" "%{lib}%/P3"] bytecomp: ["-I" "%{lib}%/P3"] asmlink : ["-I" "%{lib}%/P3" "p3.cmxa"] bytelink: ["-I" "%{lib}%/P3" "p3.cma"] requires: ["p1"] } library "p3_bar" { asmcomp : ["-I" "%{lib}%/P3"] asmlink : ["-I" "%{lib}%/P3" "p3_bar.cmxa"] bytecomp: ["-I" "%{lib}%/P3"] bytelink: ["-I" "%{lib}%/P3" "p3_bar.cma"] requires: [ "p3"] }opam-1.1.1/tests/packages/P3/p3_bar.ml0000644000175000017500000000007012272210733015610 0ustar i33173i33173let f () = Printf.printf "foo\n%!" let _ = P3.z () opam-1.1.1/tests/packages/P3/p3.ml0000644000175000017500000000004712272210733014770 0ustar i33173i33173let z () = try P1.x () with _ -> 0 opam-1.1.1/tests/packages/P3/build.sh0000755000175000017500000000027012272210733015550 0ustar i33173i33173#! /bin/sh -eu echo "Building P3 version ${OPAM_PACKAGE_VERSION}" if [ "x${OPAM_PACKAGE_NAME}" = "xP3" ]; then ocamlbuild p3.cma p3.cmxa p3_bar.cma p3_bar.cmxa else exit 1 fi opam-1.1.1/tests/packages/P3/P3.install0000644000175000017500000000030212272210733015760 0ustar i33173i33173lib: [ (* p3 *) "_build/p3.cma" "_build/p3.cmxa" "_build/p3.a" "_build/p3.cmi" (* p3_bar *) "_build/p3_bar.cma" "_build/p3_bar.cmxa" "_build/p3_bar.a" "_build/p3_bar.cmi" ] opam-1.1.1/tests/packages/P3/myocamlbuild.ml0000644000175000017500000000060512272210733017127 0ustar i33173i33173let deps = [ "P1" ] open Ocamlbuild_plugin let ocp_get pkg = Ocamlbuild_pack.My_unix.run_and_open (Printf.sprintf "%s config includes -R %s" (Unix.getenv "OPAM") (Filename.quote pkg)) input_line let add_dep p = flag ["ocaml"; "compile"] & S[Sh (ocp_get p)] let _ = dispatch & function | After_rules -> List.iter add_dep deps | _ -> () opam-1.1.1/tests/packages/P2.opam0000644000175000017500000000026712272210733014775 0ustar i33173i33173opam-version: "1" name: "P2" version: "1" maintainer: "contact@ocamlpro.com" substs: [ "config" "P2.config" ] depends: [ "P1" ] libraries: [ "p2" ] build: [ "./build.sh" ] opam-1.1.1/tests/packages/P1-1/0000755000175000017500000000000012272210733014247 5ustar i33173i33173opam-1.1.1/tests/packages/P1-1/README0000644000175000017500000000002612272210733015125 0ustar i33173i33173A very useful package opam-1.1.1/tests/packages/P1-1/P1.install0000644000175000017500000000031412272210733016115 0ustar i33173i33173lib: [ "_build/p1.cmi" "_build/p1.cma" "_build/p1.cmxa" "_build/p1.a" "?_build/this_file_will_not_exits_but_that's_ok" ] share: [ "build.sh" ] doc: [ "_build/p1.cmi" { "foo/bar/index.html" } ]opam-1.1.1/tests/packages/P1-1/P1.config.in0000644000175000017500000000036512272210733016327 0ustar i33173i33173opam-version: "1" library "p1" { asmcomp: [ "-I" "%{lib}%/P1" ] bytelink: [ "-I" "%{lib}%/P1" ] asmlink: [ "-I" "%{lib}%/P1" "p1.cmxa" ] bytelink: [ "-I" "%{lib}%/P1" "p1.cma" ] LOCAL: "local" l: "L" } FOO: "foo" bar: trueopam-1.1.1/tests/packages/P1-1/build.sh0000755000175000017500000000005212272210733015702 0ustar i33173i33173#! /bin/sh -eu ocamlbuild p1.cma p1.cmxa opam-1.1.1/tests/packages/P1-1/p1.ml0000644000175000017500000000005512272210733015121 0ustar i33173i33173let x () = try Random.int 10 with _ -> 0 opam-1.1.1/tests/packages/P2/0000755000175000017500000000000012272210733014112 5ustar i33173i33173opam-1.1.1/tests/packages/P2/config.in0000644000175000017500000000012612272210733015706 0ustar i33173i33173Foo is %{P1:FOO}% Foo also contains a section with %{P1.p1:l}%. Funny, isn't it? opam-1.1.1/tests/packages/P2/README0000644000175000017500000000023112272210733014766 0ustar i33173i33173An other very useful package The description can go on multiple lines. The first line is the package synopsis, and the rest is the package description. opam-1.1.1/tests/packages/P2/p2.ml0000644000175000017500000000002512272210733014762 0ustar i33173i33173let g () = P1.x () opam-1.1.1/tests/packages/P2/P2.install0000644000175000017500000000006412272210733015763 0ustar i33173i33173lib: [ "p2.cma" "p2.cmxa" "p2.a" "p2.cmi" ] opam-1.1.1/tests/packages/P2/build.sh0000755000175000017500000000026612272210733015554 0ustar i33173i33173#! /bin/sh -eu FLAGS="`${OPAM} config includes P1`" echo "Bytecode Compilation" ocamlopt ${FLAGS} -a p2.ml -o p2.cmxa echo "Native Compilation" ocamlc ${FLAGS} -a p2.ml -o p2.cma opam-1.1.1/tests/packages/P2/P2.config.in0000644000175000017500000000026712272210733016174 0ustar i33173i33173library "p2" { asmcomp: ["-I" "%{lib}%/P2"] bytecomp: ["-I" "%{lib}%/P2"] asmlink: ["-I" "%{lib}%/P2" "p2.cmxa"] bytelink: ["-I" "%{lib}%/P2" "p2.cma"] requires: ["p1"] } opam-1.1.1/tests/packages/P1-1.opam0000644000175000017500000000203312272210733015123 0ustar i33173i33173(* API version *) opam-version: "1" name: "P1" # Test # Toto (* Version are arbitrary strings *) version: "1" maintainer: "contact@ocamlpro.com" (* The command to run *) build: [ [ "./build.sh" ] # HAHAH [ "this" "should" "never" "run" ] { ocaml-version > "100" } [ make "this" ocaml-version "also" ] { os = "NO" } [ "echo" "HAHA!" ] { ocaml-version = "10" } [ "echo" make share ocaml-version ] [ "this as well" { os = "myOS" } ] ] os: [ !"NO" | ( !"NO" & !"YES") ] ocaml-version: [ ="system" | ="20" | ="10" ] (* List of files to substitute env variables *) substs: [ "P1.config" ] (* Libraries *) libraries: [ "p1" ] (* External dependencies *) depexts: [ [ ["debian" "amd64"] ["foo" "bar"] ] [ ["osx" ] ["foobar"] ] ] messages: [ "I'll always bother you displaying this message" ] post-messages: [ "Thanks SO MUCH for installing this humble package" "Everything went well" {success} "Nooo, something went wrong, this makes me feel sooo sad..." {failure} ] bug-reports: "TEST.com"opam-1.1.1/tests/packages/P4-1.opam0000644000175000017500000000020212272210733015122 0ustar i33173i33173opam-version: "1" name: "P4" version: "1" maintainer: "contact@ocamlpro.com" depends: [ "P2" "P3" ] build: [ "./build.sh" ] opam-1.1.1/tests/results/0000755000175000017500000000000012272210733013554 5ustar i33173i33173opam-1.1.1/tests/results/install-P10000644000175000017500000000031112272210733015416 0ustar i33173i33173Available packages for system: P1 1 A very useful package P2 -- An other very useful package P3 -- Testing version names P4 -- Testing transitive closure P5 -- Testing optional dependencies opam-1.1.1/tests/results/install-upgrade-P20000644000175000017500000000044312272210733017052 0ustar i33173i33173Available packages for system: P1 1 A very useful package P2 1 An other very useful package P3 1~weird-version.test Testing version names P4 1 Testing transitive closure P5 -- Testing optional dependencies opam-1.1.1/tests/results/README.tests0000644000175000017500000000115212272210733015574 0ustar i33173i33173 # All tests are performed in a clean repository Initial state of the repository Available packages for system: P1 -- A very useful package P2 -- An other very useful package P3 -- Testing version names P4 -- Testing transitive closure P5 -- Testing optional dependencies * install-P1 install P1 * install-P1-P2-P3-P4 install P1, P2, P3, P4 * install-remove-P1 install P1 and then remove P1 * install-upgrade-P2 install P4 and then upgrade P2 * reinstall-P2 install P2 and the re-install P2 * install_opt install P5 , install P2, remove P5, remove P2, remove P1 opam-1.1.1/tests/results/install-opt0000644000175000017500000000031112272210733015740 0ustar i33173i33173Available packages for system: P1 -- A very useful package P2 -- An other very useful package P3 -- Testing version names P4 -- Testing transitive closure P5 -- Testing optional dependencies opam-1.1.1/tests/results/reinstall-P20000644000175000017500000000031112272210733015746 0ustar i33173i33173Available packages for system: P1 1 A very useful package P2 1 An other very useful package P3 -- Testing version names P4 -- Testing transitive closure P5 -- Testing optional dependencies opam-1.1.1/tests/results/install-remove-P10000644000175000017500000000031112272210733016711 0ustar i33173i33173Available packages for system: P1 -- A very useful package P2 -- An other very useful package P3 -- Testing version names P4 -- Testing transitive closure P5 -- Testing optional dependencies opam-1.1.1/tests/results/install-P1-P2-P3-P40000644000175000017500000000044312272210733016444 0ustar i33173i33173Available packages for system: P1 1 A very useful package P2 1 An other very useful package P3 1~weird-version.test Testing version names P4 1 Testing transitive closure P5 -- Testing optional dependencies opam-1.1.1/tests/tests.py0000755000175000017500000001035612272210733013577 0ustar i33173i33173#!/usr/bin/python import unittest from subprocess import Popen, STDOUT, PIPE from subprocess import call import uuid import os,sys,time import argparse import difflib tmpdir = "/tmp/OPAM.UNITTEST" results = "results" opamcmd = "/tmp/OPAM.BIN/opam --yes --root /tmp/OPAM.ROOT" verbose=0 FNULL=open(os.devnull, "w") def diff(fromfile,tofile,verbose=0): fromdate = time.ctime(os.stat(fromfile).st_mtime) todate = time.ctime(os.stat(tofile).st_mtime) fromlines = open(fromfile, 'U').readlines() tolines = open(tofile, 'U').readlines() diff = difflib.unified_diff(fromlines, tolines, fromfile, tofile)#, fromdate, todate) l = list(diff) if l : print "File Differences : " print ''.join(l) return False else : return True def opam(cmd, diffile=None,verbose=0): # first we exectute the action, then # we compare the output of list with # the diffile env = os.environ.copy() env['PATH'] = ':'.join(['/tmp/OPAM.BIN',env['PATH']]) env['OPAM_ROOT'] = '/tmp/OPAM.ROOT' cmd = opamcmd.split() + cmd if verbose > 1 : print "Env\nPATH=%s\nOPAM_ROOT=%s" % (env['PATH'],env['OPAM_ROOT']) print "CMD=%s" % (' '.join(cmd)) if verbose <= 1 : call(cmd, stdout=FNULL, env=env) else : call(cmd, env=env) if diffile : f = "%s/%s.opamtest" % (tmpdir,uuid.uuid1()) output = open(f,'w') call(opamcmd.split() + ["list"], stdout=output, env=env) output.close() d = diff(f,diffile,verbose) os.remove(f) return d return None def load_scenario(scenario,verbose=0): if verbose > 0 : print "Loading scenario %d" % scenario if verbose <= 1 : call(["./init-repo.sh", "-s", str(scenario)],stdout=FNULL) else : call(["./init-repo.sh", "-s", str(scenario)]) class OpamTests(unittest.TestCase): def setUp(self): if verbose > 0 : print "\nsetting up repository" call(["./init-repo.sh", "-i"], stdout=FNULL) if not os.path.exists(tmpdir): os.makedirs(tmpdir) def tearDown(self): if verbose > 0 : print "tearing down repository" call(["./init-repo.sh", "-c"], stdout=FNULL) def test_install(self): load_scenario(1,verbose) diffile="%s/install-P1" % results d = opam(["install", "P1"],diffile,verbose) self.assertTrue(d) def test_install_many(self): load_scenario(1,verbose) diffile="%s/install-P1-P2-P3-P4" % results opam(["install", "P1"]) opam(["install", "P2"]) opam(["install", "P3"]) d = opam(["install", "P4"], diffile,verbose) self.assertTrue(d) def test_remove(self): load_scenario(1,verbose) diffile="%s/install-remove-P1" % results opam(["install", "P1"]) d = opam(["remove", "P1"],diffile,verbose) self.assertTrue(d) def test_upgrade(self): load_scenario(1,verbose) diffile="%s/install-upgrade-P2" % results opam(["install", "P4"]) d = opam(["upgrade", "P2"],diffile,verbose) self.assertTrue(d) # @unittest.skip("skipping") def test_reinstall(self): load_scenario(1,verbose) diffile="%s/reinstall-P2" % results opam(["install", "P2"]) d = opam(["reinstall", "P2"],diffile,verbose) self.assertTrue(d) def test_install_opt(self): load_scenario(1,verbose) load_scenario(2,verbose) diffile="%s/install-opt" % results opam(["install", "P5"]) opam(["install", "P2"]) opam(["remove", "P5"]) opam(["remove", "P2"]) d = opam(["remove", "P1"],diffile,verbose) self.assertTrue(d) def main(): global verbose parser = argparse.ArgumentParser(description='description of you program') parser.add_argument('-v', '--verbose', action='store_true') parser.add_argument('-d', '--debug', action='store_true') args = parser.parse_args() verbosity=0 if args.verbose == True : verbose = 1 verbosity=2 if args.debug == True : verbose = 2 suite = unittest.TestLoader().loadTestsFromTestCase(OpamTests) unittest.TextTestRunner(verbosity=verbosity).run(suite) if __name__ == '__main__': main() opam-1.1.1/tests/init-repo.sh0000755000175000017500000000461712272210733014330 0ustar i33173i33173#! /bin/sh TEST_DIR=/tmp OPAM_ROOT=$TEST_DIR/OPAM.ROOT OPAM_REPO=$TEST_DIR/OPAM.REPO BIN=$TEST_DIR/OPAM.BIN REPO=test BINARIES=opam # opam in the path should not be a requirement ENV="OCAMLRUNPARAM=b OPAMDEBUG=2 OPAM_ROOT=$OPAM_ROOT PATH=$BIN:$PATH" ENV="OCAMLRUNPARAM=b OPAM_ROOT=$OPAM_ROOT PATH=$BIN:$PATH" OPAM="$ENV opam --yes --root $OPAM_ROOT" function binaries() { mkdir -p $BIN for bin in $BINARIES; do \ cp ../_obuild/$bin/$bin.asm $BIN/$bin ; \ done } function opam_clean() { rm -rf $ARCHIVES rm -rf $OPAM_ROOT $BIN rm -rf $OPAM_REPO } function opam_init() { mkdir -p $OPAM_REPO binaries eval $OPAM init -no-base-packages $REPO $OPAM_REPO -kind rsync } function opam_upload_stage1() { cd packages eval $OPAM upload -opam P1-1.opam -descr P1-1/README -archive P1-1.tar.gz -repo $REPO eval $OPAM upload -opam P2.opam -descr P2/README -archive P2.tar.gz -repo $REPO eval $OPAM upload -opam P3.opam -descr P3/README -archive P3.tar.gz -repo $REPO eval $OPAM upload -opam P4-1.opam -descr P4/README -archive P4.tar.gz -repo $REPO eval $OPAM upload -opam P5.opam -descr P5/README -archive P5.tar.gz -repo $REPO cd - cp compilers/* $OPAM_REPO/compilers/ # update the list of available packages with the one being updated eval $OPAM update } function opam_upload_stage2() { cd packages eval $OPAM upload -opam P1-2.opam -descr P1-2/README -archive P1-2.tar.gz -repo $REPO eval $OPAM upload -opam P4-2.opam -descr P4/README -archive P4.tar.gz -repo $REPO eval $OPAM upload -opam P4-3.opam -descr P4/README -archive P4.tar.gz -repo $REPO cd - # update the list of available packages with the one being updated eval $OPAM update } function usage() { DESCRIPTION="Opam unittest init functions" cat << EOF usage: $0 options $DESCRIPTION OPTIONS: -h Show this message -v Verbose -d Debug -i Init -c Clean EOF } VERBOSE= DEBUG= INIT= CLEAN= STAGE= while getopts "vhdcis:" flag do case "$flag" in d) set -x ; DEBUG=true;; v) VERBOSE=true ;; i) INIT=true ;; s) STAGE=$OPTARG ;; c) CLEAN=true ;; h) usage ; exit 0 ;; esac # echo "$flag" $OPTIND $OPTARG done if [ -n "$INIT" ]; then opam_clean opam_init fi if [ -n "$STAGE" ]; then if [ $STAGE = "1" ]; then opam_upload_stage1 fi if [ $STAGE = "2" ]; then opam_upload_stage2 fi fi if [ -n "$CLEAN" ]; then opam_clean fi exit 0 opam-1.1.1/LICENSE0000644000175000017500000012530512272210733011724 0ustar i33173i33173As 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 Library General Public License. By "a publicly distributed version of the Library", we mean either the unmodified Library as distributed by the copyright holder, or a modified version of the Library that is distributed under the conditions defined in clause 3 of the GNU Library 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. 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. ------------------------------------------------------------------------ GNU 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. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU 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 Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read .