├── src ├── test_gtk │ ├── test.mli │ └── dune ├── tests │ ├── data │ │ ├── test-gui │ │ ├── Short │ │ ├── rpm │ │ │ ├── Packages │ │ │ └── rpm │ │ ├── test-echo.1 │ │ ├── dpkg │ │ │ ├── pkgcache.bin │ │ │ ├── dpkg-query │ │ │ └── apt-cache │ │ ├── bug-reply │ │ ├── macports │ │ │ ├── registry.db │ │ │ └── port │ │ ├── runnable │ │ │ ├── script │ │ │ ├── go.sh │ │ │ ├── runner │ │ │ ├── Runner.xml │ │ │ ├── RunExec.xml │ │ │ ├── RecursiveRunner.xml │ │ │ ├── Runnable.xml │ │ │ └── ArgList.xml │ │ ├── slack │ │ │ └── packages │ │ │ │ ├── infozip-5.52-i486-2 │ │ │ │ └── man-pages-3.15-noarch-1 │ │ ├── HelloWorldMain │ │ ├── gentoo │ │ │ ├── sys-apps │ │ │ │ └── portage-2.1.7.16 │ │ │ │ │ ├── PF │ │ │ │ │ └── CHOST │ │ │ ├── sys-kernel │ │ │ │ ├── gentoo-sources-2.6.32 │ │ │ │ │ ├── PF │ │ │ │ │ └── CHOST │ │ │ │ └── gentoo-sources-2.6.30-r4 │ │ │ │ │ ├── CHOST │ │ │ │ │ └── PF │ │ │ └── app-emulation │ │ │ │ └── emul-linux-x86-baselibs-20100220 │ │ │ │ ├── CHOST │ │ │ │ └── PF │ │ ├── v2-alias │ │ ├── HelloSym.tgz │ │ ├── HelloWorld.dmg │ │ ├── HelloWorld.tgz │ │ ├── HelloWorld.zip │ │ ├── hello-0.1.gem │ │ ├── unicode.tar.gz │ │ ├── dummy_1-1_all.deb │ │ ├── recipe-base.tgz │ │ ├── HelloWorld.tar.bz2 │ │ ├── HelloWorld.tar.lzma │ │ ├── HelloWorld.autopackage │ │ ├── dummy-1-1.noarch.rpm │ │ ├── ports │ │ │ └── zeroinstall-injector-0.41_2 │ │ │ │ └── +CONTENTS │ │ ├── v1-alias │ │ ├── Compiler-new.xml │ │ ├── Replaced.xml │ │ ├── prog.xml │ │ ├── dbus.conf │ │ ├── Foo.xml │ │ ├── command-dep.xml │ │ ├── foo-empty.xml │ │ ├── HelloSingleFile.xml │ │ ├── Local2.xml │ │ ├── Native.xml │ │ ├── foo-new.xml │ │ ├── MultiArchLib.xml │ │ ├── Autopackage.xml │ │ ├── RecipeSingleFile.xml │ │ ├── search-firefox.xml │ │ ├── HelloExtractToNewDest.xml │ │ ├── RecipeExtractToNewDest.xml │ │ ├── RecipeSymlink.xml │ │ ├── selections.xml │ │ ├── RecipeRemove.xml │ │ ├── RecipeRemoveDir.xml │ │ ├── arch │ │ │ └── local │ │ │ │ ├── python2-2.7.2-4 │ │ │ │ └── desc │ │ │ │ └── zeroinstall-injector-1.5-1 │ │ │ │ └── desc │ │ ├── MultiArch.xml │ │ ├── Recipe.xml │ │ ├── RecipeRenameToNewDest.xml │ │ ├── Recursive.xml │ │ ├── ranking-cpu.xml │ │ ├── source-sel.xml │ │ ├── Hello │ │ ├── Hello.xml │ │ ├── Build.xml │ │ ├── Hello-new.xml │ │ ├── Hello-bad-digest.xml │ │ ├── RecipeRename.xml │ │ ├── Hello-wrong-size │ │ ├── Local.xml │ │ ├── RecipeExtractToExistingDest.xml │ │ ├── test_selections.xml │ │ ├── test_selections_win.xml │ │ ├── package-selection.xml │ │ ├── Hello-impossible.xml │ │ ├── Binary.xml │ │ ├── Binary2.xml │ │ ├── ReplacedConflicts.xml │ │ ├── Conflicts.xml │ │ ├── Versions.xml │ │ ├── Compiler.xml │ │ ├── Compiler2.xml │ │ ├── Command.xml │ │ ├── LocalArchive.xml │ │ ├── 6FCF121BE2390E0B.gpg │ │ ├── Source-missing-req.xml │ │ ├── ranking.xml │ │ ├── Source.xml │ │ └── old-selections.xml │ ├── server.mli │ ├── dune │ ├── fake_gpg_agent.mli │ └── fake_distro.ml ├── solver │ ├── tests │ │ ├── test.mli │ │ └── dune │ ├── dune │ └── zeroinstall_solver.ml ├── .gitignore ├── windows │ ├── 0install.exe.rc │ ├── 0install.exe.manifest │ ├── zeroinstall_windows.ml │ └── dune ├── cli │ ├── dune │ ├── completion.mli │ ├── main.mli │ ├── manage_cache.ml │ ├── alias.ml │ ├── select.ml │ ├── download.ml │ ├── destroy.ml │ ├── desktop.ml │ ├── cli.mli │ ├── runenv_shared.ml │ ├── list_ifaces.ml │ ├── list_feeds.ml │ ├── secureadd.ml │ ├── import.ml │ ├── remove_feed.ml │ ├── run.ml │ ├── command_tree.mli │ ├── add.ml │ └── show.ml ├── support │ ├── windows_api.disabled.ml │ ├── base64.mli │ ├── windows_api.mli │ ├── env.mli │ ├── stream.mli │ ├── dune │ ├── urlparse.mli │ ├── system.mli │ ├── hash.mli │ ├── windows_api.enabled.ml │ ├── env.ml │ ├── basedir.mli │ ├── base64.ml │ ├── stream.ml │ ├── safe_exn.ml │ ├── locale.mli │ ├── gpg.mli │ ├── safe_exn.mli │ ├── utils.c │ ├── logging.mli │ ├── xString.mli │ └── xString.ml ├── zeroinstall │ ├── about.ml │ ├── tree.mli │ ├── compiled.mli │ ├── justify.mli │ ├── stability.mli │ ├── command.mli │ ├── default_ui.mli │ ├── host_python.mli │ ├── dune │ ├── requirements.mli │ ├── key_info_provider.mli │ ├── mirror.mli │ ├── exec.mli │ ├── feed_import.mli │ ├── default_ui.ml │ ├── feed_import.ml │ ├── feed_provider.mli │ ├── stability.ml │ ├── feed_url.mli │ ├── feed_metadata.mli │ ├── sigs.mli │ ├── packagekit_stubs.mli │ ├── archive.mli │ ├── distro_cache.mli │ ├── recipe.mli │ ├── http.mli │ ├── impl_provider.mli │ ├── fetch.mli │ ├── ui.mli │ ├── general.ml │ ├── constants.ml │ ├── progress.mli │ ├── feed.mli │ ├── version.mli │ ├── scope_filter.ml │ ├── packagekit.mli │ ├── feed_url.ml │ ├── scope_filter.mli │ ├── distro_impls.mli │ ├── arch.mli │ ├── stores.mli │ ├── json_connection.mli │ ├── feed_cache.mli │ ├── dbus.with.ml │ ├── solver.mli │ └── apps.mli ├── gui_gtk │ ├── gui_gtk.mli │ ├── dune │ ├── preferences_box.mli │ ├── trust_box.mli │ ├── unsorted_list.ml │ ├── alert_box.ml │ ├── limiter.ml │ ├── gtk_common.ml │ ├── unsorted_list.mli │ ├── tray_icon.ml │ └── help_box.ml ├── runenv.ml ├── Makefile ├── static_0install.ml ├── dune └── 0desktop.1 ├── static ├── .gitignore ├── Dockerfile-test-fedora-36 ├── README.md ├── Dockerfile-test-debian-11 ├── run-tests.sh └── Dockerfile ├── .dockerignore ├── dune-project ├── .gitignore ├── dune ├── share ├── 0install.net │ ├── unzstd │ ├── unxz │ └── unlzma ├── icons │ ├── 24x24 │ │ └── zeroinstall.png │ ├── 48x48 │ │ └── zeroinstall.png │ └── 128x128 │ │ └── zeroinstall.png ├── zsh │ └── site-functions │ │ ├── _0launch │ │ └── _0install ├── applications │ └── 0install.desktop ├── fish │ └── completions │ │ ├── 0launch.fish │ │ └── 0install.fish ├── bash-completion │ └── completions │ │ ├── 0install │ │ └── 0launch └── metainfo │ └── 0install.appdata.xml ├── 0compile.properties ├── binary-feed.xml.in ├── .travis.yml ├── appveyor.yml ├── 0install-gtk.opam ├── .github └── workflows │ └── mac.yml ├── .travis-extra-deps.sh ├── 0install-solver.opam ├── .travis-test-compile.sh ├── 0install.opam └── ZeroInstall.xml /src/test_gtk/test.mli: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/tests/data/test-gui: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/solver/tests/test.mli: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/tests/data/Short: -------------------------------------------------------------------------------- 1 | ! 2 | -------------------------------------------------------------------------------- /src/tests/data/rpm/Packages: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/tests/data/test-echo.1: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/tests/data/dpkg/pkgcache.bin: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /static/.gitignore: -------------------------------------------------------------------------------- 1 | dist.tgz 2 | -------------------------------------------------------------------------------- /src/.gitignore: -------------------------------------------------------------------------------- 1 | _build 2 | .merlin 3 | -------------------------------------------------------------------------------- /src/tests/data/bug-reply: -------------------------------------------------------------------------------- 1 | Thanks 2 | -------------------------------------------------------------------------------- /src/tests/data/macports/registry.db: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/tests/data/runnable/script: -------------------------------------------------------------------------------- 1 | A test script 2 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | dist 2 | static 3 | _build 4 | .git 5 | -------------------------------------------------------------------------------- /src/tests/data/slack/packages/infozip-5.52-i486-2: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/tests/data/slack/packages/man-pages-3.15-noarch-1: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/windows/0install.exe.rc: -------------------------------------------------------------------------------- 1 | 1 24 "0install.exe.manifest" 2 | -------------------------------------------------------------------------------- /src/tests/data/HelloWorldMain: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | echo Hello World 3 | -------------------------------------------------------------------------------- /src/tests/data/gentoo/sys-apps/portage-2.1.7.16/PF: -------------------------------------------------------------------------------- 1 | portage-2.1.7.16 2 | -------------------------------------------------------------------------------- /dune-project: -------------------------------------------------------------------------------- 1 | (lang dune 2.5) 2 | (name 0install) 3 | (formatting disabled) 4 | -------------------------------------------------------------------------------- /src/tests/data/gentoo/sys-apps/portage-2.1.7.16/CHOST: -------------------------------------------------------------------------------- 1 | x86_64-pc-linux-gnu 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | README.html 2 | /build/ 3 | /_build/ 4 | /dist 5 | /0install.install 6 | -------------------------------------------------------------------------------- /src/tests/data/gentoo/sys-kernel/gentoo-sources-2.6.32/PF: -------------------------------------------------------------------------------- 1 | gentoo-sources-2.6.32 2 | -------------------------------------------------------------------------------- /dune: -------------------------------------------------------------------------------- 1 | (install 2 | (package 0install) 3 | (section doc) 4 | (files COPYING)) 5 | -------------------------------------------------------------------------------- /src/tests/data/gentoo/sys-kernel/gentoo-sources-2.6.30-r4/CHOST: -------------------------------------------------------------------------------- 1 | i686-pc-linux-gnu 2 | -------------------------------------------------------------------------------- /src/tests/data/gentoo/sys-kernel/gentoo-sources-2.6.32/CHOST: -------------------------------------------------------------------------------- 1 | x86_64-pc-linux-gnu 2 | -------------------------------------------------------------------------------- /src/tests/data/gentoo/sys-kernel/gentoo-sources-2.6.30-r4/PF: -------------------------------------------------------------------------------- 1 | gentoo-sources-2.6.30-r4 2 | -------------------------------------------------------------------------------- /src/tests/data/runnable/go.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | "$PROG" var "$@" 3 | exec 0testprog path "$@" 4 | -------------------------------------------------------------------------------- /src/solver/dune: -------------------------------------------------------------------------------- 1 | (library 2 | (name zeroinstall_solver) 3 | (public_name 0install-solver)) 4 | -------------------------------------------------------------------------------- /src/tests/data/gentoo/app-emulation/emul-linux-x86-baselibs-20100220/CHOST: -------------------------------------------------------------------------------- 1 | x86_64-pc-linux-gnu 2 | -------------------------------------------------------------------------------- /src/tests/data/gentoo/app-emulation/emul-linux-x86-baselibs-20100220/PF: -------------------------------------------------------------------------------- 1 | emul-linux-x86-baselibs-20100220 2 | -------------------------------------------------------------------------------- /src/tests/data/v2-alias: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec 0launch --command 'run' 'http://example.com/alias2.xml' "$@" 3 | -------------------------------------------------------------------------------- /src/tests/data/HelloSym.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leonidas-from-XIV/0install/master/src/tests/data/HelloSym.tgz -------------------------------------------------------------------------------- /src/solver/tests/dune: -------------------------------------------------------------------------------- 1 | (test 2 | (name test) 3 | (package 0install-solver) 4 | (libraries ounit2 0install-solver)) 5 | -------------------------------------------------------------------------------- /src/tests/data/HelloWorld.dmg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leonidas-from-XIV/0install/master/src/tests/data/HelloWorld.dmg -------------------------------------------------------------------------------- /src/tests/data/HelloWorld.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leonidas-from-XIV/0install/master/src/tests/data/HelloWorld.tgz -------------------------------------------------------------------------------- /src/tests/data/HelloWorld.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leonidas-from-XIV/0install/master/src/tests/data/HelloWorld.zip -------------------------------------------------------------------------------- /src/tests/data/hello-0.1.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leonidas-from-XIV/0install/master/src/tests/data/hello-0.1.gem -------------------------------------------------------------------------------- /src/tests/data/unicode.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leonidas-from-XIV/0install/master/src/tests/data/unicode.tar.gz -------------------------------------------------------------------------------- /share/0install.net/unzstd: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec 0install run --command=decompress https://apps.0install.net/utils/zstd.xml "$@" 3 | -------------------------------------------------------------------------------- /src/tests/data/dummy_1-1_all.deb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leonidas-from-XIV/0install/master/src/tests/data/dummy_1-1_all.deb -------------------------------------------------------------------------------- /src/tests/data/recipe-base.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leonidas-from-XIV/0install/master/src/tests/data/recipe-base.tgz -------------------------------------------------------------------------------- /share/icons/24x24/zeroinstall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leonidas-from-XIV/0install/master/share/icons/24x24/zeroinstall.png -------------------------------------------------------------------------------- /share/icons/48x48/zeroinstall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leonidas-from-XIV/0install/master/share/icons/48x48/zeroinstall.png -------------------------------------------------------------------------------- /src/tests/data/HelloWorld.tar.bz2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leonidas-from-XIV/0install/master/src/tests/data/HelloWorld.tar.bz2 -------------------------------------------------------------------------------- /src/tests/data/HelloWorld.tar.lzma: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leonidas-from-XIV/0install/master/src/tests/data/HelloWorld.tar.lzma -------------------------------------------------------------------------------- /static/Dockerfile-test-fedora-36: -------------------------------------------------------------------------------- 1 | FROM fedora:36 2 | RUN dnf install -y unzip gpg ca-certificates gtk3 findutils bzip2 python3 3 | -------------------------------------------------------------------------------- /share/icons/128x128/zeroinstall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leonidas-from-XIV/0install/master/share/icons/128x128/zeroinstall.png -------------------------------------------------------------------------------- /src/tests/data/HelloWorld.autopackage: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leonidas-from-XIV/0install/master/src/tests/data/HelloWorld.autopackage -------------------------------------------------------------------------------- /src/tests/data/dummy-1-1.noarch.rpm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Leonidas-from-XIV/0install/master/src/tests/data/dummy-1-1.noarch.rpm -------------------------------------------------------------------------------- /src/solver/zeroinstall_solver.ml: -------------------------------------------------------------------------------- 1 | module Make = Solver_core.Make 2 | module Diagnostics = Diagnostics.Make 3 | module Sat = Sat 4 | module S = S 5 | -------------------------------------------------------------------------------- /src/tests/data/rpm/rpm: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | cat << EOF 3 | ksh 93u-28.2.2 i586 4 | yast2-update 2.15.23-21 i586 5 | yast2-mail 2.15.23-2 noarch 6 | poor=name 2 noarch 7 | EOF 8 | -------------------------------------------------------------------------------- /static/README.md: -------------------------------------------------------------------------------- 1 | To build portable static binaries, run `make static/dist.tgz` in the top-level directory. 2 | This uses Docker. Run `static-test` to test the results. 3 | -------------------------------------------------------------------------------- /0compile.properties: -------------------------------------------------------------------------------- 1 | [compile] 2 | download-base-url = 3 | version-modifier = 4 | interface = ZeroInstall.xml 5 | selections = 6 | metadir = 0install 7 | distdir = dist 8 | 9 | -------------------------------------------------------------------------------- /static/Dockerfile-test-debian-11: -------------------------------------------------------------------------------- 1 | FROM debian:11 2 | RUN apt-get update && apt-get install -y unzip gpg gpg-agent ca-certificates libgtk-3-0 bzip2 python3 --no-install-recommends 3 | -------------------------------------------------------------------------------- /src/cli/dune: -------------------------------------------------------------------------------- 1 | (library 2 | (name zeroinstall_cli) 3 | (modules_without_implementation options) 4 | (wrapped false) 5 | (libraries zeroinstall support yojson xmlm lwt lwt.unix)) 6 | -------------------------------------------------------------------------------- /src/tests/data/ports/zeroinstall-injector-0.41_2/+CONTENTS: -------------------------------------------------------------------------------- 1 | @comment PKG_FORMAT_REVISION:1.1 2 | @name zeroinstall-injector-0.41_2 3 | @comment ORIGIN:devel/zeroinstall-injector 4 | @cwd /usr/local 5 | -------------------------------------------------------------------------------- /src/support/windows_api.disabled.ml: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2019, Thomas Leonard 2 | See the README file for details, or visit http://0install.net. *) 3 | 4 | let v ~wow64:_ = failwith "Not a Windows build!" 5 | -------------------------------------------------------------------------------- /src/tests/data/v1-alias: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | if [ "$*" = "--versions" ]; then 3 | exec 0launch -gd 'http://example.com/alias1.xml' "$@" 4 | else 5 | exec 0launch 'http://example.com/alias1.xml' "$@" 6 | fi 7 | -------------------------------------------------------------------------------- /src/cli/completion.mli: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2013, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | val handle_complete : stdout:Format.formatter -> Zeroinstall.General.config -> string list -> unit 6 | -------------------------------------------------------------------------------- /share/0install.net/unxz: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . gettext.sh 3 | TEXTDOMAIN=zero-install 4 | export TEXTDOMAIN 5 | message="`eval_gettext \"An XZ decompressor is needed to extract this archive\"`" 6 | 7 | exec 0launch --message="$message" http://0install.net/2010/interfaces/xzdec.xml "$@" 8 | -------------------------------------------------------------------------------- /share/0install.net/unlzma: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . gettext.sh 3 | TEXTDOMAIN=zero-install 4 | export TEXTDOMAIN 5 | message="`eval_gettext \"An LZMA decompressor is needed to extract this archive\"`" 6 | 7 | exec 0launch --message="$message" http://0install.net/2008/interfaces/lzmadec.xml "$@" 8 | -------------------------------------------------------------------------------- /src/zeroinstall/about.ml: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2013, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** Information about this software *) 6 | 7 | let version = "2.18-post" 8 | 9 | let parsed_version = Version.parse version 10 | -------------------------------------------------------------------------------- /src/gui_gtk/gui_gtk.mli: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2013, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** A GTK GUI plugin. 6 | There is no public interface - the plugin registers itself with [Zeroinstall.Gui.register_plugin] when it is loaded. *) 7 | -------------------------------------------------------------------------------- /src/gui_gtk/dune: -------------------------------------------------------------------------------- 1 | (executable 2 | (name gui_gtk) 3 | (modes plugin) 4 | (libraries lablgtk3 lwt_glib zeroinstall support lwt lwt.unix lwt_react) 5 | (embed_in_plugin_libraries lablgtk3 lwt_glib)) 6 | 7 | (install 8 | (section lib) 9 | (package 0install-gtk) 10 | (files gui_gtk.cmxs)) 11 | -------------------------------------------------------------------------------- /src/tests/data/Compiler-new.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | Compiler-new 5 | Compiler-new 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/tests/data/Replaced.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Hello 4 | Hello 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/support/base64.mli: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2017, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** Base64 decoder. This is only used for GPG signatures - performance is not important. *) 6 | 7 | exception Invalid_char 8 | 9 | val str_decode : string -> string 10 | -------------------------------------------------------------------------------- /src/tests/data/prog.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | prog 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/tests/data/runnable/runner: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | if [ "$1" != "runner-arg" ]; then 3 | exit 1 4 | fi 5 | shift 6 | mydir="$1" 7 | if [ ! -f "$mydir/Runnable.xml" ]; then 8 | exit 1 9 | fi 10 | shift 11 | if [ "$1" != "arg-for-runner" ]; then 12 | exit 1 13 | fi 14 | shift 15 | script=$1 16 | shift 17 | echo Runner: script=`cat $script`: args=$@ 18 | -------------------------------------------------------------------------------- /src/tests/data/dpkg/dpkg-query: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | if [ "$4" = "python-bittorrent" ]; then 3 | echo "3.4.2-10ubuntu2 any install ok installed" 4 | elif [ "$4" = "libxcomposite-dev" ]; then 5 | echo "1:0.3.1-1 i386 install ok installed" 6 | elif [ "$4" = "openjdk-7-jre" ]; then 7 | echo "7~u3-2.1.1-3 amd64 install ok installed" 8 | else 9 | exit 1 10 | fi 11 | -------------------------------------------------------------------------------- /src/gui_gtk/preferences_box.mli: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2016, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** The global preferences dialog. *) 6 | 7 | open Zeroinstall 8 | 9 | val make : 10 | General.config -> 11 | Trust.trust_db -> 12 | recalculate:(unit -> unit) -> 13 | GWindow.window_skel * unit Lwt.t 14 | -------------------------------------------------------------------------------- /src/support/windows_api.mli: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2019, Thomas Leonard 2 | See the README file for details, or visit http://0install.net. *) 3 | 4 | val v : wow64:bool -> Common.windows_api 5 | (** [v ~wow] is an object for interacting with Windows. 6 | Raises an exception if the host system is not Windows. 7 | @param wow64 This is a 64-bit system - use [KEY_WOW64_32KEY], etc. *) 8 | -------------------------------------------------------------------------------- /src/tests/data/macports/port: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | if [ "$1 $2" = "echo installed" ]; then 3 | cat << EOF 4 | zeroinstall-injector @0.54_0 5 | EOF 6 | elif [ "$1 $2" = "-v installed" ]; then 7 | cat << EOF 8 | The following ports are currently installed: 9 | zeroinstall-injector @0.54_0 10 | zeroinstall-injector @1.0_0 (active) platform='darwin 10' archs='noarch' 11 | EOF 12 | fi 13 | -------------------------------------------------------------------------------- /src/cli/main.mli: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2013, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | open Support.Common 6 | 7 | (* This is the entry-point for the unit-tests; it avoids the exception handling. *) 8 | val main : stdout:Format.formatter -> system -> unit 9 | 10 | val start : system -> unit 11 | val start_if_not_windows : system -> unit 12 | -------------------------------------------------------------------------------- /share/zsh/site-functions/_0launch: -------------------------------------------------------------------------------- 1 | #compdef 0launch 2 | COMP_CWORD=$CURRENT "${words[1]}" _complete zsh "${words[@]}" |\ 3 | while read item 4 | do 5 | case "$item" in 6 | add\ *) compadd -V dontsort -- "${item/#add /}" ;; 7 | filter\ *) compadd -- "${item/#filter /}" ;; 8 | prefix\ *) compadd -S '' -- "${item/#prefix /}" ;; 9 | file) _files ;; 10 | "") ;; 11 | *) echo 1>&2 Bad reply $item ;; 12 | esac 13 | done 14 | -------------------------------------------------------------------------------- /src/runenv.ml: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2013, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (* The stand-alone 0install-runenv.exe (only used on Windows) *) 6 | 7 | module RealSystem = Support.System.RealSystem(Unix) 8 | 9 | let () = 10 | let system = new RealSystem.real_system in 11 | Support.Utils.handle_exceptions (Runenv_shared.runenv system) (Array.to_list Sys.argv) 12 | -------------------------------------------------------------------------------- /share/zsh/site-functions/_0install: -------------------------------------------------------------------------------- 1 | #compdef 0install 2 | COMP_CWORD=$CURRENT "${words[1]}" _complete zsh "${words[@]}" |\ 3 | while read item 4 | do 5 | case "$item" in 6 | add\ *) compadd -V dontsort -- "${item/#add /}" ;; 7 | filter\ *) compadd -- "${item/#filter /}" ;; 8 | prefix\ *) compadd -S '' -- "${item/#prefix /}" ;; 9 | file) _files ;; 10 | "") ;; 11 | *) echo 1>&2 Bad reply $item ;; 12 | esac 13 | done 14 | -------------------------------------------------------------------------------- /src/Makefile: -------------------------------------------------------------------------------- 1 | # Running make from this directory builds with the "dev" profile rather than the "release" one. 2 | # To build and run a custom command manually, use e.g.: 3 | # 4 | # dune exec 0install -- -help 5 | 6 | default: test 7 | 8 | all: 9 | make -C .. PROFILE=dev all 10 | 11 | test: 12 | make -C .. PROFILE=dev test 13 | 14 | doc: 15 | make -C .. PROFILE=dev doc 16 | 17 | clean: 18 | make -C .. PROFILE=dev clean 19 | -------------------------------------------------------------------------------- /src/tests/data/dbus.conf: -------------------------------------------------------------------------------- 1 | 3 | 4 | session 5 | unix:tmpdir=/unused 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/static_0install.ml: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2013, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** The main executable for static (native or bytecode) builds. 6 | Portable bytecode uses 0install.ml instead. *) 7 | 8 | (* Use the Unix module we're compiled with, rather than loading it dynamically. *) 9 | module RealSystem = Support.System.RealSystem(Unix) 10 | 11 | let () = Main.start new RealSystem.real_system 12 | -------------------------------------------------------------------------------- /src/tests/data/Foo.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | Foo 5 | Foo 6 | Foo 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/tests/data/command-dep.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | command-dep 4 | a command depending on a command 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/tests/data/foo-empty.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Foo 5 | Foo 6 | Foo (check non-ASCII chars úüû) 7 | 8 | 13 | -------------------------------------------------------------------------------- /src/tests/server.mli: -------------------------------------------------------------------------------- 1 | open Support.Common 2 | 3 | type response = 4 | [ `Serve 5 | | `ServeFile of filepath 6 | | `Chunked 7 | | `AcceptKey 8 | | `UnknownKey 9 | | `Redirect of string 10 | | `Unexpected 11 | | `Give404 ] 12 | 13 | val with_server : 14 | ?portable_base:bool -> 15 | (Zeroinstall.General.config * Fake_system.fake_system -> 16 | < expect : (string * response) list list -> unit; port : int; terminate : unit Lwt.t > -> 17 | unit) -> 18 | unit -> unit 19 | -------------------------------------------------------------------------------- /static/run-tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -eu 3 | cd /tmp 4 | tar xf /mnt/dist.tgz 5 | /tmp/dist/install.sh local 6 | /usr/local/bin/0install --version 7 | echo -n "Checking that GTK plugin loads... " 8 | env DISPLAY=:0 0install config -g 2>&1 | grep -q 'ml_gtk_init: initialization failed' 9 | echo OK 10 | echo "Checking installation of 0test..." 11 | 0install add 0test https://apps.0install.net/0install/0test.xml 12 | 0test --version | grep '0test (zero-install)' 13 | echo "All tests passed!" 14 | -------------------------------------------------------------------------------- /share/applications/0install.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Type=Application 3 | Version=1.0 4 | Name=0install 5 | GenericName=Installer 6 | GenericName[es]=Instalador 7 | GenericName[sv]=Installerare 8 | Comment=Run or manage Zero Install programs 9 | Comment[es]=Actualiza o quita programas de tu menú Aplicaciones 10 | Comment[sv]=Uppdatera eller ta bort Zero Install-program i menyn Program 11 | Exec=0desktop 12 | Icon=zeroinstall 13 | Terminal=false 14 | Categories=Utility;Settings;PackageManager;GTK; 15 | -------------------------------------------------------------------------------- /src/support/env.mli: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2013, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** Environment variables (generic support code) *) 6 | 7 | type t 8 | 9 | type name = string 10 | 11 | val empty : t 12 | val put : name -> string -> t -> t 13 | val get : name -> t -> string option 14 | val get_exn : name -> t -> string 15 | val unset : name -> t -> t 16 | 17 | val of_array : string array -> t 18 | val to_array : t -> string array 19 | -------------------------------------------------------------------------------- /src/tests/data/HelloSingleFile.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Recipe 4 | Recipe 5 | Recipe 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/tests/data/Local2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Echo 4 | Local feed, remote archive 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/tests/data/runnable/Runner.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Runner 4 | test runner 5 | 6 | 7 | 8 | 9 | runner-arg 10 | ${SELF} 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/test_gtk/dune: -------------------------------------------------------------------------------- 1 | (rule 2 | (targets 0install%{ext_exe}) 3 | (deps %{bin:0install}) 4 | (action (copy %{deps} %{targets}))) 5 | 6 | (rule 7 | (targets 0install-runenv%{ext_exe}) 8 | (deps %{bin:0install-runenv}) 9 | (action (copy %{deps} %{targets}))) 10 | 11 | (test 12 | (name test) 13 | (package 0install-gtk) 14 | (deps (alias ../../install) ; Build the GTK plugin if possible 15 | 0install%{ext_exe} 0install-runenv%{ext_exe}) 16 | (libraries ounit2 zeroinstall support str)) 17 | -------------------------------------------------------------------------------- /src/tests/data/Native.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Native 5 | Native 6 | 7 | 8 | 13 | -------------------------------------------------------------------------------- /src/tests/data/foo-new.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Foo 5 | Foo 6 | Foo (check non-ASCII chars úüû) 7 | 8 | 9 | 14 | -------------------------------------------------------------------------------- /src/tests/dune: -------------------------------------------------------------------------------- 1 | (rule 2 | (targets 0install%{ext_exe}) 3 | (deps %{bin:0install}) 4 | (action (copy %{deps} %{targets}))) 5 | 6 | (rule 7 | (targets 0install-runenv%{ext_exe}) 8 | (deps %{bin:0install-runenv}) 9 | (action (copy %{deps} %{targets}))) 10 | 11 | (test 12 | (name test) 13 | (package 0install) 14 | (deps (source_tree data) 15 | 0install%{ext_exe} 0install-runenv%{ext_exe}) 16 | (libraries ounit2 zeroinstall zeroinstall_cli 0install-solver support lwt lwt.unix lwt_react xmlm yojson)) 17 | -------------------------------------------------------------------------------- /src/zeroinstall/tree.mli: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2013, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** Getting the dependency tree from a selections document. *) 6 | 7 | module Make (Model : Sigs.SELECTIONS) : sig 8 | type node = 9 | Model.Role.t * [ 10 | | `Problem 11 | | `Selected of Model.impl * node list 12 | ] 13 | 14 | val as_tree : Model.t -> node 15 | end 16 | 17 | val print : General.config -> Format.formatter -> Selections.t -> unit 18 | -------------------------------------------------------------------------------- /src/cli/manage_cache.ml: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2013, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** The "0install store manage" command *) 6 | 7 | open Options 8 | 9 | let handle options flags args = 10 | Support.Argparse.iter_options flags (function 11 | | #common_option as o -> Common_options.process_common_option options o 12 | ); 13 | if args <> [] then raise (Support.Argparse.Usage_error 1); 14 | 15 | options.tools#ui#open_cache_explorer |> Lwt_main.run 16 | -------------------------------------------------------------------------------- /src/support/stream.mli: -------------------------------------------------------------------------------- 1 | (** This is a reimplementation of parts of the OCaml 4 Stream API, which was deprecated in 4.14. 2 | The only API difference is that {!from}'s callback no longer takes a position argument. *) 3 | 4 | type 'a t 5 | 6 | exception Failure 7 | 8 | val of_list : 'a list -> 'a t 9 | val count : 'a t -> int 10 | val empty : 'a t -> unit 11 | val from : (unit -> 'a option) -> 'a t 12 | val next : 'a t -> 'a 13 | val junk : 'a t -> unit 14 | val npeek : int -> 'a t -> 'a list 15 | val peek : 'a t -> 'a option 16 | -------------------------------------------------------------------------------- /src/tests/data/MultiArchLib.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | MultiArchLib 4 | MultiArchLib 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/tests/data/Autopackage.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Autopackage 4 | Autopackage 5 | Autopackage 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/tests/data/RecipeSingleFile.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Recipe 4 | Recipe 5 | Recipe 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/tests/data/runnable/RunExec.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | RunExec 4 | script that uses a command 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/tests/data/search-firefox.xml: -------------------------------------------------------------------------------- 1 | WebbrowserNetworkWebbrowserNetworkWeb Browser 2 | -------------------------------------------------------------------------------- /src/tests/data/HelloExtractToNewDest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Recipe 4 | Recipe 5 | Recipe 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/tests/data/runnable/RecursiveRunner.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Recursive Runnable 4 | our runner has a runner of its own 5 | 6 | 7 | 8 | 9 | arg-for-runnable 10 | 11 | recursive-arg 12 | -- 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/zeroinstall/compiled.mli: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2014, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** Binary implementations that could be created from source ones. *) 6 | 7 | (** Return the binary implementation that would be created by compiling the given 8 | * source. *) 9 | val of_source : host_arch:Arch.arch -> Impl.existing Impl.t -> 10 | [ `Ok of Impl.generic_implementation 11 | | `Reject of [> `No_compile_command] 12 | | `Filtered_out ] (* We produced a binary not supported by this version of 0install. *) 13 | -------------------------------------------------------------------------------- /src/tests/data/RecipeExtractToNewDest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Recipe 4 | Recipe 5 | Recipe 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/tests/data/RecipeSymlink.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | RecipeSymlink 4 | RecipeSymlink 5 | RecipeSymlink 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/tests/data/selections.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/zeroinstall/justify.mli: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2014, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** Explaining why a particular implementation was or was not chosen. *) 6 | 7 | (** Run a solve with a single implementation as the only choice for an interface. 8 | If no solution is possible, explain why not. 9 | If a solution is possible, explain why it isn't the preferred solution. *) 10 | val justify_decision : General.config -> Feed_provider.feed_provider -> Requirements.t -> Sigs.iface_uri -> source:bool -> Feed_url.global_id -> string 11 | -------------------------------------------------------------------------------- /src/tests/data/RecipeRemove.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Recipe 4 | Recipe 5 | Recipe 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/tests/data/RecipeRemoveDir.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Recipe 4 | Recipe 5 | Recipe 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/tests/data/arch/local/python2-2.7.2-4/desc: -------------------------------------------------------------------------------- 1 | %NAME% 2 | python2 3 | 4 | %VERSION% 5 | 2.7.2-4 6 | 7 | %DESC% 8 | A high-level scripting language 9 | 10 | %URL% 11 | http://www.python.org/ 12 | 13 | %LICENSE% 14 | PSF 15 | 16 | %ARCH% 17 | x86_64 18 | 19 | %BUILDDATE% 20 | 1321896418 21 | 22 | %INSTALLDATE% 23 | 1326037157 24 | 25 | %PACKAGER% 26 | Stéphane Gaudreault 27 | 28 | %SIZE% 29 | 72404992 30 | 31 | %DEPENDS% 32 | bzip2 33 | gdbm 34 | openssl 35 | zlib 36 | expat 37 | sqlite3 38 | libffi 39 | 40 | %OPTDEPENDS% 41 | tk: for IDLE 42 | 43 | %CONFLICTS% 44 | python<3 45 | 46 | -------------------------------------------------------------------------------- /src/zeroinstall/stability.mli: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2017, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** The stability rating of an implementation. These are set by the author in the upstread feed, 6 | but can be overridden by users. *) 7 | 8 | type t = 9 | | Insecure 10 | | Buggy 11 | | Developer 12 | | Testing 13 | | Stable 14 | | Packaged 15 | | Preferred 16 | 17 | val of_string : from_user:bool -> string -> t 18 | (** The ratings [Packaged] and [Preferred] are only allowed if [from_user] is set. *) 19 | 20 | val to_string : t -> string 21 | -------------------------------------------------------------------------------- /src/zeroinstall/command.mli: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2018, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** elements *) 6 | 7 | open Support 8 | open Support.Common 9 | 10 | (** [build_command sels reqs env] is the argv for the command to run to execute [sels] as requested by [reqs]. 11 | In --dry-run mode, don't complain if the target doesn't exist. *) 12 | val build_command : 13 | ?main:string -> 14 | ?dry_run:bool -> 15 | (Selections.impl * filepath option) Selections.RoleMap.t -> 16 | Selections.requirements -> 17 | Env.t -> 18 | string list 19 | -------------------------------------------------------------------------------- /src/zeroinstall/default_ui.mli: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2013, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** High-level helper functions *) 6 | 7 | (** Create a UI appropriate for the current environment and user options. 8 | * This will be a graphical UI if [Gui.try_get_gui] returns one and we're not in dry-run mode. 9 | * Otherwise, it will be an interactive console UI if stderr is a tty. 10 | * Otherwise, it will be a batch UI (no progress display). 11 | *) 12 | val make_ui : 13 | General.config -> 14 | use_gui:[< `Yes | `No | `Auto] -> 15 | Ui.ui_handler 16 | -------------------------------------------------------------------------------- /src/cli/alias.ml: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2013, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | open Support 6 | open Options 7 | 8 | let handle options flags args = 9 | match args with 10 | | [name] -> Safe_exn.failf "ERROR: '0alias' has been removed; use '0install update' instead:\n0install update alias:%s" name 11 | | [name; iface] -> 12 | Format.fprintf options.stdout "(\"0alias\" is deprecated; using \"0install add\" instead)@."; 13 | Add.handle options flags [name; iface] 14 | | _ -> Safe_exn.failf "ERROR: '0alias' has been removed; use '0install add' instead" 15 | -------------------------------------------------------------------------------- /src/tests/data/MultiArch.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | MultiArch 4 | MultiArch 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/tests/data/Recipe.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Recipe 4 | Recipe 5 | Recipe 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/tests/data/arch/local/zeroinstall-injector-1.5-1/desc: -------------------------------------------------------------------------------- 1 | %NAME% 2 | zeroinstall-injector 3 | 4 | %VERSION% 5 | 1.5-1 6 | 7 | %DESC% 8 | A decentralised loosly-coupled secure installation system 9 | 10 | %URL% 11 | http://zero-install.sourceforge.net/ 12 | 13 | %LICENSE% 14 | GPL2 15 | LGPL 16 | 17 | %ARCH% 18 | any 19 | 20 | %BUILDDATE% 21 | 1326038881 22 | 23 | %INSTALLDATE% 24 | 1326038910 25 | 26 | %PACKAGER% 27 | Unknown Packager 28 | 29 | %SIZE% 30 | 2244608 31 | 32 | %DEPENDS% 33 | pygtk 34 | gnupg 35 | hicolor-icon-theme 36 | desktop-file-utils 37 | 38 | %OPTDEPENDS% 39 | xdg-utils: GNOME and KDE desktop integration 40 | 41 | -------------------------------------------------------------------------------- /src/zeroinstall/host_python.mli: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2017, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** Special-case code for detecting some Python-related packages that used to 6 | be installed automatically whenever 0install was, but now might not be 7 | after the move to OCaml. *) 8 | 9 | open Support.Common 10 | 11 | type t 12 | 13 | val make : system -> t 14 | 15 | val get : t -> [> `Remote_feed of string] -> (string * [`Package_impl of Impl.package_impl] Impl.t) list 16 | (** [get t feed_url] returns the list of host implementations of [feed_url], if we recognise it. *) 17 | -------------------------------------------------------------------------------- /src/tests/data/RecipeRenameToNewDest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Recipe 4 | Recipe 5 | Recipe 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/support/dune: -------------------------------------------------------------------------------- 1 | (rule 2 | (targets extra_objects.sexp) 3 | (enabled_if (<> %{os_type} "Win32")) 4 | (action (write-file %{targets} "()"))) 5 | 6 | (rule 7 | (targets extra_objects.sexp) 8 | (enabled_if (= %{os_type} "Win32")) 9 | (action (chdir %{workspace_root} 10 | (write-file %{targets} "(\"%{dep:../windows/0install.exe.o}\")")))) 11 | 12 | (library 13 | (name support) 14 | (libraries lwt lwt.unix sha str xmlm yojson 15 | (select windows_api.ml from 16 | (zeroinstall_windows -> windows_api.enabled.ml) 17 | ( -> windows_api.disabled.ml))) 18 | (foreign_stubs 19 | (language c) 20 | (names utils))) 21 | -------------------------------------------------------------------------------- /src/tests/data/Recursive.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | Recursive 5 | Recursive 6 | Recursive 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/cli/select.ml: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2013, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** The "0install select" command *) 6 | 7 | open Options 8 | 9 | let handle options flags args = 10 | let select_opts = ref [] in 11 | Support.Argparse.iter_options flags (function 12 | | #common_option as o -> Common_options.process_common_option options o 13 | | #select_option | `ShowXML | `Refresh as o -> select_opts := o :: !select_opts 14 | ); 15 | match args with 16 | | [arg] -> ignore (Generic_select.handle options !select_opts arg `Select_only) 17 | | _ -> raise (Support.Argparse.Usage_error 1) 18 | -------------------------------------------------------------------------------- /src/tests/data/ranking-cpu.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Ranking 4 | ranking 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/tests/data/source-sel.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /binary-feed.xml.in: -------------------------------------------------------------------------------- 1 | 2 | 3 | 0install 4 | decentralised installation system 5 | 6 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/tests/data/Hello: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Hello 5 | Hello 6 | Hello 7 | 8 | 9 | 10 | 11 | 16 | -------------------------------------------------------------------------------- /src/cli/download.ml: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2013, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** The "0install download" command *) 6 | 7 | open Options 8 | 9 | let handle options flags args = 10 | let select_opts = ref [] in 11 | Support.Argparse.iter_options flags (function 12 | | #common_option as o -> Common_options.process_common_option options o 13 | | #binary_select_option | `ShowHuman | `ShowXML | `Refresh as o -> select_opts := o :: !select_opts 14 | ); 15 | match args with 16 | | [arg] -> ignore (Generic_select.handle options !select_opts arg `Download_only) 17 | | _ -> raise (Support.Argparse.Usage_error 1) 18 | -------------------------------------------------------------------------------- /src/zeroinstall/dune: -------------------------------------------------------------------------------- 1 | (library 2 | (name zeroinstall) 3 | (modules_without_implementation feed_provider progress sigs ui) 4 | (libraries dynlink lwt lwt.unix react lwt_react support yojson xmlm 0install-solver 5 | (select http.ml from 6 | (curl curl.lwt -> http.curl.ml) 7 | (cohttp cohttp-lwt cohttp-lwt-unix lwt_ssl -> http.cohttp.ml) 8 | ) 9 | (select dbus.ml from 10 | (obus.network_manager 11 | obus.notification -> dbus.with.ml) 12 | (obus.network-manager 13 | obus.notification -> dbus.with.ml) 14 | ( -> dbus.without.ml)))) 15 | -------------------------------------------------------------------------------- /src/tests/data/Hello.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Hello 5 | Hello 6 | Hello 7 | 8 | 9 | 10 | 11 | 16 | -------------------------------------------------------------------------------- /src/windows/0install.exe.manifest: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/tests/data/Build.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | Build 5 | Build 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/tests/data/Hello-new.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Hello 5 | Hello 6 | Hello 7 | 8 | 9 | 10 | 11 | 16 | -------------------------------------------------------------------------------- /src/tests/data/Hello-bad-digest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Hello 5 | Hello 6 | Hello 7 | 8 | 9 | 10 | 11 | 16 | -------------------------------------------------------------------------------- /src/tests/data/RecipeRename.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Recipe 4 | Recipe 5 | Recipe 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/cli/destroy.ml: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2013, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** The "0install destroy" command *) 6 | 7 | open Options 8 | open Support 9 | 10 | let handle options flags args = 11 | Support.Argparse.iter_options flags (function 12 | | #common_option as o -> Common_options.process_common_option options o 13 | ); 14 | match args with 15 | | [name] -> ( 16 | match Zeroinstall.Apps.lookup_app options.config name with 17 | | None -> Safe_exn.failf "No such application '%s'" name 18 | | Some app -> Zeroinstall.Apps.destroy options.config app 19 | ) 20 | | _ -> raise (Support.Argparse.Usage_error 1) 21 | -------------------------------------------------------------------------------- /src/tests/data/Hello-wrong-size: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Hello 5 | Hello 6 | 7 | Hello 8 | 9 | 10 | 11 | 12 | 17 | -------------------------------------------------------------------------------- /src/tests/data/Local.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Echo 4 | Local feed (English) 5 | Local feed (Greek) 6 | Local feed (English GB) 7 | Fuente local 8 | 9 | English 10 | Español 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/support/urlparse.mli: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2013, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** Helpers for dealing with URLs. *) 6 | 7 | (* Note: Ocamlnet has a Neturl package which does all this, but it's too big for us. 8 | * This is just enough for 0install: we support only http:, https: and ftp: schemes. *) 9 | 10 | (* "http://host:port/path?query" -> ("http://host:port", "/path?query") 11 | * A missing path is returned as "/" *) 12 | val split_path : string -> (string * string) 13 | 14 | (** [join_url base url] converts [url] to an absolute URL (if it isn't already), using 15 | * [base] as the base. *) 16 | val join_url : string -> string -> string 17 | -------------------------------------------------------------------------------- /src/tests/data/RecipeExtractToExistingDest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Recipe 4 | Recipe 5 | Recipe 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/tests/data/test_selections.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | my-prog 10 | Hello World 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/windows/zeroinstall_windows.ml: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2019, Thomas Leonard 2 | See the README file for details, or visit http://0install.net. *) 3 | 4 | type wow = 5 | | KEY_WOW64_NONE (* 0 *) 6 | | KEY_WOW64_32KEY (* 1 *) 7 | | KEY_WOW64_64KEY (* 2 *) 8 | 9 | let () = ignore Callback.register 10 | 11 | external win_get_appdata : unit -> string = "caml_win_get_appdata" 12 | external win_get_local_appdata : unit -> string = "caml_win_get_local_appdata" 13 | external win_get_common_appdata : unit -> string = "caml_win_get_common_appdata" 14 | external win_read_registry_string : string -> string -> wow -> string = "caml_win_read_registry_string" 15 | external win_read_registry_int : string -> string -> wow -> int = "caml_win_read_registry_int" 16 | -------------------------------------------------------------------------------- /src/tests/data/test_selections_win.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | my-prog 10 | Hello World 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: c 2 | sudo: required 3 | dist: xenial 4 | install: wget https://raw.githubusercontent.com/ocaml/ocaml-ci-scripts/master/.travis-opam.sh 5 | script: bash .travis-extra-deps.sh 6 | env: 7 | global: 8 | - POST_INSTALL_HOOK="bash .travis-test-compile.sh" 9 | - PINS="0install-solver.dev:. 0install.dev:. 0install-gtk.dev:." 10 | jobs: 11 | include: 12 | - env: OCAML_VERSION=4.08 PACKAGE="0install" 13 | os: linux 14 | 15 | - env: OCAML_VERSION=4.08 PACKAGE="0install-gtk" 16 | os: linux 17 | 18 | - env: STATIC_DIST=true 19 | os: linux 20 | services: 21 | - docker 22 | 23 | - env: OCAML_VERSION=4.09 PACKAGE="0install-gtk" 24 | os: osx 25 | addons: 26 | apt: 27 | update: true 28 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | platform: 2 | - x86 3 | 4 | environment: 5 | FORK_USER: ocaml 6 | FORK_BRANCH: master 7 | OPAM_SWITCH: 4.08.1+mingw64c 8 | CYG_ROOT: C:\cygwin64 9 | PINS: 0install.dev:. 0install-gtk.dev:. 0install-solver.dev:. 10 | PACKAGE: 0install 11 | 12 | install: 13 | - ps: iex ((new-object net.webclient).DownloadString("https://raw.githubusercontent.com/$env:FORK_USER/ocaml-ci-scripts/$env:FORK_BRANCH/appveyor-install.ps1")) 14 | 15 | build_script: 16 | - call %CYG_ROOT%\bin\bash.exe -l %APPVEYOR_BUILD_FOLDER%\appveyor-opam.sh 17 | - call %CYG_ROOT%\bin\bash.exe -l -c 'opam install 0install' 18 | - mv %CYG_ROOT%\home\appveyor\.opam %APPVEYOR_BUILD_FOLDER%\opam 19 | 20 | artifacts: 21 | - name: Binaries 22 | path: 'opam\*\bin\0*' 23 | -------------------------------------------------------------------------------- /src/gui_gtk/trust_box.mli: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2016, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** A dialog box for confirming whether to trust a feed's GPG key(s). *) 6 | 7 | open Support 8 | open Zeroinstall 9 | 10 | val confirm_keys : 11 | Gpg.t -> 12 | Trust.trust_db -> 13 | ?parent:#GWindow.window_skel -> 14 | Feed_url.remote_feed -> 15 | (Gpg.fingerprint * (Progress.key_vote_type * string) list Lwt.t) list -> 16 | Gpg.fingerprint list Lwt.t 17 | (** [confirm_keys gpg trust_db feed hints] asks the user to confirm which keys they trust to sign [feed]. 18 | [hints] is displayed to the user to help them decide. 19 | The result is a list of fingerprints which should now be trusted. *) 20 | -------------------------------------------------------------------------------- /src/zeroinstall/requirements.mli: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2016, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** A structure representing constraints/requirements specified by the user *) 6 | 7 | open Support 8 | 9 | type t = { 10 | interface_uri : Sigs.iface_uri; 11 | command : string option; 12 | source : bool; 13 | extra_restrictions : string XString.Map.t; (* iface -> range *) 14 | os : Arch.os option; 15 | cpu : Arch.machine option; 16 | message : string option; 17 | may_compile : bool; 18 | } 19 | 20 | val run : Sigs.iface_uri -> t 21 | (** [run iface] is a requirement to run [iface] with no restrictions. *) 22 | 23 | val of_json : Yojson.Basic.t -> t 24 | val to_json : t -> Yojson.Basic.t 25 | -------------------------------------------------------------------------------- /src/tests/data/package-selection.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/tests/data/Hello-impossible.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Hello 5 | Hello 6 | Hello 7 | 8 | 9 | 10 | 11 | 12 | 17 | -------------------------------------------------------------------------------- /src/cli/desktop.ml: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2013, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | open Zeroinstall.General 6 | open Options 7 | 8 | let handle options flags args = 9 | let tools = options.tools in 10 | Support.Argparse.iter_options flags (function 11 | | #common_option as o -> Common_options.process_common_option options o 12 | ); 13 | let gui = tools#ui in 14 | let config = options.config in 15 | 16 | let finished = 17 | match args with 18 | | [] -> 19 | gui#open_app_list_box; 20 | | [arg] -> 21 | let url = Generic_select.canonical_iface_uri config.system arg in 22 | gui#open_add_box url 23 | | _ -> raise (Support.Argparse.Usage_error 1) in 24 | 25 | Lwt_main.run finished 26 | -------------------------------------------------------------------------------- /src/support/system.mli: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2013, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** Access to the rest of the system. This capabilities are provided via an object, which can be replaced for unit-testing. *) 6 | 7 | module type UnixType = module type of Unix 8 | 9 | val wrap_unix_errors : (unit -> 'a) -> 'a 10 | val check_exit_status : Unix.process_status -> unit 11 | val waitpid_non_intr : int -> int * Unix.process_status 12 | val reap_child : int -> unit 13 | 14 | val canonical_machine : string -> string 15 | val canonical_os : string -> string 16 | 17 | val dev_null : Common.filepath 18 | 19 | module RealSystem : 20 | functor (U : UnixType) -> 21 | sig 22 | class real_system : Common.system 23 | end 24 | -------------------------------------------------------------------------------- /src/tests/data/runnable/Runnable.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Runnable 4 | test script that needs a runner 5 | 6 | 7 | 8 | 9 | arg-for-runner 10 | 11 | command-arg 12 | -- 13 | 14 | 15 | 16 | arg-for-runner 17 | 18 | foo-arg 19 | -- 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/tests/data/Binary.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Binary 5 | Binary 6 | Binary 7 | 8 | 9 | 10 | 11 | 12 | 13 | 18 | -------------------------------------------------------------------------------- /src/tests/data/Binary2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Binary 5 | Binary 6 | Binary 7 | 8 | 9 | 10 | 11 | 12 | 13 | 18 | -------------------------------------------------------------------------------- /share/fish/completions/0launch.fish: -------------------------------------------------------------------------------- 1 | function __fish_0launch_complete 2 | begin; 3 | set -x COMP_CWORD (count (commandline --tokenize --cut-at-cursor)) 4 | set args (commandline --tokenize) 5 | for item in (0launch _complete fish $args) 6 | switch $item 7 | case 'add *' ; echo $item | cut -c 5- 8 | case 'filter *' ; echo $item | cut -c 8- 9 | case 'prefix *' ; echo $item | cut -c 8- 10 | case 'file' ; 11 | begin 12 | # echo needed to prevent empty list 13 | set arg (echo (commandline --tokenize --current-token)) 14 | ls -1 (dirname {$arg}_) ^/dev/null 15 | end; 16 | case '*' ; echo >&2 Bad reply $item 17 | end 18 | end 19 | end 20 | end 21 | 22 | complete -e -c 0launch 23 | complete -c 0launch --no-files --arguments '(__fish_0launch_complete)' 24 | -------------------------------------------------------------------------------- /share/fish/completions/0install.fish: -------------------------------------------------------------------------------- 1 | function __fish_0install_complete 2 | begin; 3 | set -x COMP_CWORD (count (commandline --tokenize --cut-at-cursor)) 4 | set args (commandline --tokenize) 5 | for item in (0install _complete fish $args) 6 | switch $item 7 | case 'add *' ; echo $item | cut -c 5- 8 | case 'filter *' ; echo $item | cut -c 8- 9 | case 'prefix *' ; echo $item | cut -c 8- 10 | case 'file' ; 11 | begin 12 | # echo needed to prevent empty list 13 | set arg (echo (commandline --tokenize --current-token)) 14 | ls -1 (dirname {$arg}_) ^/dev/null 15 | end; 16 | case '*' ; echo >&2 Bad reply $item 17 | end 18 | end 19 | end 20 | end 21 | 22 | complete -e -c 0install 23 | complete -c 0install --no-files --arguments '(__fish_0install_complete)' 24 | -------------------------------------------------------------------------------- /src/gui_gtk/unsorted_list.ml: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2013, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | type t = GTree.list_store 6 | type iter = Gtk.tree_iter 7 | 8 | let list_store cols = GTree.list_store cols 9 | let clear (model:t) = model#clear () 10 | let model_sort model = GTree.model_sort model 11 | let get_iter_first (model:t) = model#get_iter_first 12 | let set (model:t) ~(row:iter) ~column value = model#set ~row ~column value 13 | let get (model:t) ~(row:iter) ~column = model#get ~row ~column 14 | let remove (model:t) (row:iter) = model#remove row 15 | let convert_iter_to_child_iter (model:GTree.model_sort) (iter:Gtk.tree_iter) = model#convert_iter_to_child_iter iter 16 | let append (model:t) = model#append () 17 | let iter_next (model:t) (row:iter) = model#iter_next row 18 | -------------------------------------------------------------------------------- /src/zeroinstall/key_info_provider.mli: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2014, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** Queries the configured key info server for advice about GPG keys. *) 6 | 7 | type t 8 | 9 | val make : General.config -> t 10 | 11 | (** [get provider downloader fingerprint] requests information about the given GPG key. 12 | * If the info is in the cache, returns it immediately. 13 | * If we are already fetching this information, returns the existing task. 14 | * If the previous fetch failed, tries again. 15 | * On error, returns a [Bad] response rather than raising an exception. *) 16 | val get : 17 | t -> 18 | download:(switch:Lwt_switch.t -> string -> Downloader.download_result Lwt.t) -> 19 | Support.Gpg.fingerprint -> 20 | Progress.key_vote list Lwt.t 21 | -------------------------------------------------------------------------------- /src/tests/data/ReplacedConflicts.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | ReplacedConflicts 4 | replaced-by conflicts 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/zeroinstall/mirror.mli: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2014, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** Support functions for using mirror servers *) 6 | 7 | (** Get a recipe for the tar.bz2 of the implementation at the mirror. 8 | * @return a recipe for a single archive containing the whole implementation. 9 | * Note: This is just one way we try the mirror. You can also use [for_archive] 10 | * to check for mirrored copies of individual archives. *) 11 | val for_impl : General.config -> _ Impl.t -> Recipe.t option 12 | 13 | (** Return the URL to check for a mirror of an archive URL. *) 14 | val for_archive : General.config -> string -> string option 15 | 16 | (** Return the URL to check for a mirror of a feed. *) 17 | val for_feed : General.config -> Feed_url.remote_feed -> string option 18 | -------------------------------------------------------------------------------- /src/cli/cli.mli: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2013, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** Parsing command-line arguments *) 6 | 7 | val common_options : 8 | ([> `DryRun 9 | | `Help 10 | | `UseGUI of [`Yes | `No | `Auto] 11 | | `Verbose 12 | | `WithStore of Support.Common.filepath ], 13 | Options.zi_arg_type) 14 | Support.Argparse.opt_spec list 15 | 16 | val commands : Command_tree.commands 17 | val store_commands : Command_tree.commands 18 | 19 | val no_command : Command_tree.node 20 | 21 | val spec : (Options.zi_option, Options.zi_arg_type) Support.Argparse.argparse_spec 22 | val get_default_options : stdout:Format.formatter -> Zeroinstall.General.config -> Options.global_settings 23 | val handle : stdout:Format.formatter -> Zeroinstall.General.config -> string list -> unit 24 | -------------------------------------------------------------------------------- /src/tests/fake_gpg_agent.mli: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2014, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (* A dummy gpg agent for unit-tests. 6 | * GnuPG >= 2.1 requires an agent, even though it doesn't need it for anything, 7 | * and there's no way to stop it trying to connect to it. 8 | * See: http://stackoverflow.com/questions/27459869/how-to-stop-gpg-2-1-spawning-many-agents-for-unit-testing *) 9 | 10 | open Support.Common 11 | 12 | (** [run dir] creates a socket in [dir] and accepts connections from gpg, returning 13 | * dummy responses to all commands. Cancel the thread when done. *) 14 | val run : filepath -> unit Lwt.t 15 | 16 | (** [with_gpg test] creates a temporary directory with a fake agent socket and runs [test tmpdir] inside it. *) 17 | val with_gpg : (filepath -> unit) -> (unit -> unit) 18 | -------------------------------------------------------------------------------- /0install-gtk.opam: -------------------------------------------------------------------------------- 1 | opam-version: "2.0" 2 | synopsis: "Decentralised installation system - GTK UI" 3 | maintainer: "talex5@gmail.com" 4 | license: "LGPL-2.1-or-later" 5 | authors: "zero-install-devel@lists.sourceforge.net" 6 | homepage: "https://0install.net/" 7 | bug-reports: "https://github.com/0install/0install/issues" 8 | dev-repo: "git+https://github.com/0install/0install.git" 9 | doc: "https://0install.github.io/0install/" 10 | build: [ 11 | ["dune" "build" "-p" name "-j" jobs "@install" "@runtest" {with-test}] 12 | ] 13 | depends: [ 14 | "ocaml" {>= "4.08.0"} 15 | "0install" {= version} 16 | "ounit2" {with-test} 17 | "dune" {>= "2.5"} 18 | "lablgtk3" {>= "3.1.0"} 19 | "lwt_glib" 20 | ] 21 | description: """ 22 | Zero Install is a decentralised cross-distribution software installation system. 23 | This package provides a GTK-based user interface for it.""" 24 | -------------------------------------------------------------------------------- /src/cli/runenv_shared.ml: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2013, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (* The main runenv code, used on all systems (POSIX and Windows) *) 6 | 7 | open Support 8 | open Support.Common 9 | 10 | (** This is called in a new process by the launcher created by [Zeroinstall.Exec.ensure_runenv]. *) 11 | let runenv (system:system) args = 12 | match args with 13 | | [] -> failwith "No args passed to runenv!" 14 | | arg0::args -> 15 | try 16 | let var = "zeroinstall_runenv_" ^ Filename.basename arg0 in 17 | let s = Support.Utils.getenv_ex system var in 18 | let open Yojson.Basic in 19 | let envargs = Util.convert_each Util.to_string (from_string s) in 20 | system#exec (envargs @ args) 21 | with Safe_exn.T _ as ex -> Safe_exn.reraise_with ex "... launching %s" arg0 22 | -------------------------------------------------------------------------------- /src/support/hash.mli: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2014, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** Secure hashes. *) 6 | 7 | type digest_context 8 | 9 | (** Create a new context from an algorithm name. 10 | * Supported names are "sha1" and "sha256". *) 11 | val create : string -> digest_context 12 | 13 | (** Add bytes to a context. *) 14 | val update : digest_context -> string -> unit 15 | 16 | (** Return the final digest of [ctx] as an ASCII string. [ctx] cannot be used after this. *) 17 | val hex_digest : digest_context -> string 18 | 19 | (** Return the digest as a base-32-encoded ASCII string (with no padding characters) *) 20 | val b32_digest : digest_context -> string 21 | 22 | (** Read until the end of the channel, adding each byte to the digest. *) 23 | val update_from_channel : digest_context -> in_channel -> unit 24 | -------------------------------------------------------------------------------- /src/windows/dune: -------------------------------------------------------------------------------- 1 | (* -*- tuareg -*- *) 2 | 3 | let bin = 4 | try 5 | match Sys.getenv "WINDRES" with 6 | | "" -> raise Not_found 7 | | x -> x 8 | with Not_found -> 9 | if Sys.word_size = 32 then 10 | "i686-w64-mingw32-windres" 11 | else 12 | "x86_64-w64-mingw32-windres" 13 | 14 | let dune = Printf.sprintf {| 15 | (library 16 | (name zeroinstall_windows) 17 | (enabled_if (or (= %%{os_type} "Win32") 18 | (= %%{os_type} "Cygwin"))) 19 | (foreign_stubs 20 | (language c) 21 | (flags -lwindows -lshell32) 22 | (names windows))) 23 | 24 | (rule 25 | (targets 0install.exe.o) 26 | (deps 0install.exe.rc 0install.exe.manifest) 27 | (action (run %s 28 | --input-format rc 29 | --input 0install.exe.rc 30 | --output-format coff 31 | --output 0install.exe.o))) 32 | |} bin 33 | 34 | let () = 35 | Jbuild_plugin.V1.send dune 36 | -------------------------------------------------------------------------------- /src/zeroinstall/exec.mli: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2013, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** Executing a selections document *) 6 | 7 | open General 8 | 9 | (** Calculate the arguments and environment to pass to exec to run this 10 | process. This also ensures any necessary launchers exist, creating them 11 | if not. *) 12 | val get_exec_args : config -> ?main:string -> Selections.t -> string list -> (string list * string array) 13 | 14 | (** Run the given selections. If [wrapper] is given, run that command with the command we would have run as the arguments. 15 | If [exec] is given, use that instead of config.system#exec. *) 16 | val execute_selections : 17 | config -> 18 | ?exec:(string list -> env:string array -> 'a) -> 19 | ?wrapper:string -> 20 | ?main:string -> 21 | Selections.t -> 22 | string list -> 23 | [ `Dry_run of string | `Ok of 'a ] 24 | -------------------------------------------------------------------------------- /src/zeroinstall/feed_import.mli: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2020, Thomas Leonard 2 | See the README file for details, or visit http://0install.net. *) 3 | 4 | (** Parsed feed imports. *) 5 | 6 | type feed_type = 7 | | Feed_import (* A import element inside a feed *) 8 | | User_registered (* Added manually with "0install add-feed" : save to config *) 9 | | Site_packages (* Found in the site-packages directory : save to config for older versions, but flag it *) 10 | | Distro_packages (* Found in native_feeds : don't save *) 11 | 12 | type t = { 13 | src : Feed_url.non_distro_feed; 14 | 15 | os : Arch.os option; (* All impls requires this OS *) 16 | machine : Arch.machine option; (* All impls requires this CPU *) 17 | langs : string list option; (* No impls for languages not listed *) 18 | ty : feed_type; 19 | } 20 | 21 | val make_user : [< Feed_url.non_distro_feed] -> t 22 | -------------------------------------------------------------------------------- /.github/workflows/mac.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | run: 11 | name: Build 12 | runs-on: ${{ matrix.operating-system }} 13 | strategy: 14 | matrix: 15 | operating-system: [macos-latest] 16 | ocaml-version: [ '4.14.0' ] 17 | steps: 18 | - uses: actions/checkout@master 19 | - uses: ocaml/setup-ocaml@v2 20 | with: 21 | ocaml-compiler: ${{ matrix.ocaml-version }} 22 | - run: opam pin add 0install-solver.dev -n . 23 | - run: opam pin add 0install.dev -n . 24 | - run: opam pin add 0install-gtk.dev -n . 25 | - run: opam depext -yt 0install-gtk 26 | - run: opam install -t . --deps-only 27 | - run: opam exec -- make 28 | - uses: actions/upload-artifact@master 29 | with: 30 | name: 0install-${{ matrix.operating-system }}.zip 31 | path: dist 32 | -------------------------------------------------------------------------------- /src/tests/data/Conflicts.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Conflicts 5 | test conflicts 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /src/gui_gtk/alert_box.ml: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2013, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** A simple error report box *) 6 | 7 | open Gtk_common 8 | 9 | let report_info ?parent ~title message = 10 | let box = GWindow.message_dialog 11 | ?parent 12 | ~message_type:`INFO 13 | ~title 14 | ~message 15 | ~buttons:GWindow.Buttons.ok 16 | () in 17 | box#connect#response ==> (fun _ -> box#destroy ()); 18 | box#show () 19 | 20 | let last_error = ref None 21 | 22 | let report_error ?parent ex = 23 | last_error := Some ex; 24 | Support.Logging.dump_crash_log ~ex (); 25 | let error_box = GWindow.message_dialog 26 | ?parent 27 | ~message_type:`ERROR 28 | ~title:"Error" 29 | ~message:(Printexc.to_string ex) 30 | ~buttons:GWindow.Buttons.ok 31 | () in 32 | error_box#connect#response ==> (fun _ -> error_box#destroy ()); 33 | error_box#show () 34 | -------------------------------------------------------------------------------- /src/tests/data/Versions.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | Versions 5 | Versions 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /share/bash-completion/completions/0install: -------------------------------------------------------------------------------- 1 | _0install_completion() { 2 | local c IFS=$'\n' 3 | COMPREPLY=() 4 | local TO_FILTER=() 5 | local WORD=${COMP_WORDS[$COMP_CWORD]} 6 | 7 | if [ "$WORD" == "=" ]; then 8 | WORD="" 9 | fi 10 | 11 | local RESULTS=$(COMP_CWORD=$COMP_CWORD ${COMP_WORDS[0]} _complete bash "${COMP_WORDS[@]}") 12 | while read item 13 | do 14 | #echo "item>$item<" >&2 15 | case "$item" in 16 | add\ *) COMPREPLY=(${COMPREPLY[@]} ${item/#add /}) ;; 17 | filter\ *) TO_FILTER=(${TO_FILTER[@]} ${item/#filter /}) ;; 18 | prefix\ *) COMPREPLY=(${COMPREPLY[@]} ${item/#prefix /}) ;; 19 | file) COMPREPLY=(${COMPREPLY[@]} $(compgen -A file "$WORD")) ;; 20 | "") ;; 21 | *) echo 1>&2 Bad reply $item ;; 22 | esac 23 | done <<< "$RESULTS" 24 | if (( ${#TO_FILTER[@]} > 0 )); then 25 | COMPREPLY=( ${COMPREPLY[@]} $(compgen -W "${TO_FILTER[*]}" -- "$WORD" ) ) 26 | fi 27 | } 28 | complete -o nospace -F _0install_completion 0install 29 | -------------------------------------------------------------------------------- /share/bash-completion/completions/0launch: -------------------------------------------------------------------------------- 1 | _0launch_completion() { 2 | local c IFS=$'\n' 3 | COMPREPLY=() 4 | local TO_FILTER=() 5 | local WORD=${COMP_WORDS[$COMP_CWORD]} 6 | 7 | if [ "$WORD" == "=" ]; then 8 | WORD="" 9 | fi 10 | 11 | local RESULTS=$(COMP_CWORD=$COMP_CWORD ${COMP_WORDS[0]} _complete bash "${COMP_WORDS[@]}") 12 | while read item 13 | do 14 | #echo "item>$item<" >&2 15 | case "$item" in 16 | add\ *) COMPREPLY=(${COMPREPLY[@]} ${item/#add /}) ;; 17 | filter\ *) TO_FILTER=(${TO_FILTER[@]} ${item/#filter /}) ;; 18 | prefix\ *) COMPREPLY=(${COMPREPLY[@]} ${item/#prefix /}) ;; 19 | file) COMPREPLY=(${COMPREPLY[@]} $(compgen -A file "$WORD")) ;; 20 | "") ;; 21 | *) echo 1>&2 Bad reply $item ;; 22 | esac 23 | done <<< "$RESULTS" 24 | if (( ${#TO_FILTER[@]} > 0 )); then 25 | COMPREPLY=( ${COMPREPLY[@]} $(compgen -W "${TO_FILTER[*]}" -- "$WORD" ) ) 26 | fi 27 | } 28 | complete -o nospace -F _0launch_completion 0launch 29 | -------------------------------------------------------------------------------- /src/tests/fake_distro.ml: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2016, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | open Support.Common 6 | 7 | let fake_packagekit status = 8 | object (_ : Zeroinstall.Packagekit.packagekit) 9 | method status = Lwt.return status 10 | method get_impls (package_name:string) = 11 | log_info "packagekit: get_impls(%s)" package_name; 12 | { Zeroinstall.Packagekit.results = []; problems = [] } 13 | method check_for_candidates ~ui:_ ~hint (package_names:string list) : unit Lwt.t = 14 | log_info "packagekit: check_for_candidates(%s) for %s" (String.concat ", " package_names) hint; 15 | Lwt.return () 16 | method install_packages _ui _names = failwith "install_packages" 17 | end 18 | 19 | 20 | let make config = 21 | let packagekit = lazy (fake_packagekit `Ok) in 22 | Zeroinstall.Distro_impls.generic_distribution ~packagekit config |> Zeroinstall.Distro.of_provider 23 | -------------------------------------------------------------------------------- /src/zeroinstall/default_ui.ml: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2013, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** High-level helper functions *) 6 | 7 | open General 8 | open Support 9 | open Support.Common 10 | 11 | let make_ui config ~use_gui : Ui.ui_handler = 12 | let use_gui = 13 | match use_gui, config.dry_run with 14 | | `Yes, true -> Safe_exn.failf "Can't use GUI with --dry-run" 15 | | (`Auto | `No), true -> `No 16 | | use_gui, false -> (use_gui :> [`Yes | `No | `Auto]) in 17 | 18 | let make_no_gui () = 19 | if config.system#isatty Unix.stderr then 20 | (new Console.console_ui :> Ui.ui_handler) 21 | else 22 | (new Console.batch_ui :> Ui.ui_handler) in 23 | 24 | match use_gui with 25 | | `No -> make_no_gui () 26 | | `Yes | `Auto -> 27 | (* [try_get_gui] will throw if use_gui is [Yes] and the GUI isn't available *) 28 | Gui.try_get_gui config ~use_gui |? lazy (make_no_gui ()) 29 | -------------------------------------------------------------------------------- /static/Dockerfile: -------------------------------------------------------------------------------- 1 | # Build on a really old system to avoid glibc symbol version problems. 2 | FROM ocaml/opam:debian-10-ocaml-4.14 3 | RUN sudo apt-get update && sudo apt-get -y install ca-certificates build-essential libglib2.0-dev libgtk-3-dev m4 pkg-config libexpat1-dev unzip gnupg wget --no-install-recommends 4 | WORKDIR /src 5 | RUN sudo chown opam /src 6 | RUN wget https://www.openssl.org/source/openssl-1.1.1q.tar.gz -O openssl.tgz 7 | RUN tar xf openssl.tgz 8 | # Install openssl from source without dynamic libraries. This is the easiest way to force it to be linked statically. 9 | RUN cd openssl-1.1.1q && ./config no-dgram no-dso no-dynamic-engine no-engine no-shared no-tests && make && sudo make install 10 | RUN sudo ln -sf /usr/bin/opam-2.1 /usr/bin/opam 11 | RUN opam install yojson xmlm ounit lwt_react cohttp-lwt-unix lwt_ssl obus lablgtk3 lwt_glib sha dune 12 | COPY --chown=opam . /src/ 13 | RUN opam exec -- make 14 | RUN ldd /src/dist/files/0install 15 | RUN strip /src/dist/files/0install 16 | -------------------------------------------------------------------------------- /src/cli/list_ifaces.ml: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2013, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** The "0install list" command *) 6 | 7 | open Options 8 | open Support 9 | 10 | let handle options flags args = 11 | Support.Argparse.iter_options flags (function 12 | | #common_option as o -> Common_options.process_common_option options o 13 | ); 14 | (* Actually, we list all the cached feeds. Close enough. *) 15 | let ifaces = Zeroinstall.Feed_cache.list_all_feeds options.config in 16 | let results = 17 | match args with 18 | | [] -> ifaces 19 | | [query] -> 20 | let re = Str.regexp_string_case_fold query in 21 | ifaces |> XString.Set.filter (fun item -> 22 | try Str.search_forward re item 0 |> ignore; true 23 | with Not_found -> false) 24 | | _ -> raise (Support.Argparse.Usage_error 1) in 25 | 26 | results |> XString.Set.iter (fun item -> Format.fprintf options.stdout "%s@." item) 27 | -------------------------------------------------------------------------------- /.travis-extra-deps.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | if [ "$STATIC_DIST" == true ]; then 3 | set -eux 4 | make static-test 5 | else 6 | set -eux 7 | 8 | # Install OCaml and OPAM PPAs 9 | install_on_ubuntu () { 10 | sudo apt-get install -qq python3 11 | } 12 | 13 | install_on_osx () { 14 | # Disable sandboxing on OS X; it prevents the unit-tests from working. 15 | cat > ~/.opamrc << EOF 16 | wrap-build-commands: [] 17 | wrap-install-commands: [] 18 | wrap-remove-commands: [] 19 | required-tools: [] 20 | EOF 21 | brew update &> /dev/null 22 | brew unlink python@2 # Python 3 conflicts with Python 2's /usr/local/bin/2to3-2 file 23 | brew upgrade gnupg wget 24 | brew install gtk+3 25 | } 26 | 27 | case $TRAVIS_OS_NAME in 28 | linux) 29 | install_on_ubuntu ;; 30 | osx) 31 | install_on_osx ;; 32 | *) echo "Unknown OS $TRAVIS_OS_NAME"; 33 | exit 1 ;; 34 | esac 35 | 36 | # (downloaded by Travis install step) 37 | bash -e ./.travis-opam.sh 38 | fi 39 | -------------------------------------------------------------------------------- /src/support/windows_api.enabled.ml: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2019, Thomas Leonard 2 | See the README file for details, or visit http://0install.net. *) 3 | 4 | module W = Zeroinstall_windows 5 | 6 | let v ~wow64 = 7 | let read_registry fn key value ~key64 = 8 | try 9 | match wow64, key64 with 10 | | true, false -> Some (fn key value W.KEY_WOW64_32KEY) 11 | | true, true -> Some (fn key value W.KEY_WOW64_64KEY) 12 | | false, false -> Some (fn key value W.KEY_WOW64_NONE) 13 | | false, true -> None 14 | with Failure msg -> 15 | Logging.log_debug "Error getting registry value %s:%s: %s" key value msg; 16 | None 17 | in 18 | object 19 | method get_appdata = W.win_get_appdata () 20 | method get_local_appdata = W.win_get_local_appdata () 21 | method get_common_appdata = W.win_get_common_appdata () 22 | method read_registry_string = read_registry W.win_read_registry_string 23 | method read_registry_int = read_registry W.win_read_registry_int 24 | end 25 | -------------------------------------------------------------------------------- /src/zeroinstall/feed_import.ml: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2020, Thomas Leonard 2 | See the README file for details, or visit http://0install.net. *) 3 | 4 | type feed_type = 5 | | Feed_import (* A import element inside a feed *) 6 | | User_registered (* Added manually with "0install add-feed" : save to config *) 7 | | Site_packages (* Found in the site-packages directory : save to config for older versions, but flag it *) 8 | | Distro_packages (* Found in native_feeds : don't save *) 9 | 10 | type t = { 11 | src : Feed_url.non_distro_feed; 12 | os : Arch.os option; (* All impls requires this OS *) 13 | machine : Arch.machine option; (* All impls requires this CPU *) 14 | langs : string list option; (* No impls for languages not listed *) 15 | ty : feed_type; 16 | } 17 | 18 | let make_user src = { 19 | src = (src :> Feed_url.non_distro_feed); 20 | os = None; 21 | machine = None; 22 | langs = None; 23 | ty = User_registered; 24 | } 25 | -------------------------------------------------------------------------------- /src/zeroinstall/feed_provider.mli: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2013, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** Provides feeds to the solver. *) 6 | 7 | open Support 8 | 9 | type distro_impls = { 10 | impls : Impl.distro_implementation XString.Map.t; 11 | overrides : Feed_metadata.t; 12 | problems : string list; 13 | } 14 | 15 | class type feed_provider = 16 | object 17 | method forget_distro : Feed_url.non_distro_feed -> unit 18 | method forget_user_feeds : Sigs.iface_uri -> unit 19 | method get_distro_impls : Feed.t -> distro_impls 20 | method get_feed : Feed_url.non_distro_feed -> (Feed.t * Feed_metadata.t) option 21 | method get_feeds_used : Feed_url.non_distro_feed list 22 | method get_iface_config : Sigs.iface_uri -> Feed_cache.interface_config 23 | method have_stale_feeds : bool 24 | method replace_feed : Feed_url.non_distro_feed -> Feed.t -> unit 25 | method was_used : Feed_url.non_distro_feed -> bool 26 | end 27 | -------------------------------------------------------------------------------- /src/zeroinstall/stability.ml: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2017, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | open Support 6 | 7 | type t = 8 | | Insecure 9 | | Buggy 10 | | Developer 11 | | Testing 12 | | Stable 13 | | Packaged 14 | | Preferred 15 | 16 | let of_string ~from_user s = 17 | let if_from_user l = 18 | if from_user then l else Safe_exn.failf "Stability '%s' not allowed here" s in 19 | match s with 20 | | "insecure" -> Insecure 21 | | "buggy" -> Buggy 22 | | "developer" -> Developer 23 | | "testing" -> Testing 24 | | "stable" -> Stable 25 | | "packaged" -> if_from_user Packaged 26 | | "preferred" -> if_from_user Preferred 27 | | x -> Safe_exn.failf "Unknown stability level '%s'" x 28 | 29 | let to_string = function 30 | | Insecure -> "insecure" 31 | | Buggy -> "buggy" 32 | | Developer -> "developer" 33 | | Testing -> "testing" 34 | | Stable -> "stable" 35 | | Packaged -> "packaged" 36 | | Preferred -> "preferred" 37 | -------------------------------------------------------------------------------- /src/tests/data/Compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Compiler 5 | Compiler 6 | Compiler 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 23 | -------------------------------------------------------------------------------- /src/tests/data/Compiler2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Compiler 5 | Compiler 6 | Compiler 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 23 | -------------------------------------------------------------------------------- /src/cli/list_feeds.ml: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2013, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** The "0install list-feeds" command *) 6 | 7 | open Options 8 | open Zeroinstall.General 9 | 10 | module F = Zeroinstall.Feed 11 | module FC = Zeroinstall.Feed_cache 12 | 13 | let handle options flags args = 14 | Support.Argparse.iter_options flags (function 15 | | #common_option as o -> Common_options.process_common_option options o 16 | ); 17 | match args with 18 | | [iface] -> 19 | let iface = Generic_select.canonical_iface_uri options.config.system iface in 20 | let iface_config = FC.load_iface_config options.config iface in 21 | begin match iface_config.FC.extra_feeds with 22 | | [] -> Format.fprintf options.stdout "(no feeds)@." 23 | | extra_feeds -> 24 | extra_feeds |> List.iter (fun {Zeroinstall.Feed_import.src; _} -> 25 | Format.fprintf options.stdout "%s@." (Zeroinstall.Feed_url.format_url src); 26 | ) 27 | end 28 | | _ -> raise (Support.Argparse.Usage_error 1) 29 | -------------------------------------------------------------------------------- /src/zeroinstall/feed_url.mli: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2013, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** Feed URLs *) 6 | 7 | type local_feed = [`Local_feed of Support.Common.filepath] 8 | type remote_feed = [`Remote_feed of string] 9 | type non_distro_feed = [local_feed | remote_feed] 10 | type parsed_feed_url = [`Distribution_feed of non_distro_feed | non_distro_feed] 11 | 12 | (** A globally-unique identifier for an implementation. *) 13 | type global_id = { 14 | feed : parsed_feed_url; 15 | id : string; 16 | } 17 | 18 | val parse_non_distro : Sigs.feed_url -> non_distro_feed 19 | 20 | val parse : Sigs.feed_url -> parsed_feed_url 21 | 22 | val format_url : [< parsed_feed_url] -> Sigs.feed_url 23 | 24 | val pp : Format.formatter -> [< parsed_feed_url] -> unit 25 | 26 | (** Get the master feed for an interface URI. Internally, this is just [parse_non_distro]. *) 27 | val master_feed_of_iface : Sigs.iface_uri -> [> non_distro_feed] 28 | 29 | module FeedSet : (Set.S with type elt = non_distro_feed) 30 | module FeedMap : (Map.S with type key = non_distro_feed) 31 | -------------------------------------------------------------------------------- /src/gui_gtk/limiter.ml: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2013, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** Queuing of GUI updates. *) 6 | 7 | (** When [run fn] is called, run it asynchronously. If called again while it's still running, queue the next run. 8 | * If called while something is queued, drop the queued item and queue the new one instead. 9 | * This is useful to ensure that updates to the GUI are displayed, but don't interfere with each other. *) 10 | let make_limiter ~parent = 11 | let state = ref `Idle in 12 | let rec run fn = 13 | match !state with 14 | | `Running | `Running_with_queued _ -> state := `Running_with_queued fn 15 | | `Idle -> 16 | state := `Running; 17 | Gtk_utils.async ~parent (fun () -> 18 | Lwt.finalize fn 19 | (fun () -> 20 | begin match !state with 21 | | `Idle -> assert false 22 | | `Running -> state := `Idle 23 | | `Running_with_queued fn -> state := `Idle; run fn end; 24 | Lwt.return () 25 | ) 26 | ) in 27 | run 28 | -------------------------------------------------------------------------------- /src/zeroinstall/feed_metadata.mli: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2020, Thomas Leonard 2 | See the README file for details, or visit http://0install.net. *) 3 | 4 | (** Mutable state associated with feeds. *) 5 | 6 | open Support 7 | 8 | type t = { 9 | last_checked : float option; 10 | user_stability : Stability.t XString.Map.t; 11 | } 12 | 13 | val load : General.config -> [< Feed_url.parsed_feed_url] -> t 14 | (** Load per-feed extra data (last-checked time and preferred stability). *) 15 | 16 | val save : General.config -> [< Feed_url.parsed_feed_url] -> t -> unit 17 | 18 | val update : General.config -> [< Feed_url.parsed_feed_url] -> (t -> t) -> unit 19 | (** [update config url f] loads the metadata for [url], transforms it with [f], and then saves it back. *) 20 | 21 | val update_last_checked_time : General.config -> [< Feed_url.remote_feed] -> unit 22 | 23 | val stability : string -> t -> Stability.t option 24 | (** [stability id t] is the user's rating of [id], if any. *) 25 | 26 | val with_stability : string -> Stability.t option -> t -> t 27 | (** [with_stability id rating t] is [t] with [id]'s user stability set to [rating]. *) 28 | -------------------------------------------------------------------------------- /src/tests/data/Command.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | Commands 5 | Local feed 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /src/tests/data/LocalArchive.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Hello 4 | Hello 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /0install-solver.opam: -------------------------------------------------------------------------------- 1 | opam-version: "2.0" 2 | synopsis: "Package dependency solver" 3 | maintainer: "talex5@gmail.com" 4 | license: "LGPL-2.1-or-later" 5 | authors: "zero-install-devel@lists.sourceforge.net" 6 | homepage: "https://docs.0install.net/developers/solver/" 7 | bug-reports: "https://github.com/0install/0install/issues" 8 | dev-repo: "git+https://github.com/0install/0install.git" 9 | doc: "https://0install.github.io/0install/" 10 | build: [ 11 | ["dune" "build" "-p" name "-j" jobs "@install" "@runtest" {with-test}] 12 | ] 13 | depends: [ 14 | "ocaml" {>= "4.08.0"} 15 | "dune" {>= "2.5"} 16 | "ounit2" {with-test} 17 | ] 18 | description: """ 19 | A package dependency resolver based on a SAT solver. This was originally 20 | written for the 0install package manager, but is now generic and is also used 21 | as a solver backend for opam. 22 | The SAT solver is based on MiniSat (http://minisat.se/Papers.html) and 23 | the application to package management is based on OPIUM (Optimal Package 24 | Install/Uninstall Manager). 0install-solver uses a (novel?) strategy to find 25 | the optimal solution extremely quickly (even for a SAT-based solver). 26 | """ 27 | -------------------------------------------------------------------------------- /src/support/env.ml: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2013, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | type t = string XString.Map.t 6 | 7 | type name = string 8 | 9 | let empty = XString.Map.empty 10 | 11 | let parse_binding line = 12 | match Str.bounded_split_delim XString.re_equals line 2 with 13 | | [key; value] -> (key, value) 14 | | _ -> failwith (Printf.sprintf "Invalid environment mapping '%s'" line) 15 | 16 | let of_array = 17 | XString.Map.empty 18 | |> Array.fold_left @@ fun acc line -> 19 | let key, value = parse_binding line in 20 | XString.Map.add key value acc 21 | 22 | let put = XString.Map.add 23 | let unset = XString.Map.remove 24 | let get = XString.Map.find_opt 25 | 26 | let get_exn k t = 27 | match get k t with 28 | | Some v -> v 29 | | None -> Safe_exn.failf "Environment variable %S not set" k 30 | 31 | let to_array t = 32 | let len = XString.Map.cardinal t in 33 | let arr = Array.make len "" in 34 | let item_to_array key value i = (arr.(i) <- key ^ "=" ^ value; i + 1) in 35 | let check_len = XString.Map.fold item_to_array t 0 in 36 | assert (len = check_len); 37 | arr 38 | -------------------------------------------------------------------------------- /src/gui_gtk/gtk_common.ml: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2013, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** To be opened by all GTK modules. *) 6 | 7 | (** Connect a signal handler, ignoring the resulting signal ID. 8 | * This avoids having to use [|> ignore] everywhere. *) 9 | let (==>) (signal:(callback:_ -> GtkSignal.id)) callback = 10 | ignore (signal ~callback) 11 | 12 | (** Create a widget and ignore it. This is useful for decorations (e.g. labels) 13 | * to avoid using the generic [ignore], which can ignore other things too. *) 14 | let ignore_widget : #GObj.widget -> unit = ignore 15 | 16 | (** Append a column and ignore the returned column ID. *) 17 | let append_column (tv:GTree.view) (col:GTree.view_column) = 18 | ignore (tv#append_column col) 19 | 20 | (** Append a notebook page and ignore the returned page number. *) 21 | let append_page (nb:GPack.notebook) ?tab_label page = 22 | ignore (nb#append_page ?tab_label page) 23 | 24 | let with_insensitive (widget:#GObj.widget) f = 25 | widget#misc#set_sensitive false; 26 | Lwt.finalize f 27 | (fun () -> widget#misc#set_sensitive true; Lwt.return ()) 28 | -------------------------------------------------------------------------------- /src/zeroinstall/sigs.mli: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2013, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** Some useful abstract module types. *) 6 | 7 | open Support.Common 8 | 9 | type iface_uri = string 10 | (** A URI used to identify an interface. 11 | Uses only plain URI characters, unicode chars, spaces, etc are %-escaped. *) 12 | 13 | type feed_url = string 14 | 15 | module type SELECTIONS = Zeroinstall_solver.S.SELECTIONS 16 | 17 | module type SEARCH_PATH = sig 18 | type config 19 | type key 20 | 21 | val all_paths : key -> config -> filepath list 22 | (** [all_paths key config] is all configured paths for [key], in search order, 23 | whether they exist currently or not. *) 24 | 25 | val first : key -> config -> filepath option 26 | (** [first key config] is the first existing path of [key] in the search path. *) 27 | 28 | val save_path : key -> config -> filepath 29 | (** [save_path key config] creates a directory for [key] in the first directory in 30 | the search path (if it doesn't yet exist) and returns the path of the 31 | [key] within it (which may not yet exist). *) 32 | end 33 | -------------------------------------------------------------------------------- /src/zeroinstall/packagekit_stubs.mli: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2016, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** There are several different versions of the PackageKit API. 6 | This module provides a consistent interface to them. *) 7 | 8 | module Transaction : sig 9 | type t 10 | 11 | val monitor : t -> switch:Lwt_switch.t -> int32 React.signal Lwt.t 12 | (** [monitor t ~switch] is a signal giving the percentage complete for the transaction. *) 13 | 14 | val cancel : t -> unit Lwt.t 15 | (** [cancel t] asks PackageKit to cancel the transaction. *) 16 | 17 | val install_packages : t -> string list -> unit Lwt.t 18 | (** [install_packages t ids] installs the packages with the given package IDs. *) 19 | end 20 | 21 | type t 22 | val connect : Support.Locale.lang_spec -> [`Ok of t | `Unavailable of string] Lwt.t 23 | val summaries : t -> package_names:string list -> (package_id:string -> summary:string -> unit) -> unit Lwt.t 24 | val sizes : t -> package_ids:string list -> (package_id:string -> size:int64 -> unit) -> unit Lwt.t 25 | val run_transaction : t -> (Lwt_switch.t -> Transaction.t -> unit Lwt.t) -> unit Lwt.t 26 | -------------------------------------------------------------------------------- /src/tests/data/runnable/ArgList.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Runnable 4 | test script that needs a runner 5 | 6 | 7 | 8 | 9 | arg-for-runner 10 | 11 | -X 12 | ${item} 13 | 14 | 15 | command-arg 16 | 17 | ${item} 18 | 19 | 20 | ${foo} 21 | 22 | -- 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /src/cli/secureadd.ml: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2013, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** The "0store-secure-add" command *) 6 | 7 | open Zeroinstall.General 8 | open Support 9 | 10 | module Manifest = Zeroinstall.Manifest 11 | module U = Support.Utils 12 | 13 | let handle config args = 14 | (* Make all system files world-readable, even if the default system umask is more strict. *) 15 | ignore (Unix.umask 0o022); 16 | 17 | let system = config.system in 18 | 19 | if system#getenv "ENV_NOT_CLEARED" <> None then ( 20 | Safe_exn.failf "Environment not cleared. Check your sudoers file." 21 | ) else if system#getenv "HOME" = Some "Unclean" then ( 22 | Safe_exn.failf "$HOME not set. Check your sudoers file has 'always_set_home' turned on for zeroinst." 23 | ) else ( 24 | match args with 25 | | [digest] -> 26 | let digest = Manifest.parse_digest digest in 27 | let manifest_data = U.read_file system ".manifest" in 28 | Manifest.copy_tree_with_verify system "." "/var/cache/0install.net/implementations" manifest_data digest 29 | | _ -> Safe_exn.failf "Usage: 0store-secure-add DIGEST" 30 | ) 31 | -------------------------------------------------------------------------------- /src/dune: -------------------------------------------------------------------------------- 1 | (executable 2 | (public_name 0install) 3 | (name static_0install) 4 | (modules static_0install) 5 | (ocamlopt_flags -linkall) ; Needed for the GUI plugin 6 | (ocamlc_flags -linkall -custom) 7 | (link_flags (:include support/extra_objects.sexp)) 8 | (package 0install) 9 | (libraries zeroinstall_cli zeroinstall support)) 10 | 11 | (executable 12 | (public_name 0install-runenv) 13 | (package 0install) 14 | (name runenv) 15 | (modules runenv) 16 | (link_flags (:include support/extra_objects.sexp)) 17 | (libraries zeroinstall_cli zeroinstall support)) 18 | 19 | (install 20 | (package 0install) 21 | (section bin) 22 | (files 23 | (static_0install.exe as 0launch) 24 | (static_0install.exe as 0store) 25 | (static_0install.exe as 0store-secure-add) 26 | (static_0install.exe as 0desktop) 27 | (static_0install.exe as 0alias) 28 | )) 29 | 30 | (install 31 | (package 0install) 32 | (section man) 33 | (files 34 | (0launch.1 as man1/0launch.1) 35 | (0store-secure-add.1 as man1/0store-secure-add.1) 36 | (0store.1 as man1/0store.1) 37 | (0desktop.1 as man1/0desktop.1) 38 | (0install.1 as man1/0install.1) 39 | )) 40 | -------------------------------------------------------------------------------- /share/metainfo/0install.appdata.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 0install.desktop 5 | CC0-1.0 6 | LGPL-2.1+ 7 | 0install 8 | Run or manage Zero Install programs 9 | 10 |

11 | Zero Install is a decentralised cross-distribution software installation system. 12 |

13 |

14 | Features include full support for shared libraries (with a SAT solver for dependency resolution), 15 | sharing between users, and integration with native platform package managers. 16 |

17 |

18 | It supports both binary and source packages, and works on Linux, OS X, Unix and Windows systems. 19 | It is fully Open Source. 20 |

21 |
22 | 23 | http://0install.net/screens/0install-0desktop.png 24 | 25 | http://0install.net 26 | zero-install-devel@lists.sourceforge.net 27 | 28 |
29 | -------------------------------------------------------------------------------- /src/support/basedir.mli: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2013, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** XDG Base Directory support, for locating caches, configuration, etc *) 6 | 7 | open Common 8 | 9 | type basedirs = { 10 | data: filepath list; 11 | cache: filepath list; 12 | config: filepath list; 13 | } 14 | 15 | (** Get configuration using [ZEROINSTALL_PORTABLE_BASE] (if set), or the platform default, 16 | * modified by any [XDG_*] variables which are set. *) 17 | val get_default_config : #system -> basedirs 18 | 19 | (** [load_first system relpath search_path] returns the first configuration path (base +/ relpath) that exists 20 | * from the base paths in [search_path]. *) 21 | val load_first : #filesystem -> filepath -> filepath list -> filepath option 22 | 23 | (** [save_path system relpath search_path] creates the directory [List.hd search_path +/ relpath] (and 24 | * any missing parents) and returns its path. *) 25 | val save_path : #filesystem -> filepath -> filepath list -> filepath 26 | 27 | (** Get the home directory (normally [$HOME]). If we're running as root and $HOME isn't owned by root 28 | * (e.g. under sudo) then return root's real home directory instead. *) 29 | val get_unix_home : system -> filepath 30 | -------------------------------------------------------------------------------- /src/zeroinstall/archive.mli: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2013, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** Unpacking archives *) 6 | 7 | type mime_type = string 8 | 9 | (* Guess the MIME type from the URL's extension. 10 | * @raise Safe_exn.T if the extension is unknown. *) 11 | val type_from_url : string -> mime_type 12 | 13 | (* Check we have the needed software to extract from an archive of the given type. 14 | * @raise Safe_exn.T with a suitable message if not. *) 15 | val check_type_ok : Support.Common.system -> mime_type -> unit 16 | 17 | (** Unpack [archive] to a temporary directory and then move things into [destdir], checking that we're not following symlinks at each 18 | stage. Use this when you want to unpack an archive into a directory which already has stuff in it. 19 | @param extract treat this subdirectory of [archive] as the root to unpack. 20 | @param tmpdir a directory on the same filesystem as [destdir] in which to create temporary directories. 21 | *) 22 | val unpack_over : ?extract:Support.Common.filepath -> General.config -> 23 | archive:Support.Common.filepath -> tmpdir:Support.Common.filepath -> destdir:Support.Common.filepath -> 24 | mime_type:mime_type -> unit Lwt.t 25 | -------------------------------------------------------------------------------- /src/zeroinstall/distro_cache.mli: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2014, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** A simple cache for storing key-value pairs on disk. Distributions may wish to use this to record the 6 | version(s) of each distribution package currently installed. *) 7 | 8 | open Support.Common 9 | 10 | type t 11 | 12 | type package_name = string 13 | type entry = Version.t * Arch.machine option 14 | 15 | val create_eager : General.config -> cache_leaf:string -> source:filepath -> regenerate:((package_name -> entry -> unit) -> unit) -> t 16 | (* [create_eager config ~cache_leaf ~source ~regenerate] creates a new cache backed by [cache_leaf]. 17 | Whenever [source] changes, everything in the cache is assumed to be invalid and [regenerate] 18 | is called. It should call the provided function once for each entry. *) 19 | 20 | val create_lazy : General.config -> cache_leaf:string -> source:filepath -> if_missing:(package_name -> entry list) -> t 21 | (** Similar to [create_eager], but the cache is repopulated lazily by calling [if_missing] for a single package 22 | when it is requested and not present. *) 23 | 24 | val get : t -> package_name -> entry list * Distro.quick_test option 25 | (** Look up an item in the cache. *) 26 | -------------------------------------------------------------------------------- /src/zeroinstall/recipe.mli: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2013, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** Handling , and similar elements *) 6 | 7 | type archive_options = { 8 | dest : string option; 9 | extract : string option; 10 | start_offset : Int64.t; 11 | mime_type : string option; 12 | } 13 | 14 | module FileDownload : sig 15 | type t = { 16 | dest : string; 17 | executable : bool; 18 | } 19 | end 20 | 21 | type download_type = 22 | | FileDownload of FileDownload.t 23 | | ArchiveDownload of archive_options 24 | 25 | type download = { 26 | url : string; 27 | size : Int64.t option; (* may be None when using the mirror *) 28 | download_type : download_type; 29 | } 30 | 31 | type rename = { 32 | rename_source : string; 33 | rename_dest : string; 34 | } 35 | 36 | type remove = { 37 | remove : string; 38 | } 39 | 40 | type recipe_step = 41 | | DownloadStep of download 42 | | RenameStep of rename 43 | | RemoveStep of remove 44 | 45 | type t = recipe_step list 46 | 47 | val parse_retrieval_method : [`Archive | `File | `Recipe] Element.t -> t option 48 | 49 | val recipe_requires_network : t -> bool 50 | val get_download_size : t -> Int64.t 51 | 52 | val get_mirror_download : string -> t 53 | -------------------------------------------------------------------------------- /src/support/base64.ml: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2017, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | exception Invalid_char 6 | 7 | let decode s i = 8 | match s.[i] with 9 | | 'A'..'Z' as c -> Char.code c - 65 10 | | 'a'..'z' as c -> Char.code c - 97 + 26 11 | | '0'..'9' as c -> Char.code c - 48 + 52 12 | | '+' -> 62 13 | | '/' -> 63 14 | | '=' when i = String.length s - 1 -> raise End_of_file 15 | | '=' when i = String.length s - 2 && s.[i + 1] = '=' -> raise End_of_file 16 | | _ -> raise Invalid_char 17 | | exception _ when i = String.length s -> raise End_of_file 18 | 19 | (* Every 6 bits of plain text become 8 bits of encoded data, so 20 | every 3 bytes (24 bits) of plain text become 4 bytes (32 bits) of output. *) 21 | let str_decode s = 22 | let buf = Buffer.create (3 * ((String.length s + 3) / 4)) in 23 | let add c = Buffer.add_char buf (Char.chr c) in 24 | let rec aux i = 25 | let s1 = decode s i in 26 | let s2 = decode s (i + 1) in 27 | add @@ (s1 lsl 2) lor (s2 lsr 4); 28 | let s3 = decode s (i + 2) in 29 | add @@ ((s2 land 0xf) lsl 4) lor (s3 lsr 2); 30 | let s4 = decode s (i + 3) in 31 | add @@ ((s3 land 0x3) lsl 6) lor s4; 32 | aux (i + 4) 33 | in 34 | try aux 0 35 | with End_of_file -> Buffer.contents buf 36 | -------------------------------------------------------------------------------- /src/gui_gtk/unsorted_list.mli: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2013, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** A GTK list store with its own types *) 6 | 7 | (* When displaying items in a TreeView/IconView, we often have two models: an 8 | * underlying model and a sorted view of it, which is what the widget displays. 9 | * It's very important not to confuse the iterators of one model with those of 10 | * the other, or you may act on the wrong data. 11 | * 12 | * For example, to delete a row you need to call the delete operation on the underlying model, 13 | * using an underlying iterator. But the TreeView's get_selected_rows returns iterators in the 14 | * sorted model. 15 | * 16 | * This module isolates the underlying model and its iterators from the rest of the code, so 17 | * mixups aren't possible. 18 | *) 19 | type t 20 | type iter 21 | val list_store : GTree.column_list -> t 22 | val clear : t -> unit 23 | val model_sort : t -> GTree.model_sort 24 | val get_iter_first : t -> iter option 25 | val set : t -> row:iter -> column:'a GTree.column -> 'a -> unit 26 | val get : t -> row:iter -> column:'a GTree.column -> 'a 27 | val remove : t -> iter -> bool 28 | val convert_iter_to_child_iter : GTree.model_sort -> Gtk.tree_iter -> iter 29 | val append : t -> iter 30 | val iter_next : t -> iter -> bool 31 | -------------------------------------------------------------------------------- /.travis-test-compile.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo Display: $DISPLAY 3 | set -eux 4 | export DISPLAY= 5 | 6 | if [ -d 0compile ]; then 7 | # Already did this test 8 | exit 0 9 | fi 10 | 11 | eval `opam config env` 12 | 13 | mkdir -p ~/.config/0install.net/injector 14 | cat > ~/.config/0install.net/injector/trustdb.xml < 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | EOF 25 | 26 | make all 27 | sudo make install 28 | 0install add-feed http://0install.net/tools/0install.xml dist/0install/feed.xml 29 | git clone https://github.com/0install/0compile.git -b use-ocaml 30 | 0install select -c 0compile/0compile.xml 31 | 32 | # Autocompile doesn't use the new solver, so test with manual build for now 33 | 0install run -c 0compile/0compile.xml -v setup http://0install.net/tests/GNU-Hello.xml 34 | cd GNU-Hello 35 | 0install run -c ../0compile/0compile.xml -v build 36 | 37 | #0install run -c 0compile/0compile.xml autocompile http://0install.net/tests/GNU-Hello.xml 38 | #0install run -c http://0install.net/tests/GNU-Hello.xml 39 | -------------------------------------------------------------------------------- /src/support/stream.ml: -------------------------------------------------------------------------------- 1 | module LList = struct 2 | type 'a item = Nil | Cons of 'a * 'a t 3 | and 'a t = 'a item Lazy.t 4 | 5 | let rec of_list = function 6 | | [] -> lazy Nil 7 | | x :: xs -> lazy (Cons (x, of_list xs)) 8 | 9 | let rec from fn = 10 | lazy ( 11 | match fn () with 12 | | None -> Nil 13 | | Some x -> Cons (x, from fn) 14 | ) 15 | end 16 | 17 | type 'a t = { 18 | mutable next : 'a LList.t; 19 | mutable count : int; 20 | } 21 | 22 | exception Failure 23 | 24 | let of_lazy x = { next = x; count = 0 } 25 | 26 | let of_list x = of_lazy (LList.of_list x) 27 | 28 | let count t = t.count 29 | 30 | let empty t = 31 | match t.next with 32 | | lazy Nil -> () 33 | | _ -> raise Failure 34 | 35 | let from fn = of_lazy (LList.from fn) 36 | 37 | let next t = 38 | match Lazy.force t.next with 39 | | Nil -> raise Failure 40 | | Cons (x, next) -> 41 | t.next <- next; 42 | t.count <- t.count + 1; 43 | x 44 | 45 | let junk t = ignore (next t) 46 | 47 | let npeek n t = 48 | let rec aux (next : _ LList.t) = function 49 | | 0 -> [] 50 | | i -> 51 | match Lazy.force next with 52 | | Nil -> [] 53 | | Cons (x, next) -> 54 | x :: aux next (i - 1) 55 | in 56 | aux t.next n 57 | 58 | let peek t = 59 | match Lazy.force t.next with 60 | | Nil -> None 61 | | Cons (x, _) -> Some x 62 | -------------------------------------------------------------------------------- /src/zeroinstall/http.mli: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2019, Thomas Leonard 2 | See the README file for details, or visit http://0install.net. *) 3 | 4 | (** Generic interface for HTTP libraries (ocurl or ocaml-tls) *) 5 | 6 | val escape : string -> string 7 | (** [escape s] %-escapes unsafe characters in [s] so that it can be used in a URL's path component. *) 8 | 9 | val variant : string 10 | (** Describes this HTTP-backend. Displayed in the output of "0install --version". *) 11 | 12 | module Connection : sig 13 | type t 14 | 15 | val create : unit -> t 16 | 17 | val release : t -> unit 18 | 19 | val get : 20 | cancelled:bool ref -> 21 | ?size:int64 -> 22 | ?modification_time:float -> 23 | ?start_offset:int64 -> 24 | progress:(int64 * int64 option * bool -> unit) -> 25 | t -> 26 | out_channel -> 27 | string -> 28 | [ `Aborted_by_user 29 | | `Network_failure of string 30 | | `Redirect of string 31 | | `Success 32 | | `Unmodified ] Lwt.t 33 | (** @param expected size (if known), including the [start_offset] skipped bytes *) 34 | end 35 | 36 | val post : 37 | data:string -> 38 | string -> 39 | (string, (string * string)) result Lwt.t 40 | (** [post ~data url] sends [data] to [url] and returns the body of the response from the server on success. 41 | On failure, it returns a suitable error message and the body from the server. *) 42 | -------------------------------------------------------------------------------- /0install.opam: -------------------------------------------------------------------------------- 1 | opam-version: "2.0" 2 | synopsis: "Decentralised installation system" 3 | maintainer: "talex5@gmail.com" 4 | license: "LGPL-2.1-or-later" 5 | authors: "zero-install-devel@lists.sourceforge.net" 6 | homepage: "https://0install.net/" 7 | bug-reports: "https://github.com/0install/0install/issues" 8 | dev-repo: "git+https://github.com/0install/0install.git" 9 | doc: "https://0install.github.io/0install/" 10 | build: [ 11 | ["dune" "build" "-p" name "-j" jobs "@install" "@runtest" {with-test}] 12 | ] 13 | depends: [ 14 | "ocaml" {>= "4.08.0"} 15 | "0install-solver" 16 | "yojson" {>= "1.7.0"} 17 | "xmlm" 18 | "ounit2" {with-test} 19 | "lwt" 20 | "lwt_react" 21 | "obus" {os != "macos" & os-family != "windows"} 22 | "ocurl" {>= "0.7.9"} 23 | "sha" {>= "1.9"} 24 | "dune" {>= "2.5"} 25 | ] 26 | depexts: [ 27 | ["gnupg" "unzip"] {os-family = "debian"} 28 | ["gnupg" "unzip"] {os-distribution = "alpine"} 29 | ["gnupg"] {os = "macos" & os-distribution = "homebrew"} 30 | ] 31 | description: """ 32 | Zero Install is a decentralised cross-distribution software installation system. 33 | Other features include full support for shared libraries (with a SAT solver for 34 | dependency resolution), sharing between users, and integration with native platform 35 | package managers. It supports both binary and source packages, and works on Linux, 36 | macOS, Unix and Windows systems.""" 37 | -------------------------------------------------------------------------------- /src/support/safe_exn.ml: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2018, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | type payload = (string * string list ref) 6 | 7 | exception T of payload 8 | 9 | let msg = fst 10 | 11 | let v ?(ctx=[]) f = 12 | f |> Format.kasprintf @@ fun msg -> 13 | T (msg, ref ctx) 14 | 15 | let failf ?(ctx=[]) fmt = 16 | fmt |> Format.kasprintf @@ fun msg -> 17 | raise (T (msg, ref ctx)) 18 | 19 | let reraise_with ex fmt = 20 | fmt |> Format.kasprintf @@ fun context -> 21 | begin match ex with 22 | | T (_, old_contexts) -> old_contexts := context :: !old_contexts 23 | | _ -> Printf.eprintf "warning: Attempt to add note '%s' to non-Safe_exn.T!" context 24 | end; 25 | raise ex 26 | 27 | let with_info note f = 28 | Lwt.catch f 29 | (function 30 | | T (_, old_contexts) as ex -> 31 | note @@ Format.kasprintf (fun x -> old_contexts := x :: !old_contexts); 32 | raise ex 33 | | ex -> Lwt.fail ex 34 | ) 35 | 36 | let pp_ctx_line f line = 37 | Format.fprintf f "@,%s" line 38 | 39 | let pp f (msg, context) = 40 | Format.fprintf f "@[%s%a@]" msg 41 | (Format.pp_print_list ~pp_sep:(fun _ _ -> ()) pp_ctx_line) (List.rev !context) 42 | 43 | let to_string = function 44 | | T e -> Some (Format.asprintf "%a" pp e) 45 | | _ -> None 46 | 47 | let () = Printexc.register_printer to_string 48 | -------------------------------------------------------------------------------- /src/0desktop.1: -------------------------------------------------------------------------------- 1 | .TH 0DESKTOP 1 "2013" "Thomas Leonard" "" 2 | .SH NAME 3 | 0desktop \(em add programs to the desktop environment 4 | 5 | .SH SYNOPSIS 6 | 7 | .B 0destkop 8 | [ \fBURI\fP ] 9 | 10 | .SH DESCRIPTION 11 | .PP 12 | 0desktop can be used to create launchers for 0install applications in 13 | desktop environments supporting the freedesktop.org menu specification (e.g. 14 | GNOME and KDE). 15 | 16 | .PP 17 | If the URI of a 0install application is given, this application is added. 18 | On success, a launcher is added to the user's menu which, when invoked, runs 19 | the application using the command "0launch URI". 20 | 21 | .PP 22 | Without a URI, a dialog box is displayed listing the user's current applications and 23 | allowing new ones to be added. 24 | 25 | .SH FILES 26 | 27 | .IP "~/.local/share/applications" 28 | Default directory in which the .desktop file for the new launcher is created. 29 | 30 | .SH LICENSE 31 | .PP 32 | Copyright (C) 2013 Thomas Leonard. 33 | 34 | .PP 35 | You may redistribute copies of this program under the terms of the GNU Lesser General Public License. 36 | 37 | .SH BUGS 38 | .PP 39 | Please report bugs to the developer mailing list: 40 | 41 | http://0install.net/support.html 42 | 43 | .SH AUTHOR 44 | .PP 45 | Zero Install was created by Thomas Leonard. 46 | 47 | .SH SEE ALSO 48 | 0install(1) 49 | .PP 50 | The 0install web-site: 51 | 52 | .B http://0install.net 53 | -------------------------------------------------------------------------------- /src/tests/data/6FCF121BE2390E0B.gpg: -------------------------------------------------------------------------------- 1 | -----BEGIN PGP PUBLIC KEY BLOCK----- 2 | Version: GnuPG v1.4.1 (GNU/Linux) 3 | 4 | mQGiBD9VwZERBADxb0hM4yKveb/G0NzuznadLsMyvXvgcPHC/gFWEL3JV7gefEal 5 | RhKOu6VzmBjaC6a2xsZ23//z+p1uvCq4SW7KCrxZAXmIdL4FnYd8n+IU8AgnlmSh 6 | qbpjuMndbC8PV/leettqUgrBZbMbnbeM0M9VDndtN6/9gesExKELzK0P/wCgjv+G 7 | 6G3bgW4qPuEisfZ+DnO9XQ8EAI/VTM4Y1ZN7Yd3WZwWWlk7OkayxWRzjoRsfgSTL 8 | AXTItnyubclKbJrO2HGHD508yd4eV0KSD70Pu3DNi8OTDk6auFWNEFxTgi5GSfBY 9 | /6ghCJLS0wKtA/XkN2HvWf4MDOLcls+lKzJ1sbNFfGbU2kgNhVZQn+K4yC89fSBb 10 | CCarA/9MVnqECzJ0LitbVpEWYvWrLiqyDJMDBu/bVHF8ZsjWofXGLsjhCLeX1QZB 11 | mosehmYn4KsihnUJE00Y5G4VdPAKgFqAVhlDldJCl6cBu3VaiGjHLNuyJm/FZjfP 12 | wx29PxYuuZKtyh+ax6ncsNDW/Ac8uVgjee29KH/UGZIfu2pqlLQcVGVzdGluZyA8 13 | MGluc3RhbGxAbG9jYWxob3N0PoheBBMRAgAeBQI/VcGRAhsDBgsJCAcDAgMVAgMD 14 | FgIBAh4BAheAAAoJEG/PEhviOQ4L/cUAnA2HlKWwafeKUdiHQ+P2LPKKcNnFAKCF 15 | 4Y317QsTpF4nfxJPIqFW6CkVP7kBDQQ/VcGSEAQA4JFAkfn8s3kxCwnWrV80ie79 16 | QKvRYrshMlmqK4g38vMi5J2A9ZDV7BpgX6kLn3nhemNI+FECsD6f6gwFsoq5Nx6p 17 | KWZn1x/nzCccdfAvlXsmruZCE5ZMzeK3syQx+b5MHIZ8Ab8cy0PYbzAM3inm8q2C 18 | IOIFeDP4c/UxbzZFeocAAwUD/0sUksf9adOtDuOxt5ywH8pjlECrTVkm1//m0zHA 19 | 3fuFUyakpfUWhToA7d39Z2AzZp16RbRq+MueBHSmH3VjtP3HVBR35qhlexk+z5fh 20 | AMIxttimB3SHqsnPi04N25hPgdzefB3jsfKYPEbTzFJEmsHkk7q7r4sT2cMeAEi/ 21 | D/F6iEkEGBECAAkFAj9VwZICGwwACgkQb88SG+I5DgtWIQCfYbMHDZkeEBrxPRbx 22 | TILMJAHrMUcAn2/FCRQx7NUvKQxmP9MoQTCvTRuO 23 | =rIrp 24 | -----END PGP PUBLIC KEY BLOCK----- 25 | -------------------------------------------------------------------------------- /src/cli/import.ml: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2013, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** The "0install import" command *) 6 | 7 | open Options 8 | open Zeroinstall.General 9 | open Support 10 | open Support.Common 11 | 12 | module Q = Support.Qdom 13 | module FeedAttr = Zeroinstall.Constants.FeedAttr 14 | module U = Support.Utils 15 | 16 | let import_feed options arg = 17 | let tools = options.tools in 18 | let system = options.config.system in 19 | 20 | if not (system#file_exists arg) then 21 | Safe_exn.failf "File '%s' does not exist" arg; 22 | 23 | log_info "Importing from file '%s'" arg; 24 | let xml = U.read_file system arg in 25 | let root = `String (0, xml) |> Xmlm.make_input |> Q.parse_input (Some arg) in 26 | let url = ZI.get_attribute FeedAttr.uri root in 27 | let parsed_url = match Zeroinstall.Feed_url.parse_non_distro url with 28 | | `Remote_feed _ as url -> url 29 | | `Local_feed _ -> Safe_exn.failf "Invalid URI '%s' on feed" url in 30 | 31 | log_info "Importing feed %s" url; 32 | 33 | Lwt_main.run ((tools#make_fetcher tools#ui#watcher)#import_feed parsed_url xml) 34 | 35 | let handle options flags args = 36 | Support.Argparse.iter_options flags (function 37 | | #common_option as o -> Common_options.process_common_option options o 38 | ); 39 | if args = [] then raise (Support.Argparse.Usage_error 1); 40 | args |> List.iter (import_feed options) 41 | -------------------------------------------------------------------------------- /src/zeroinstall/impl_provider.mli: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2013, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** Provides implementation candidates to the solver. *) 6 | 7 | open Support 8 | 9 | (** Why we rejected an implementation *) 10 | type rejection_reason 11 | 12 | (** Why we picked one implementation over another *) 13 | type preference_reason 14 | 15 | val describe_problem : _ Impl.t -> rejection_reason -> string 16 | val describe_preference : preference_reason -> string 17 | 18 | type candidates = { 19 | replacement : Sigs.iface_uri option; 20 | impls : Impl.generic_implementation list; 21 | rejects : (Impl.generic_implementation * rejection_reason) list; 22 | compare : Impl.generic_implementation -> Impl.generic_implementation -> int * preference_reason; 23 | feed_problems : string list; 24 | } 25 | 26 | class type impl_provider = 27 | object 28 | (** Return all the implementations of this interface (including from feeds). 29 | Most preferred implementations should come first. *) 30 | method get_implementations : Sigs.iface_uri -> source:bool -> candidates 31 | 32 | (** Should the solver consider this dependency? *) 33 | method is_dep_needed : Impl.dependency -> bool 34 | 35 | method extra_restrictions : Impl.restriction XString.Map.t 36 | end 37 | 38 | class default_impl_provider : General.config -> Feed_provider.feed_provider -> Scope_filter.t -> impl_provider 39 | -------------------------------------------------------------------------------- /src/zeroinstall/fetch.mli: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2013, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | type fetch_feed_response = 6 | [ `Update of ([`Feed] Element.t * fetch_feed_response Lwt.t option) (* Use this version (but a better version may come soon) *) 7 | | `Aborted_by_user (* Abort silently (no need to notify the user) *) 8 | | `Problem of (string * fetch_feed_response Lwt.t option) (* Report a problem (but may still succeed later) *) 9 | | `No_update ] (* Use the previous version *) 10 | 11 | class type fetcher = 12 | object 13 | method download_and_import_feed : Feed_url.remote_feed -> fetch_feed_response Lwt.t 14 | method download_impls : Impl.existing Impl.t list -> [ `Success | `Aborted_by_user ] Lwt.t 15 | 16 | (** [import_feed url xml] checks the signature on [xml] and imports it into the cache if trusted. 17 | * If not trusted, it confirms with the user first, downloading any missing keys first. *) 18 | method import_feed : Feed_url.remote_feed -> string -> unit Lwt.t 19 | 20 | (** Download the icon and add it to the disk cache as the icon for the given feed. *) 21 | method download_icon : Feed_url.non_distro_feed -> string -> unit Lwt.t 22 | 23 | method ui : Progress.watcher 24 | end 25 | 26 | (** Create a fetcher for this platform. *) 27 | val make : General.config -> Trust.trust_db -> Distro.t -> Downloader.download_pool -> #Progress.watcher -> fetcher 28 | -------------------------------------------------------------------------------- /src/support/locale.mli: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2013, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** Support for internationalisation. *) 6 | 7 | (* There is an ocaml-gettext package, but it's hard to install and seems unmaintained. As we don't need much, 8 | here's a simple implementation. Note: encodings are ignored; we only support UTF-8. *) 9 | 10 | type lang_spec = (string * string option) (* Langauge, country *) 11 | 12 | module LangMap : (Map.S with type key = lang_spec) 13 | 14 | val parse_lang : string -> lang_spec option 15 | 16 | val format_lang : lang_spec -> string 17 | 18 | (** Get the user's preferred language(s), most preferred first. The default is always included. 19 | See: http://www.gnu.org/software/gettext/manual/html_mono/gettext.html#The-LANGUAGE-variable *) 20 | val get_langs : ?default:lang_spec -> #Common.environment -> lang_spec list 21 | 22 | (* Converts a list of languages (most preferred first) to a map from languauges to scores. 23 | * For example, the list ["en_US", "en_GB", "fr"] produces the scores: 24 | * en_US -> 6 25 | * en_GB -> 4 26 | * en -> 3 27 | * fr -> 1 28 | *) 29 | val score_langs : lang_spec list -> int LangMap.t 30 | 31 | (* Look up a language string (e.g. from an xml:lang attribute) using a ranking from [score_langs]. 32 | * If lang is None, we assume English. Returns 0 if there is no match, or a positive number *) 33 | val score_lang : int LangMap.t -> string option -> int 34 | -------------------------------------------------------------------------------- /src/zeroinstall/ui.mli: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2013, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** Common types for user interface callbacks *) 6 | 7 | type select_mode = [ 8 | | `Select_only (* only download feeds, not archives; display "Select" in GUI *) 9 | | `Download_only (* download archives too; refresh if stale feeds; display "Download" in GUI *) 10 | | `Select_for_run (* download archives; update stale in background; display "Run" in GUI *) 11 | ] 12 | 13 | class type ui_handler = 14 | object 15 | (** Choose (and possibly download) a set of implementations. 16 | * @param systray is used during background updates - just show an icon in the systray if possible 17 | *) 18 | method run_solver : 19 | < config : General.config; distro : Distro.t; make_fetcher : Progress.watcher -> Fetch.fetcher; .. > -> 20 | ?systray:bool -> 21 | select_mode -> 22 | Requirements.t -> 23 | refresh:bool -> 24 | [`Aborted_by_user | `Success of Selections.t] Lwt.t 25 | 26 | (** Display the Preferences dialog. Resolves when dialog is closed. 27 | * @return None if we don't have a GUI available. *) 28 | method show_preferences : unit Lwt.t option 29 | 30 | method open_app_list_box : unit Lwt.t 31 | 32 | method open_add_box : Sigs.feed_url -> unit Lwt.t 33 | 34 | method open_cache_explorer : unit Lwt.t 35 | 36 | method watcher : Progress.watcher 37 | end 38 | -------------------------------------------------------------------------------- /src/zeroinstall/general.ml: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2013, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** Useful constants and utilities to be [open]ed by all modules. *) 6 | 7 | (** {2 Types} *) 8 | 9 | open Support.Common 10 | 11 | type network_use = Full_network | Minimal_network | Offline 12 | 13 | type config = { 14 | paths : Paths.t; 15 | mutable stores: filepath list; 16 | mutable extra_stores: filepath list; (* (subset of stores; passed to Python slave with --with-store) *) 17 | abspath_0install: filepath; 18 | 19 | system : Support.Common.system; 20 | 21 | mutable mirror : string option; 22 | mutable key_info_server : string option; 23 | mutable freshness: float option; 24 | mutable dry_run : bool; 25 | mutable network_use : network_use; 26 | mutable help_with_testing : bool; 27 | mutable auto_approve_keys : bool; 28 | 29 | langs : int Support.Locale.LangMap.t; 30 | } 31 | 32 | (** {2 Useful constants} *) 33 | 34 | let hours = 60. *. 60. (* Seconds per hour *) 35 | 36 | let days = 24. *. hours (* Seconds per day *) 37 | 38 | (** {2 The 0install XML namespace} *) 39 | 40 | module ZI_NS = struct 41 | let ns = "http://zero-install.sourceforge.net/2004/injector/interface" 42 | let prefix_hint = "zi" 43 | end 44 | 45 | module ZI = Support.Qdom.NsQuery (ZI_NS) 46 | 47 | module COMPILE_NS = struct 48 | let ns = "http://zero-install.sourceforge.net/2006/namespaces/0compile" 49 | let prefix_hint = "compile" 50 | end 51 | -------------------------------------------------------------------------------- /src/zeroinstall/constants.ml: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2013, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** Some constant strings used in the XML (to avoid typos) *) 6 | 7 | module FeedAttr = 8 | struct 9 | let id = "id" 10 | let command = "command" 11 | let main = "main" 12 | let self_test = "self-test" 13 | let stability = "stability" 14 | let value_testing = "testing" 15 | let importance = "importance" 16 | let version = "version" 17 | let version_modifier = "version-modifier" (* This is stripped out and moved into attr_version *) 18 | let released = "released" 19 | let os= "os" 20 | let use = "use" 21 | let local_path = "local-path" 22 | let lang = "lang" 23 | let langs = "langs" 24 | let interface = "interface" 25 | let src = "src" 26 | let if_0install_version = "if-0install-version" 27 | let distribution = "distribution" 28 | let uri = "uri" 29 | let from_feed = "from-feed" 30 | let doc_dir = "doc-dir" 31 | let package = "package" 32 | let quick_test_file = "quick-test-file" 33 | let quick_test_mtime = "quick-test-mtime" 34 | let license = "license" 35 | end 36 | 37 | module FeedConfigAttr = 38 | struct 39 | let user_stability = "user-stability" 40 | end 41 | 42 | module IfaceConfigAttr = 43 | struct 44 | let stability_policy = "stability_policy" 45 | let is_site_package = "is-site-package" 46 | let src = "src" 47 | let arch = "arch" 48 | end 49 | -------------------------------------------------------------------------------- /src/zeroinstall/progress.mli: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2013, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** Used to report progress during a solve *) 6 | 7 | type key_vote_type = Good | Bad 8 | type key_vote = (key_vote_type * string) 9 | 10 | class type watcher = 11 | object 12 | (* An error ocurred (probably a failure to download something). *) 13 | method report : 'a. ([ string -> unit 14 | 15 | (* Updates the latest solution. If the first argument is [true] then the solve is 16 | * usable (although it may improve if you wait). *) 17 | method update : (bool * Solver.Output.t) * Feed_provider.feed_provider -> unit 18 | 19 | (** A new download has been added (may still be queued). *) 20 | method monitor : Downloader.download -> unit 21 | 22 | (** Ask the user to confirm they trust at least one of the signatures on this feed. 23 | * @param key_info a list of fingerprints and their (eventual) votes 24 | * Return the list of fingerprints the user wants to trust. *) 25 | method confirm_keys : Feed_url.remote_feed -> (Support.Gpg.fingerprint * key_vote list Lwt.t) list -> Support.Gpg.fingerprint list Lwt.t 26 | 27 | (** Display a confirmation request *) 28 | method confirm : string -> [`Ok | `Cancel] Lwt.t 29 | 30 | (** Called each time a new implementation is added to the cache. 31 | * This is used by the GUI to refresh its display. *) 32 | method impl_added_to_store : unit 33 | end 34 | -------------------------------------------------------------------------------- /src/cli/remove_feed.ml: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2013, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** The "0install remove-feed" command *) 6 | 7 | open Options 8 | open Zeroinstall.General 9 | open Support 10 | 11 | module G = Generic_select 12 | module FC = Zeroinstall.Feed_cache 13 | 14 | let handle options flags args = 15 | let config = options.config in 16 | Support.Argparse.iter_options flags (function 17 | | #common_option as o -> Common_options.process_common_option options o 18 | ); 19 | match args with 20 | | [feed_url] -> 21 | Format.fprintf options.stdout "Feed '%s':@." feed_url; 22 | let user_import = G.canonical_feed_url config.system feed_url in 23 | Add_feed.edit_feeds_interactive ~stdout:options.stdout config `Remove user_import 24 | | [iface; feed_src] -> 25 | let iface = G.canonical_iface_uri config.system iface in 26 | let feed_src = G.canonical_feed_url config.system feed_src in 27 | let user_import = Zeroinstall.Feed_import.make_user feed_src in 28 | 29 | let iface_config = FC.load_iface_config config iface in 30 | if not (List.mem user_import iface_config.FC.extra_feeds) then ( 31 | Safe_exn.failf "Interface %s has no feed %s" iface (Zeroinstall.Feed_url.format_url feed_src) 32 | ); 33 | 34 | let extra_feeds = List.filter ((<>) user_import) iface_config.FC.extra_feeds in 35 | FC.save_iface_config config iface {iface_config with FC.extra_feeds} 36 | | _ -> raise (Support.Argparse.Usage_error 1) 37 | -------------------------------------------------------------------------------- /src/support/gpg.mli: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2013, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** Use GnuPG to check the digital signatures on feeds. *) 6 | 7 | type t 8 | 9 | type fingerprint = string 10 | type timestamp = float 11 | 12 | type sig_error = 13 | | UnsupportedAlgorithm of string 14 | | UnknownKey of string 15 | | UnknownSigError of int 16 | 17 | type valid_details = { 18 | fingerprint : fingerprint; 19 | timestamp : timestamp; 20 | } 21 | 22 | type signature = 23 | | ValidSig of valid_details 24 | | BadSig of string (* Message has been tampered with *) 25 | | ErrSig of sig_error 26 | 27 | type key_info = { 28 | name : string option 29 | } 30 | 31 | val make : Common.system -> t 32 | 33 | (** A human-readable description of a signature. *) 34 | val string_of_sig : signature -> string 35 | 36 | (** Run "gpg --import" with this data as stdin. *) 37 | val import_key : t -> string -> unit Lwt.t 38 | 39 | (** Get the first human-readable name from the details. *) 40 | val get_key_name : t -> fingerprint -> string option Lwt.t 41 | 42 | (** Verify the GPG signature at the end of data (which must be XML). 43 | * Returns the list of signatures found, plus the raw stderr from gpg (which may be useful if 44 | * you need to report an error). *) 45 | val verify : t -> string -> (signature list * string) Lwt.t 46 | 47 | (** Load a set of keys at once. Returns a map from fingerprints to information. *) 48 | val load_keys : t -> fingerprint list -> key_info XString.Map.t Lwt.t 49 | -------------------------------------------------------------------------------- /src/zeroinstall/feed.mli: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2013, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** Parsing feeds *) 6 | 7 | open Support 8 | open Support.Common 9 | 10 | type t 11 | 12 | val parse : #filesystem -> [`Feed] Element.t -> filepath option -> t 13 | 14 | val default_attrs : url:string -> Support.Qdom.AttrMap.t 15 | val process_group_properties : local_dir:filepath option -> Impl.properties -> 16 | [<`Group | `Implementation | `Package_impl] Element.t -> Impl.properties 17 | 18 | val url : t -> Feed_url.non_distro_feed 19 | val name : t -> string 20 | val get_summary : int Support.Locale.LangMap.t -> t -> string option 21 | val get_description : int Support.Locale.LangMap.t -> t -> string option 22 | val imported_feeds : t -> Feed_import.t list 23 | val zi_implementations : t -> [> `Cache_impl of Impl.cache_impl | `Local_impl of filepath] Impl.t XString.Map.t 24 | val package_implementations : t -> ([`Package_impl] Element.t * Impl.properties) list 25 | 26 | (** The elements' interfaces *) 27 | val get_feed_targets : t -> Sigs.iface_uri list 28 | 29 | val get_category : t -> string option 30 | val needs_terminal : t -> bool 31 | val icons : t -> [`Icon] Element.t list 32 | 33 | val replacement : t -> Sigs.iface_uri option 34 | (** The URI of the interface that replaced the one with the URI of this feed's URL. 35 | This is the value of the feed's element. *) 36 | 37 | val root : t -> [`Feed] Element.t 38 | val pp_url : Format.formatter -> t -> unit 39 | -------------------------------------------------------------------------------- /src/zeroinstall/version.mli: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2014, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** Parsing version numbers *) 6 | 7 | type modifier = 8 | | Pre 9 | | Rc 10 | | Dash 11 | | Post 12 | 13 | type dotted_int = Int64.t list 14 | 15 | type t = (dotted_int * modifier) list 16 | 17 | type version_expr = t -> bool 18 | 19 | (** Convert a version string to an internal representation. 20 | The parsed format can be compared using the regular comparison operators. 21 | - Version := DottedList ("-" Mod DottedList?)* 22 | - DottedList := (Integer ("." Integer)* ) 23 | @raise Safe_exn.T if the string isn't a valid version 24 | *) 25 | val parse : string -> t 26 | val to_string : t -> string 27 | 28 | (** [make_range_restriction x y] returns a test for versions where [x <= version < y]. *) 29 | val make_range_restriction : string option -> string option -> version_expr 30 | 31 | (** [parse_expr expr] is a test for versions that match [expr]. 32 | * e.g. [parse_expr "2.2..!3 | 3.3.."] matches [2.3.1] and [3.3.2] but not [3.1]. *) 33 | val parse_expr : string -> version_expr 34 | 35 | (** Remove everything from the first "-" *) 36 | val strip_modifier : t -> t 37 | 38 | (** Try to turn a distribution version string into a 0install one. 39 | We do this by ignoring anything we can't parse, with some additional heuristics. *) 40 | val try_cleanup_distro_version : string -> t option 41 | 42 | (** Formatter for [%a] format strings. *) 43 | val pp : Format.formatter -> t -> unit 44 | -------------------------------------------------------------------------------- /src/support/safe_exn.mli: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2018, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** A [Safe_exn.T] represents an error that is not a bug in 0install. 6 | It should be reported to the user without a stack trace by default. *) 7 | 8 | type payload 9 | 10 | exception T of payload 11 | (** A [T _] is an exception with a main error message and a list of additional context lines. *) 12 | 13 | val v : ?ctx:string list -> ('a, Format.formatter, unit, exn) format4 -> 'a 14 | (** [v fmt ...] is a new [T] with [fmt ...] as its message. *) 15 | 16 | val failf : ?ctx:string list -> ('a, Format.formatter, unit, _) format4 -> 'a 17 | (** [failf fmt ...] raises a safe exception with the given message (and optional context). *) 18 | 19 | val reraise_with : exn -> ('a, Format.formatter, unit, _) format4 -> 'a 20 | (** [reraise_with exn fmt ...] adds [fmt ...] to the context of [exn] (which must be 21 | a [T]) and re-raises it, preserving the existing stack-trace. *) 22 | 23 | val with_info : ((('a, Format.formatter, unit, unit) format4 -> 'a) -> unit) -> (unit -> 'r Lwt.t) -> 'r Lwt.t 24 | (** [with_info note f] is [f ()], except that if it raises [T _] then 25 | we call [note writer] and add whatever is passed to writer to the context. *) 26 | 27 | val pp : Format.formatter -> payload -> unit 28 | (** [pp] formats a payload by writing out the message followed by each context line. *) 29 | 30 | val msg : payload -> string 31 | (** [msg p] is the message part of the payload (without the context) .*) 32 | -------------------------------------------------------------------------------- /src/tests/data/dpkg/apt-cache: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | if [ "$4" = "python-bittorrent" ]; then 3 | cat < 9 | Original-Maintainer: Michael Janssen 10 | Architecture: all 11 | Source: bittorrent 12 | Version: 3.4.2-11.1ubuntu3 13 | Replaces: bittorrent (<< 3.4.2-10ubuntu2) 14 | Provides: python2.5-bittorrent, python2.6-bittorrent 15 | Depends: python (>= 2.3), python-central (>= 0.6.11) 16 | Filename: pool/main/b/bittorrent/python-bittorrent_3.4.2-11.1ubuntu3_all.deb 17 | Size: 53142 18 | MD5sum: ba5781c15297a424fc9590d36c92851c 19 | SHA1: f37f18302020d75354411f67a8d2d101ff056eb2 20 | SHA256: b16e0afba58076bc683a2a4bced8f807a5102dbe41fcde63eab2d38b86ffa621 21 | Description: Scatter-gather network file transfer 22 | BitTorrent is a tool for distributing files. It's extremely 23 | easy to use - downloads are started by clicking on hyperlinks. 24 | Whenever more than one person is downloading at once 25 | they send pieces of the file(s) to each other, thus relieving 26 | the central server's bandwidth burden. Even with many 27 | simultaneous downloads, the upload burden on the central server 28 | remains quite small, since each new downloader introduces new 29 | upload capacity. 30 | . 31 | This package contains the python modules. 32 | Homepage: http://bitconjurer.org/BitTorrent/ 33 | Python-Version: >= 2.3 34 | Bugs: https://bugs.launchpad.net/ubuntu/+filebug 35 | Origin: Ubuntu 36 | 37 | EOF 38 | fi 39 | -------------------------------------------------------------------------------- /src/cli/run.ml: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2013, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** The "0install run" command *) 6 | 7 | open Support 8 | open Options 9 | open Zeroinstall.General 10 | 11 | module U = Support.Utils 12 | 13 | type run_options = { 14 | mutable wrapper : string option; 15 | mutable main : string option; 16 | } 17 | 18 | let handle options flags args = 19 | let run_opts = { 20 | wrapper = None; 21 | main = None; 22 | } in 23 | let select_opts = ref [] in 24 | Support.Argparse.iter_options flags (function 25 | | #common_option as o -> Common_options.process_common_option options o 26 | | #binary_select_option | `Refresh as o -> select_opts := o :: !select_opts 27 | | `Wrapper w -> run_opts.wrapper <- Some w 28 | | `ShowManifest -> Safe_exn.failf "The -m argument is ambiguous before the 'run' argument. Put it after, or use --main" 29 | | `MainExecutable m -> run_opts.main <- Some m 30 | ); 31 | 32 | match args with 33 | | arg :: run_args -> ( 34 | let sels = Generic_select.handle options !select_opts arg `Select_for_run in 35 | 36 | let exec args ~env = 37 | options.config.system#exec args ~env in 38 | 39 | try 40 | match Zeroinstall.Exec.execute_selections ~exec options.config sels run_args ?main:run_opts.main ?wrapper:run_opts.wrapper with 41 | | `Dry_run msg -> Zeroinstall.Dry_run.log "%s" msg 42 | | `Ok () -> () 43 | with Safe_exn.T _ as ex -> Safe_exn.reraise_with ex "... running %s" arg 44 | ) 45 | | _ -> raise (Support.Argparse.Usage_error 1) 46 | -------------------------------------------------------------------------------- /src/tests/data/Source-missing-req.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Source 5 | Source 6 | Source 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 36 | -------------------------------------------------------------------------------- /src/support/utils.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | */ 4 | 5 | #define CAML_NAME_SPACE 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include 17 | #include 18 | 19 | #ifndef _WIN32 20 | #include 21 | #include 22 | #include 23 | #include 24 | #endif 25 | 26 | /* Based on code in extunix (LGPL-2.1) */ 27 | CAMLprim value ocaml_0install_uname(value v_unit) { 28 | CAMLparam1(v_unit); 29 | #ifdef _WIN32 30 | caml_failwith("No uname on Windows!"); 31 | CAMLreturn(v_unit); 32 | #else 33 | struct utsname uname_data; 34 | 35 | CAMLlocal2(result, domainname); 36 | 37 | memset(&uname_data, 0, sizeof(uname_data)); 38 | 39 | if (uname(&uname_data) == 0) { 40 | result = caml_alloc(3, 0); 41 | Store_field(result, 0, caml_copy_string(&(uname_data.sysname[0]))); 42 | Store_field(result, 1, caml_copy_string(&(uname_data.release[0]))); 43 | Store_field(result, 2, caml_copy_string(&(uname_data.machine[0]))); 44 | } else { 45 | caml_failwith(strerror(errno)); 46 | } 47 | 48 | CAMLreturn(result); 49 | #endif 50 | } 51 | 52 | CAMLprim value ocaml_0install_get_terminal_width(value v_unit) { 53 | CAMLparam1(v_unit); 54 | int width; 55 | #ifndef _WIN32 56 | struct winsize w; 57 | ioctl(STDOUT_FILENO, TIOCGWINSZ, &w); 58 | width = w.ws_col; 59 | #else 60 | width = 80; 61 | #endif 62 | CAMLreturn(Val_int(width)); 63 | } 64 | -------------------------------------------------------------------------------- /src/support/logging.mli: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2013, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** Simple logging support *) 6 | 7 | type level = Debug | Info | Warning 8 | 9 | type time = float 10 | 11 | type entry = time * exn option * level * string 12 | 13 | val string_of_level : level -> string 14 | 15 | val threshold : level ref 16 | 17 | val will_log : level -> bool 18 | 19 | (* If set, we call this before logging anything and then set it to None. This is used to clear progress displays. *) 20 | val clear_fn : (unit -> unit) option ref 21 | 22 | type handler = ?ex:exn -> level -> string -> unit 23 | 24 | val handler : handler ref 25 | 26 | val log : level -> ?ex:exn -> ('a, Format.formatter, unit) format -> 'a 27 | 28 | val log_debug : ?ex:exn -> ('a, Format.formatter, unit) format -> 'a 29 | 30 | (** Write a message to stderr if verbose logging is on. *) 31 | val log_info : ?ex:exn -> ('a, Format.formatter, unit) format -> 'a 32 | 33 | (** Write a message to stderr, prefixed with "warning: ". *) 34 | val log_warning : ?ex:exn -> ('a, Format.formatter, unit) format -> 'a 35 | 36 | val format_argv_for_logging : string list -> string 37 | 38 | (** If set, record all log messages (at all levels) in memory and dump to this directory 39 | * on error. Useful for tracking down intermittent bugs. *) 40 | val set_crash_logs_handler : (entry list -> unit) -> unit 41 | 42 | (** Dump all recorded log entries to the crash handler set with [set_crash_handler]. 43 | * If there is no handler, or the log is empty, does nothing. This is called automatically 44 | * after logging at level Warning. *) 45 | val dump_crash_log : ?ex:exn -> unit -> unit 46 | -------------------------------------------------------------------------------- /src/cli/command_tree.mli: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2014, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** Directory of command handlers (e.g. ["store"; "add"] -> Store.handle_add) *) 6 | 7 | open Options 8 | open Support 9 | open Support.Argparse 10 | 11 | type command 12 | and commands = (string * node) list 13 | and node = 14 | | Command of command 15 | | Group of commands 16 | 17 | (** A handler for a command, accepting options of type ['a] *) 18 | type 'a handler = global_settings -> ([< zi_option ] as 'a) parsed_options -> string list -> unit 19 | 20 | (** Parse the options and run the appropriate handler. *) 21 | val handle : 22 | command -> 23 | global_settings -> 24 | raw_option list -> 25 | string list -> (* Command path e.g. ["store"; "add"] for "0install store add" *) 26 | string list -> (* Arguments (after command path) *) 27 | unit 28 | 29 | (** Get the help text for this command. None if this is a hidden (internal) command. *) 30 | val help : command -> string option 31 | 32 | (** Get the list of options supported by this command. For tab-completion. *) 33 | val options : command -> (zi_option, zi_arg_type) opt_spec list 34 | 35 | (** Return the supported option names as a set (for tab-completion). *) 36 | val set_of_option_names : node -> XString.Set.t 37 | 38 | val make_command : 39 | string -> (* help text *) 40 | 'a handler -> 41 | ('a, zi_arg_type) opt_spec list -> 42 | node 43 | 44 | val make_command_hidden : 45 | 'a handler -> 46 | ('a, zi_arg_type) opt_spec list -> 47 | node 48 | 49 | val make_group : commands -> node 50 | 51 | val lookup : 52 | node -> 53 | string list -> (* args *) 54 | string list * node * string list (* consumed args, node, remaining args *) 55 | -------------------------------------------------------------------------------- /src/gui_gtk/tray_icon.ml: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2013, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** The system tray notification icon (used for background updates) *) 6 | 7 | open Support.Common 8 | open Gtk_common 9 | 10 | class tray_icon systray = 11 | let clicked, set_clicked = Lwt.wait () in 12 | object (self) 13 | val mutable icon = None 14 | 15 | method clicked = clicked 16 | 17 | method have_icon = icon <> None 18 | 19 | method private activate () = 20 | icon |> if_some (fun i -> 21 | i#set_visible false; 22 | icon <- None; 23 | Lwt.wakeup set_clicked () 24 | ) 25 | 26 | (* If we currently have a tray icon, set it blinking. 27 | * If we tried and failed to add an icon, activate immediately. 28 | * If there is no icon, do nothing. *) 29 | method set_blinking message = 30 | icon |> if_some (fun icon -> 31 | message |> if_some icon#set_tooltip_text; 32 | (* If the icon isn't embedded yet, give it a chance first... *) 33 | Gtk_utils.async (fun () -> 34 | begin if not icon#is_embedded then Lwt_unix.sleep 0.5 else Lwt.return () end >|= fun () -> 35 | if not icon#is_embedded then ( 36 | log_info "No system-tray support, so opening main window immediately"; 37 | self#activate () 38 | ) 39 | ) 40 | ) 41 | 42 | method set_tooltip msg = icon |> if_some (fun icon -> icon#set_tooltip_text msg) 43 | 44 | initializer 45 | if systray then ( 46 | let i = GMisc.status_icon_from_icon_name "zeroinstall" in 47 | icon <- Some i; 48 | i#connect#activate ==> self#activate 49 | ) else ( 50 | Lwt.wakeup set_clicked () 51 | ) 52 | end 53 | -------------------------------------------------------------------------------- /src/zeroinstall/scope_filter.ml: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2014, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | open Support 6 | 7 | type t = { 8 | extra_restrictions : Impl.restriction XString.Map.t; (* iface -> test *) 9 | os_ranks : Arch.os_ranking; 10 | machine_ranks : Arch.machine_ranking; 11 | languages : int Support.Locale.LangMap.t; 12 | allowed_uses : XString.Set.t; (* deprecated *) 13 | may_compile : bool; 14 | } 15 | 16 | let os_ok t v = Arch.os_ok t.os_ranks v 17 | let machine_ok t ~want_source v = 18 | if Arch.is_src v then want_source 19 | else if want_source then false 20 | else Arch.machine_ok t.machine_ranks v 21 | 22 | let lang_ok t (lang, _country) = 23 | Support.Locale.LangMap.mem (lang, None) t.languages 24 | 25 | let use_ok t = function 26 | | Some use when not (XString.Set.mem use t.allowed_uses) -> false 27 | | _ -> true 28 | 29 | let os_rank t os = Arch.os_rank t.os_ranks os 30 | 31 | let machine_rank t machine = Arch.machine_rank t.machine_ranks machine 32 | 33 | let lang_rank t lang = 34 | try Support.Locale.LangMap.find lang t.languages 35 | with Not_found -> 0 36 | 37 | let user_restriction_for t iface = XString.Map.find_opt iface t.extra_restrictions 38 | 39 | let use_feed t ~want_source feed = 40 | let machine_ok = 41 | match feed.Feed_import.machine with 42 | | None -> true (* Feed doesn't say what it contains, so we can't safely skip it *) 43 | | m when Arch.is_src m -> want_source || t.may_compile (* Feed contains only source *) 44 | | Some _ when want_source -> false (* Feed contains only binaries and we want source *) 45 | | Some _ as m -> Arch.machine_ok t.machine_ranks m in 46 | machine_ok && Arch.os_ok t.os_ranks feed.Feed_import.os 47 | -------------------------------------------------------------------------------- /src/support/xString.mli: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2018, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** Extra string utilities. *) 6 | 7 | val starts_with : string -> string -> bool 8 | (** [starts_with s prefix] is [true] iff [s] starts with [prefix]. *) 9 | 10 | val ends_with : string -> string -> bool 11 | (** [ends_with s suffix] is [true] iff [s] ends with [suffix]. *) 12 | 13 | val tail : string -> int -> string 14 | (** [tail s n] is [s] without the first [n] chars. Raises an exception if [String.length s < n]. *) 15 | 16 | val split_pair : Str.regexp -> string -> (string * string) option 17 | (** [split_pair re s] splits [s] at the left-most occurance of [re] and returns the pair of the 18 | parts before and after the match. Returns [None] if [re] does not occur in [s]. *) 19 | 20 | val split_pair_safe : Str.regexp -> string -> string * string 21 | (** [split_pair_safe] is like [split_pair], but raises [Safe_exn.T] if there is no match. *) 22 | 23 | val to_int_safe : string -> int 24 | (** [to_int_safe s] is like [int_of_string], but raises a more helpful [Safe_exn.T] on failure. *) 25 | 26 | val re_dash : Str.regexp 27 | val re_slash : Str.regexp 28 | val re_space : Str.regexp 29 | val re_tab : Str.regexp 30 | val re_colon : Str.regexp 31 | val re_equals : Str.regexp 32 | val re_semicolon : Str.regexp 33 | 34 | module Map : sig 35 | include Map.S with type key = string 36 | 37 | val find_safe : string -> 'a t -> 'a 38 | (** Like [find], but raises [Safe_exn.t] if the key is missing, 39 | with a message that includes the name of the missing key. *) 40 | 41 | val map_bindings : (string -> 'a -> 'b) -> 'a t -> 'b list 42 | (** [map_bindings f t] is [List.map f (bindings t)]. *) 43 | end 44 | 45 | module Set : Set.S with type elt = string 46 | -------------------------------------------------------------------------------- /src/zeroinstall/packagekit.mli: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2013, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** Interacting with distribution package managers via PackageKit. This is used to find uninstalled candidate packages. *) 6 | 7 | type packagekit_id = string 8 | type size = Int64.t 9 | 10 | type package_info = { 11 | version : Version.t; 12 | machine : Arch.machine option; 13 | installed : bool; 14 | retrieval_method : Impl.distro_retrieval_method; 15 | } 16 | 17 | type query_result = { 18 | results : package_info list; 19 | problems : string list; 20 | } 21 | 22 | class type ui = 23 | object 24 | method monitor : Downloader.download -> unit 25 | method confirm : string -> [`Ok | `Cancel] Lwt.t 26 | method impl_added_to_store : unit 27 | end 28 | 29 | type packagekit = < 30 | (* Check whether PackageKit is available (only slow the first time) *) 31 | status : [`Ok | `Unavailable of string] Lwt.t; 32 | 33 | (* Return any cached candidates. 34 | The candidates are those discovered by a previous call to [check_for_candidates]. 35 | @param package_name the distribution's name for the package *) 36 | get_impls : string -> query_result; 37 | 38 | (* Request information about these packages from PackageKit. *) 39 | check_for_candidates : 'a. ui:(#ui as 'a) -> hint:string -> string list -> unit Lwt.t; 40 | 41 | (* Install packages. Will confirm first with the user. *) 42 | install_packages : 'a. (#ui as 'a) -> (Impl.distro_implementation * Impl.distro_retrieval_method) list -> [ `Ok | `Cancel ] Lwt.t; 43 | > 44 | 45 | (** Create a packagekit object, which can be used to query the PackageKit D-BUS 46 | * service for information about (uninstalled) candidate packages. *) 47 | val make : Support.Locale.lang_spec -> packagekit 48 | -------------------------------------------------------------------------------- /src/tests/data/ranking.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | ranking 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /src/zeroinstall/feed_url.ml: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2013, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | open Support 6 | module U = Support.Utils 7 | 8 | type local_feed = [`Local_feed of Support.Common.filepath] 9 | type remote_feed = [`Remote_feed of string] 10 | type non_distro_feed = [local_feed | remote_feed] 11 | type parsed_feed_url = [`Distribution_feed of non_distro_feed | non_distro_feed] 12 | 13 | let is_http url = XString.starts_with url "http://" 14 | let is_https url = XString.starts_with url "https://" 15 | let is_distro url = XString.starts_with url "distribution:" 16 | 17 | let parse_non_distro url = 18 | if U.path_is_absolute url then `Local_feed url 19 | else if is_http url || is_https url then `Remote_feed url 20 | else if is_distro url then Safe_exn.failf "Can't use a distribution feed here! ('%s')" url 21 | else Safe_exn.failf "Invalid feed URL '%s'" url 22 | 23 | let parse url = 24 | if is_distro url then `Distribution_feed (XString.tail url 13 |> parse_non_distro) 25 | else parse_non_distro url 26 | 27 | let format_non_distro : non_distro_feed -> string = function 28 | | `Local_feed path -> path 29 | | `Remote_feed url -> url 30 | 31 | let format_url = function 32 | | `Distribution_feed master -> "distribution:" ^ (format_non_distro master) 33 | | #non_distro_feed as x -> format_non_distro x 34 | 35 | let pp f x = Format.pp_print_string f (format_url x) 36 | 37 | let master_feed_of_iface uri = parse_non_distro uri 38 | 39 | module FeedElt = 40 | struct 41 | type t = non_distro_feed 42 | let compare = compare 43 | end 44 | 45 | module FeedSet = Set.Make(FeedElt) 46 | module FeedMap = Map.Make(FeedElt) 47 | 48 | (** A globally-unique identifier for an implementation. *) 49 | type global_id = { 50 | feed : parsed_feed_url; 51 | id : string; 52 | } 53 | -------------------------------------------------------------------------------- /src/zeroinstall/scope_filter.mli: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2014, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** Used for filtering and ranking implementations before passing them to the solver. *) 6 | 7 | open Support 8 | 9 | type t = { 10 | extra_restrictions : Impl.restriction XString.Map.t; (* iface -> test *) 11 | os_ranks : Arch.os_ranking; 12 | machine_ranks : Arch.machine_ranking; 13 | languages : int Support.Locale.LangMap.t; 14 | allowed_uses : XString.Set.t; (* deprecated *) 15 | may_compile : bool; (* For each source impl, add the potential binary that could be made from it *) 16 | } 17 | 18 | (** Check whether some OS is acceptable. 19 | * If no particular OS is specified, then any OS will do. *) 20 | val os_ok : t -> Arch.os option -> bool 21 | 22 | (** Check whether some machine is acceptable. 23 | * If no particular machine is specified, then any will do. *) 24 | val machine_ok : t -> want_source:bool -> Arch.machine option -> bool 25 | 26 | (** Check whether the language part of a lang_spec is acceptable. *) 27 | val lang_ok : t -> Support.Locale.lang_spec -> bool 28 | 29 | (** Check whether a 'use' value is acceptable (deprecated). *) 30 | val use_ok : t -> string option -> bool 31 | 32 | (** Get the rank of an OS. Lower numbers are better. *) 33 | val os_rank : t -> Arch.os -> int option 34 | 35 | (** Get the rank of a CPU type. Lower numbers are better. *) 36 | val machine_rank : t -> Arch.machine -> int option 37 | 38 | (* Rank of this lang_spec (0 if not acceptable). *) 39 | val lang_rank : t -> Support.Locale.lang_spec -> int 40 | 41 | (* Get the user-provided restriction for an interface, if any. *) 42 | val user_restriction_for : t -> Sigs.iface_uri -> Impl.restriction option 43 | 44 | (* Should we consider this feed import? *) 45 | val use_feed : t -> want_source:bool -> Feed_import.t -> bool 46 | -------------------------------------------------------------------------------- /src/zeroinstall/distro_impls.mli: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2017, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** Platform-specific code for interacting with distribution package managers. *) 6 | 7 | (** Create a suitable distribution object for this system. *) 8 | val get_host_distribution : packagekit:(Packagekit.packagekit Lazy.t) -> General.config -> Distro.t 9 | 10 | (** {2 The following are exposed only for unit-testing} *) 11 | 12 | val generic_distribution : packagekit:Packagekit.packagekit Lazy.t -> General.config -> Distro.distribution 13 | 14 | module ArchLinux : sig 15 | val arch_distribution : ?arch_db:Support.Common.filepath -> packagekit:Packagekit.packagekit Lazy.t -> General.config -> Distro.distribution 16 | end 17 | 18 | module Debian : sig 19 | val debian_distribution : ?status_file:Support.Common.filepath -> packagekit:Packagekit.packagekit Lazy.t -> General.config -> Distro.distribution 20 | end 21 | 22 | module RPM : sig 23 | val rpm_distribution : ?rpm_db_packages:Support.Common.filepath -> packagekit:Packagekit.packagekit Lazy.t -> General.config -> Distro.distribution 24 | end 25 | 26 | module Ports : sig 27 | val ports_distribution : ?pkg_db:Support.Common.filepath -> packagekit:Packagekit.packagekit Lazy.t -> General.config -> Distro.distribution 28 | end 29 | 30 | module Gentoo : sig 31 | val gentoo_distribution : ?pkgdir:Support.Common.filepath -> packagekit:Packagekit.packagekit Lazy.t -> General.config -> Distro.distribution 32 | end 33 | 34 | module Slackware : sig 35 | val slack_distribution : ?packages_dir:Support.Common.filepath -> packagekit:Packagekit.packagekit Lazy.t -> General.config -> Distro.distribution 36 | end 37 | 38 | module Mac : sig 39 | val macports_distribution : ?macports_db:Support.Common.filepath -> General.config -> Distro.distribution 40 | val darwin_distribution : General.config -> Distro.distribution 41 | end 42 | -------------------------------------------------------------------------------- /src/zeroinstall/arch.mli: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2013, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** OS and CPU types. *) 6 | 7 | open Support 8 | open Support.Common 9 | 10 | type os 11 | type machine 12 | type arch = os option * machine option 13 | 14 | type os_ranking 15 | type machine_ranking 16 | 17 | (** Parse a (canonical) arch, as found in 0install feeds. *) 18 | val parse_arch : string -> arch 19 | 20 | val format_arch : arch -> string 21 | 22 | val get_os_ranks : os -> os_ranking 23 | 24 | (** Treat a string as a machine type. None if "*". *) 25 | val parse_machine : string -> machine option 26 | 27 | val parse_os : string -> os option 28 | 29 | type machine_group = 30 | | Machine_group_default (* e.g. i686 *) 31 | | Machine_group_64 (* e.g. x86_64 *) 32 | 33 | (* All chosen machine-specific implementations must come from the same group. 34 | Unlisted archs are in Machine_group_default. *) 35 | val get_machine_group : machine option -> machine_group option 36 | 37 | val get_machine_ranks : multiarch:bool -> machine -> machine_ranking 38 | 39 | (** Is this value in the ranking? *) 40 | val os_ok : os_ranking -> os option -> bool 41 | val machine_ok : machine_ranking -> machine option -> bool 42 | 43 | val os_rank : os_ranking -> os -> int option 44 | val machine_rank : machine_ranking -> machine -> int option 45 | 46 | val format_machine : machine -> string 47 | val format_os : os -> string 48 | 49 | (** Returns "*" if None. *) 50 | val format_machine_or_star : machine option -> string 51 | 52 | (** Returns "*" if None. *) 53 | val format_os_or_star : os option -> string 54 | 55 | val is_src : machine option -> bool 56 | 57 | val platform : system -> os * machine 58 | 59 | val linux : os 60 | val x86_64 : machine 61 | 62 | val custom_os_ranking : int XString.Map.t -> os_ranking 63 | val custom_machine_ranking : int XString.Map.t -> machine_ranking 64 | -------------------------------------------------------------------------------- /src/zeroinstall/stores.mli: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2013, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** Managing cached implementations *) 6 | 7 | open Support.Common 8 | 9 | type stores = filepath list 10 | type available_digests = (string, filepath) Hashtbl.t (* Digest -> Parent directory of implementation *) 11 | 12 | exception Not_stored of string 13 | 14 | val lookup_maybe : #filesystem -> Manifest.digest list -> stores -> filepath option 15 | val lookup_any : #filesystem -> Manifest.digest list -> stores -> string 16 | val get_default_stores : system -> Paths.t -> stores 17 | 18 | (** Scan all the stores and build a set of the available digests. This can be used 19 | later to quickly test whether a digest is in the cache. *) 20 | val get_available_digests : #filesystem -> stores -> available_digests 21 | val check_available : available_digests -> Manifest.digest list -> bool 22 | 23 | (* (for parsing and elements) *) 24 | val get_digests : [< `Implementation | `Selection] Element.t -> Manifest.digest list 25 | 26 | (* Raises an exception if no digest is supported *) 27 | val best_digest : Manifest.digest list -> Manifest.digest 28 | 29 | (** Recursively set permissions: 30 | * Directories and executable files become 0o555. 31 | * Other files become 0o444. 32 | * @raise Safe_exn.T if there are special files or files with special mode bits set *) 33 | val fixup_permissions : #filesystem -> filepath -> unit 34 | 35 | (** Create a temporary directory in the directory where we would store a new implementation. 36 | This is used to set up a new implementation before being renamed if it turns out OK. *) 37 | val make_tmp_dir : #filesystem -> stores -> filepath 38 | 39 | val check_manifest_and_rename : General.config -> Manifest.digest -> filepath -> unit Lwt.t 40 | val add_dir_to_cache : General.config -> Manifest.digest -> filepath -> unit Lwt.t 41 | -------------------------------------------------------------------------------- /src/zeroinstall/json_connection.mli: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2016, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** Communicating over a JSON link. 6 | * 7 | * Each message is a length line "0xHHHHHHHH\n" followed by that many bytes of JSON. 8 | * Each JSON message is one of: 9 | * - [["invoke", ticket, op, args]] 10 | * - [["return", ticket, "ok", result]] 11 | * - [["return", ticket, "ok+xml", result]] followed by another length and an XML document 12 | * - [["return", ticket, "fail", msg]] 13 | * 14 | * The ticket is a unique ID chosen by the sender of the "invoke" message. The same ticket is quoted back 15 | * in the corresponding "return" or "fail" response. 16 | *) 17 | 18 | open Support 19 | 20 | type t 21 | 22 | type opt_xml = [Yojson.Basic.t | `WithXML of Yojson.Basic.t * Qdom.element ] 23 | type 'a handler = (string * Yojson.Basic.t list) -> [opt_xml | `Bad_request] Lwt.t 24 | 25 | val client : 26 | from_peer:Lwt_io.input_channel -> 27 | to_peer:Lwt_io.output_channel -> 28 | (t -> 'a handler) -> 29 | (t * unit Lwt.t * Version.t) Lwt.t 30 | (** [client ~from_peer ~to_peer make_handler] is a new connection, 31 | a thread handling incoming messages, and the protocol version. 32 | It evaluates [make_handler t] once to get a handler function, which it uses to process 33 | each message until the stream is closed. Replies are sent back to the peer. *) 34 | 35 | val server : 36 | api_version:Version.t -> 37 | from_peer:Lwt_io.input_channel -> 38 | to_peer:Lwt_io.output_channel -> 39 | (t -> 'a handler) -> 40 | t * unit Lwt.t 41 | (** Like [client], except that the server starts by sending the version number rather than reading it. *) 42 | 43 | val invoke : t -> ?xml:Qdom.element -> string -> Yojson.Basic.t list -> opt_xml Lwt.t 44 | val notify : t -> ?xml:Qdom.element -> string -> Yojson.Basic.t list -> unit Lwt.t 45 | 46 | val pp_opt_xml : Format.formatter -> opt_xml -> unit 47 | -------------------------------------------------------------------------------- /src/zeroinstall/feed_cache.mli: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2013, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** Caching downloaded feeds on disk *) 6 | 7 | open General 8 | open Support 9 | open Support.Common 10 | 11 | type interface_config = { 12 | stability_policy : Stability.t option; (* Overrides config.help_with_testing if set *) 13 | extra_feeds : Feed_import.t list; (* Feeds added manually with "0install add-feed" *) 14 | } 15 | 16 | (** Load a cached feed. 17 | * As a convenience, this will also load local feeds. *) 18 | val get_cached_feed : config -> [< Feed_url.non_distro_feed] -> Feed.t option 19 | val get_cached_feed_path : config -> Feed_url.remote_feed -> filepath option 20 | val get_save_cache_path : config -> Feed_url.remote_feed -> filepath 21 | 22 | val get_cached_icon_path : config -> [< Feed_url.non_distro_feed] -> filepath option 23 | 24 | val list_all_feeds : config -> XString.Set.t 25 | 26 | val load_iface_config : config -> Sigs.iface_uri -> interface_config 27 | val save_iface_config : config -> Sigs.iface_uri -> interface_config -> unit 28 | 29 | (** Check whether feed [url] is stale. 30 | * Returns false if it's stale but last-check-attempt is recent *) 31 | val is_stale : config -> Feed_url.remote_feed -> bool 32 | 33 | (** Low-level part of [is_stale] that doesn't automatically load the feed overrides (needed to get [last_checked]). 34 | * Useful if you've already loaded them yourself (or confirmed they're missing) to avoid doing it twice. *) 35 | val internal_is_stale : config -> Feed_url.remote_feed -> Feed_metadata.t option -> bool 36 | 37 | (** Touch a 'last-check-attempt' timestamp file for this feed. 38 | This prevents us from repeatedly trying to download a failing feed many 39 | times in a short period. *) 40 | val mark_as_checking : config -> Feed_url.remote_feed -> unit 41 | 42 | val get_last_check_attempt : config -> Feed_url.remote_feed -> float option 43 | -------------------------------------------------------------------------------- /src/support/xString.ml: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2018, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | let re_dash = Str.regexp_string "-" 6 | let re_slash = Str.regexp_string "/" 7 | let re_space = Str.regexp_string " " 8 | let re_tab = Str.regexp_string "\t" 9 | let re_colon = Str.regexp_string ":" 10 | let re_equals = Str.regexp_string "=" 11 | let re_semicolon = Str.regexp_string ";" 12 | 13 | let starts_with str prefix = 14 | let ls = String.length str in 15 | let lp = String.length prefix in 16 | if lp > ls then false else 17 | let rec loop i = 18 | if i = lp then true 19 | else if str.[i] <> prefix.[i] then false 20 | else loop (i + 1) 21 | in loop 0 22 | 23 | let ends_with str suffix = 24 | let ls = String.length str in 25 | let lp = String.length suffix in 26 | if lp > ls then false else 27 | let offset = ls - lp in 28 | let rec loop i = 29 | if i = lp then true 30 | else if str.[i + offset] <> suffix.[i] then false 31 | else loop (i + 1) 32 | in loop 0 33 | 34 | let tail s i = 35 | let len = String.length s in 36 | if i > len then failwith ("String '" ^ s ^ "' too short to split at " ^ (string_of_int i)) 37 | else String.sub s i (len - i) 38 | 39 | let to_int_safe s = 40 | try int_of_string s 41 | with Failure msg -> Safe_exn.failf "Invalid integer '%s' (%s)" s msg 42 | 43 | let split_pair re str = 44 | match Str.bounded_split_delim re str 2 with 45 | | [key; value] -> Some (key, value) 46 | | _ -> None 47 | 48 | let split_pair_safe re str = 49 | match split_pair re str with 50 | | Some p -> p 51 | | None -> Safe_exn.failf "Not a pair '%s'" str 52 | 53 | module Map = struct 54 | include Map.Make(String) 55 | let find_safe key map = try find key map with Not_found -> Safe_exn.failf "BUG: Key '%s' not found in XString.Map!" key 56 | let map_bindings fn map = fold (fun key value acc -> fn key value :: acc) map [] 57 | end 58 | 59 | module Set = Set.Make(String) 60 | -------------------------------------------------------------------------------- /src/zeroinstall/dbus.with.ml: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2013, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** Convenience functions for D-BUS. This file is only compiled when D-BUS support is available. *) 6 | 7 | open Support 8 | open Common 9 | 10 | module OBus_bus = OBus_bus 11 | module OBus_proxy = OBus_proxy 12 | module OBus_peer = OBus_peer 13 | module OBus_path = OBus_path 14 | module OBus_member = OBus_member 15 | module OBus_value = OBus_value 16 | module OBus_connection = OBus_connection 17 | module Notification = Notification 18 | module Nm_manager = Nm_manager 19 | module OBus_property = OBus_property 20 | module OBus_method = OBus_method 21 | module OBus_signal = OBus_signal 22 | module OBus_error = OBus_error 23 | module OBus_object = OBus_object 24 | 25 | let () = 26 | (* Don't log a warning if we can't find a bus. *) 27 | Lwt_log.add_rule "obus(bus)" Lwt_log.Error 28 | 29 | let session ?switch () = 30 | Lwt.catch (fun () -> 31 | begin try if Sys.getenv "DBUS_SESSION_BUS_ADDRESS" = "DBUS_SESSION_UNUSED" then 32 | failwith "Disabled for unit-tests" 33 | with Not_found -> () end; 34 | (* Prevent OBus from killing us. *) 35 | OBus_bus.session ?switch () >>= fun session_bus -> 36 | OBus_connection.set_on_disconnect session_bus (fun ex -> log_info ~ex "D-BUS disconnect"; return ()); 37 | return (`Ok session_bus) 38 | ) 39 | (fun ex -> 40 | log_debug ~ex "Failed to get D-BUS session bus"; 41 | return (`Error "Failed to get D-BUS session bus") 42 | ) 43 | 44 | let system () = 45 | Lwt.catch (fun () -> 46 | begin try if Sys.getenv "DBUS_SYSTEM_BUS_ADDRESS" = "DBUS_SYSTEM_UNUSED" then 47 | failwith "Disabled for unit-tests" 48 | with Not_found -> () end; 49 | OBus_bus.system () >|= fun system_bus -> `Ok system_bus 50 | ) 51 | (fun ex -> 52 | log_debug ~ex "Failed to get D-BUS system bus"; 53 | return (`Error "Failed to get D-BUS system bus") 54 | ) 55 | 56 | let have_dbus = true 57 | -------------------------------------------------------------------------------- /src/tests/data/Source.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Source 5 | Source 6 | Source 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 47 | -------------------------------------------------------------------------------- /src/gui_gtk/help_box.ml: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2013, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** Displays a few paragraphs of help text in a dialog box. *) 6 | 7 | open Support.Common 8 | open Gtk_common 9 | 10 | let create title sections = 11 | object 12 | val mutable dialog = None 13 | 14 | method display = 15 | dialog |> if_some (fun box -> box#destroy ()); 16 | let box = GWindow.dialog 17 | ~title 18 | ~position:`CENTER 19 | () in 20 | dialog <- Some box; 21 | 22 | box#action_area#set_border_width 4; 23 | 24 | let swin = GBin.scrolled_window 25 | ~hpolicy:`AUTOMATIC 26 | ~vpolicy:`ALWAYS 27 | ~shadow_type:`IN 28 | ~border_width:2 29 | () in 30 | 31 | box#vbox#pack (swin :> GObj.widget) ~expand:true ~fill:true; 32 | 33 | let text = GText.view 34 | ~wrap_mode:`WORD 35 | ~editable:false 36 | ~cursor_visible:false 37 | () in 38 | text#set_left_margin 4; 39 | text#set_right_margin 4; 40 | 41 | let model = text#buffer in 42 | let iter = model#start_iter in 43 | let heading_style = model#create_tag [`UNDERLINE `SINGLE; `SCALE `LARGE] in 44 | 45 | let first = ref true in 46 | sections |> List.iter (fun (heading, body) -> 47 | if !first then ( 48 | first := false 49 | ) else ( 50 | model#insert ~iter "\n\n"; 51 | ); 52 | model#insert ~iter ~tags:[heading_style] heading; 53 | model#insert ~iter ("\n" ^ body); 54 | ); 55 | swin#add (text :> GObj.widget); 56 | 57 | box#add_button_stock `CLOSE `CLOSE; 58 | box#connect#response ==> (function 59 | | `CLOSE | `DELETE_EVENT -> box#destroy () 60 | ); 61 | box#connect#destroy ==> (fun () -> dialog <- None); 62 | box#set_default_response `CLOSE; 63 | box#set_default_size 64 | ~width:(Gdk.Screen.width () / 4) 65 | ~height:(Gdk.Screen.height () / 3); 66 | box#show () 67 | end 68 | -------------------------------------------------------------------------------- /src/tests/data/old-selections.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | eu.serscis.Eval 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /src/zeroinstall/solver.mli: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2014, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** Select a compatible set of components to run a program. *) 6 | 7 | type scope = Impl_provider.impl_provider 8 | type role = { 9 | scope : scope; 10 | iface : Sigs.iface_uri; 11 | source : bool; 12 | } 13 | 14 | module Input : Zeroinstall_solver.S.SOLVER_INPUT with 15 | type Role.t = role and 16 | type impl = Impl.generic_implementation 17 | 18 | module Output : Zeroinstall_solver.S.SOLVER_RESULT with module Input = Input 19 | 20 | val selections : Output.t -> Selections.t 21 | 22 | (** Get the impl_provider used for this role. Useful for diagnostics and in the GUI to list the candidates. *) 23 | val impl_provider : role -> Impl_provider.impl_provider 24 | 25 | (** Convert [Requirements.t] to requirements for the solver. 26 | * This looks at the host system to get some values (whether we have multi-arch support, default CPU and OS). *) 27 | val get_root_requirements : General.config -> Requirements.t -> (Scope_filter.t -> Impl_provider.impl_provider) -> Input.requirements 28 | 29 | (** Find a set of implementations which satisfy these requirements. Consider using [solve_for] instead. 30 | @param closest_match adds a lowest-ranked (but valid) implementation to every interface, so we can always 31 | select something. Useful for diagnostics. 32 | @return None if the solve fails (only happens if [closest_match] is false). *) 33 | val do_solve : closest_match:bool -> Input.requirements -> Output.t option 34 | 35 | (** High-level solver interface. 36 | * Runs [do_solve ~closest_match:false] and reports (true, results) on success. 37 | * On failure, tries again with [~closest_match:true] and reports (false, results) for diagnostics. *) 38 | val solve_for : General.config -> Feed_provider.feed_provider -> Requirements.t -> bool * Output.t 39 | 40 | (** Why did this solve fail? We take the partial solution from the solver and show, 41 | for each component we couldn't select, which constraints caused the candidates 42 | to be rejected. *) 43 | val get_failure_reason : General.config -> Output.t -> string 44 | -------------------------------------------------------------------------------- /src/cli/add.ml: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2013, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** The "0install add" command *) 6 | 7 | open Options 8 | open Support 9 | open Support.Common 10 | 11 | module Apps = Zeroinstall.Apps 12 | module U = Support.Utils 13 | module R = Zeroinstall.Requirements 14 | module F = Zeroinstall.Feed 15 | 16 | (** Warn the user if [uri] has been replaced. *) 17 | let check_for_replacement f config uri = 18 | let feed = Zeroinstall.Feed_url.master_feed_of_iface uri in 19 | match Zeroinstall.Feed_cache.get_cached_feed config feed with 20 | | None -> log_warning "Master feed for '%s' missing!" uri 21 | | Some feed -> 22 | match F.replacement feed with 23 | | Some replacement -> 24 | Format.fprintf f "Warning: interface %s has been replaced by %s@." uri replacement 25 | | None -> () 26 | 27 | let handle options flags args = 28 | let select_opts = ref [] in 29 | let refresh = ref false in 30 | Support.Argparse.iter_options flags (function 31 | | #common_option as o -> Common_options.process_common_option options o 32 | | #binary_select_option as o -> select_opts := o :: !select_opts 33 | | `Refresh -> refresh := true 34 | ); 35 | match args with 36 | | [pet_name; arg] -> ( 37 | let module G = Generic_select in 38 | match G.resolve_target options.config !select_opts arg with 39 | | (G.Interface, reqs) -> ( 40 | match G.get_selections options ~refresh:!refresh reqs `Download_only |> Lwt_main.run with 41 | | `Aborted_by_user -> raise (System_exit 1) 42 | | `Success sels -> 43 | check_for_replacement options.stdout options.config reqs.R.interface_uri; 44 | let app = Apps.create_app options.config pet_name reqs in 45 | Apps.set_selections options.config app sels ~touch_last_checked:true; 46 | Apps.integrate_shell options.config app pet_name 47 | ) 48 | | (G.Selections _, _) -> Safe_exn.failf "'%s' is a selections document, not an interface URI" arg 49 | | (G.App _, _) -> Safe_exn.failf "'%s' is an app, not an interface URI" arg 50 | ) 51 | | _ -> raise (Support.Argparse.Usage_error 1) 52 | -------------------------------------------------------------------------------- /ZeroInstall.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Zero Install - OCaml version 5 | OCaml version of 0install, the decentralized installation system 6 | This is the OCaml version of Zero Install. Zero Install is a cross-platform, decentralized installation system. Instead of having a central repository in which all software is placed under a naming scheme managed by some central authority, programs and libraries in Zero Install are identified by URIs. Anyone who can create a web-page can publish software. Anyone can install software (not just administrators). 7 | 8 | https://0install.net/ 9 | 10 | 11 | 12 | 13 | System 14 | 15 | 16 | 17 | ^let version = "(.*)"$ 18 | rm .gitignore 19 | 20 | 21 | 22 | 23 | 24 | SRCDIR=${SRCDIR} 25 | DISTDIR=${DISTDIR} 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /src/zeroinstall/apps.mli: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2013, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** Support for 0install apps *) 6 | 7 | open General 8 | open Support.Common 9 | 10 | type app = filepath 11 | 12 | type app_times = { 13 | last_check_time : float; (* 0.0 => timestamp missing *) 14 | last_check_attempt : float option; (* always > last_check_time, if present *) 15 | last_solve : float; (* 0.0 => timestamp missing *) 16 | } 17 | 18 | (** Create a new app with these requirements. 19 | * You should call [set_selections] immediately after this. *) 20 | val create_app : config -> string -> Requirements.t -> app 21 | 22 | (** Remove this app and any shell command created with [integrate_shell]. *) 23 | val destroy : config -> app -> unit 24 | 25 | val lookup_app : config -> string -> app option 26 | 27 | val get_requirements : system -> app -> Requirements.t 28 | val set_requirements : config -> app -> Requirements.t -> unit 29 | 30 | (** Get the dates of the available snapshots, starting with the most recent. 31 | * Used by the "0install whatchanged" command. *) 32 | val get_history : config -> app -> string list 33 | 34 | val get_times : #filesystem -> app -> app_times 35 | 36 | (** Get the current selections. Does not check whether they're still valid. 37 | * @raise Safe_exn.T if they're missing. *) 38 | val get_selections_no_updates : #filesystem -> app -> Selections.t 39 | 40 | (** Get the current selections. 41 | * If they're missing or unusable, start a solve to get them. 42 | * If they're usable but stale, spawn a background update but return immediately. *) 43 | val get_selections_may_update : 44 | < config : config; distro : 45 | Distro.t; 46 | make_fetcher : Progress.watcher -> Fetch.fetcher; 47 | ui : Ui.ui_handler; ..> -> 48 | app -> Selections.t Lwt.t 49 | 50 | val set_selections : config -> app -> Selections.t -> touch_last_checked:bool -> unit 51 | 52 | (** Place an executable in $PATH that will launch this app. *) 53 | val integrate_shell : config -> app -> string -> unit 54 | 55 | (** Mark the app as up-to-date. *) 56 | val set_last_checked : system -> app -> unit 57 | 58 | val list_app_names : config -> string list 59 | -------------------------------------------------------------------------------- /src/cli/show.ml: -------------------------------------------------------------------------------- 1 | (* Copyright (C) 2013, Thomas Leonard 2 | * See the README file for details, or visit http://0install.net. 3 | *) 4 | 5 | (** The "0install show" command *) 6 | 7 | open Zeroinstall.General 8 | open Support 9 | open Options 10 | module Qdom = Support.Qdom 11 | module Selections = Zeroinstall.Selections 12 | module Apps = Zeroinstall.Apps 13 | 14 | let show_human config f sels = 15 | Format.fprintf f "%a@." (Zeroinstall.Tree.print config) sels 16 | 17 | let show_xml sels = 18 | let out = Xmlm.make_output @@ `Channel stdout in 19 | Qdom.reindent sels |> Qdom.output out; 20 | output_string stdout "\n" 21 | 22 | let pp_restrictions f = 23 | XString.Map.iter @@ fun iface expr -> 24 | Format.fprintf f "@,%s: %s" iface expr 25 | 26 | let show_restrictions f r = 27 | let open Zeroinstall.Requirements in 28 | if r.extra_restrictions <> XString.Map.empty then ( 29 | Format.fprintf f 30 | "@[User-provided restrictions in force:%a@]@.@." 31 | pp_restrictions r.extra_restrictions 32 | ) 33 | 34 | let handle options flags args = 35 | let s_root = ref false in 36 | let s_xml = ref false in 37 | 38 | Support.Argparse.iter_options flags (function 39 | | #common_option as o -> Common_options.process_common_option options o 40 | | `ShowRoot -> s_root := true 41 | | `ShowXML -> s_xml := true 42 | ); 43 | 44 | let config = options.config in 45 | let system = config.system in 46 | match args with 47 | | [arg] -> ( 48 | let sels = match Apps.lookup_app config arg with 49 | | Some app_path -> 50 | let r = Apps.get_requirements system app_path in 51 | if not !s_xml && not !s_root then 52 | show_restrictions options.stdout r; 53 | Apps.get_selections_no_updates system app_path 54 | | None -> 55 | Selections.load_selections config.system arg in 56 | 57 | match (!s_root, !s_xml) with 58 | | (true, false) -> Format.fprintf options.stdout "%s@." Selections.((root_role sels).iface) 59 | | (false, true) -> show_xml (Selections.as_xml sels) 60 | | (false, false) -> show_human config options.stdout sels 61 | | (true, true) -> Safe_exn.failf "Can't use --xml with --root" 62 | ) 63 | | _ -> raise (Support.Argparse.Usage_error 1) 64 | --------------------------------------------------------------------------------