This commit is contained in:
parent
aa2ff7b2f0
commit
2f3113f55d
11742 changed files with 1223940 additions and 0 deletions
37
unikernel/duniverse/ocaml-crunch/.github/workflows/main.yml
vendored
Normal file
37
unikernel/duniverse/ocaml-crunch/.github/workflows/main.yml
vendored
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
name: Main workflow
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
schedule:
|
||||
# Prime the caches every Monday
|
||||
- cron: 0 1 * * MON
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os:
|
||||
- macos-latest
|
||||
- windows-latest
|
||||
ocaml-compiler:
|
||||
- 4.08.x
|
||||
- 4.14.x
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Use OCaml ${{ matrix.ocaml-compiler }}
|
||||
uses: ocaml/setup-ocaml@v2
|
||||
with:
|
||||
ocaml-compiler: ${{ matrix.ocaml-compiler }}
|
||||
|
||||
- run: opam install . --deps-only --with-test
|
||||
|
||||
- run: opam exec -- dune build
|
||||
|
||||
- run: opam exec -- dune runtest
|
||||
4
unikernel/duniverse/ocaml-crunch/.gitignore
vendored
Normal file
4
unikernel/duniverse/ocaml-crunch/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
_build/
|
||||
.merlin
|
||||
*.install
|
||||
_opam/
|
||||
3
unikernel/duniverse/ocaml-crunch/.ocamlformat
Normal file
3
unikernel/duniverse/ocaml-crunch/.ocamlformat
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
profile = default
|
||||
version = 0.23.0
|
||||
ocaml-version = 4.08
|
||||
116
unikernel/duniverse/ocaml-crunch/CHANGES.md
Normal file
116
unikernel/duniverse/ocaml-crunch/CHANGES.md
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
## v4.0.0 (2025-02-17)
|
||||
|
||||
* Update to mirage-kv-mem 4.0.0 API changes (fewer functors) (#68 @hannesm)
|
||||
|
||||
## v3.3.1 (2022-08-05)
|
||||
|
||||
* Fixed a regression in v3.3.0 where periods ('.') had to be specified
|
||||
in the extention list. (#62, @MisterDA, fixes #61 reported by @cemerick)
|
||||
|
||||
## v3.3.0 (2022-07-24)
|
||||
|
||||
* Open files in binary mode so buffers don't underread on Windows.
|
||||
(#54, @jonahbeckford)
|
||||
* Always use Unix-style paths for path keys (#58, @MisterDA)
|
||||
* Add -s and --silent flags (#52, #60, @MisterDA)
|
||||
* Add `hash` and `size` functions to the plain module (#53, #60, @MisterDA)
|
||||
* Update to cmdliner 1.1 (#55, @MisterDA)
|
||||
|
||||
## v3.2.0 (2019-12-14)
|
||||
|
||||
* Make crunch reproducible: use a Map.Make(String) instead of Hashtbl.
|
||||
Iterating over the former is guaranteed to be sorted over the keys.
|
||||
(#51 @hannesm)
|
||||
* The state (Map.t) is passed explicit to `scan_file`, `output_implementation`
|
||||
and `walk_directory_tree`. The value `empty` is provided to construct an
|
||||
empty `t`. (#51 @hannesm)
|
||||
|
||||
## v3.1.0 (2019-11-01)
|
||||
|
||||
* Adapt mirage-kv 3.0.0 interface (#50 @hannesm)
|
||||
|
||||
## v3.0.0 (2019-02-28)
|
||||
|
||||
* Implement the mirage-kv 2.0.0 interface, using mirage-kv-mem
|
||||
(#47 @linse @hannesm)
|
||||
* Removed no longer used size function (#47 @linse @hannesm)
|
||||
|
||||
## v2.2.0 (2019-02-05)
|
||||
|
||||
* Port to dune from jbuilder (#46 @hannesm)
|
||||
* use `SOURCE_DATE_EPOCH` instead of gettimeofday if set to
|
||||
support reproducible builds (#45 @xclerc)
|
||||
|
||||
## v2.1.0 (2017-06-24)
|
||||
|
||||
* Port to Jbuilder and simplify test dependencies (#38 by @rgrinberg)
|
||||
|
||||
## v2.0.0 (2016-02-24)
|
||||
|
||||
* Fix reading of files consisting of multiple pages (#30 by @hannesm)
|
||||
* Port to MirageOS3 API: removed unused `id` type (#17), add Failure
|
||||
error type (#20), `connect` does not return a result anymore.
|
||||
* Generate a `mem` function for the filesystem (#18)
|
||||
* Port to topkg and respect the odig packaging convention (#24 via @fgimenez)
|
||||
* Add `LICENSE` file to repository (#19 via @djs55)
|
||||
|
||||
## v1.4.1 (2016-02-08)
|
||||
|
||||
* Use a poor-man `realpath` instead of relying on C bindings which are not
|
||||
available under Cygwin
|
||||
|
||||
## v1.4.0 (2015-03-09)
|
||||
|
||||
* Add an explicit `connect` function to the signature of generated code. (#13)
|
||||
* Use centralised Travis CI scripts.
|
||||
|
||||
## v1.3.0 (2014-03-08)
|
||||
|
||||
* Deduplicate file chunks so that only one copy of each
|
||||
sector is allocated in the static module.
|
||||
|
||||
## v1.2.3 (2013-12-24)
|
||||
|
||||
* Fix compilation of 0-length files.
|
||||
|
||||
## v1.2.2 (2013-12-08)
|
||||
|
||||
* Use the `V1.KV_RO` signature from mirage-types>=0.5.0
|
||||
* Add Travis CI scripts.
|
||||
|
||||
## v1.2.1 (2013-12-08)
|
||||
|
||||
* Generate the correct signature for `V1.KV_RO`.
|
||||
|
||||
## v1.2.0 (2013-12-08)
|
||||
|
||||
* Use the `V1.KV_RO` signature from mirage-types>=0.3.0
|
||||
|
||||
## v1.1.2 (2013-12-07)
|
||||
|
||||
* Do not skip files without an extension.
|
||||
|
||||
## v1.1.1 (2013-12-06)
|
||||
|
||||
* Bugfix release.
|
||||
|
||||
## v1.1.0 (2013-12-05)
|
||||
|
||||
* New release to adapt to the new mirage-types API
|
||||
|
||||
## v0.7.0 (2013-07-21)
|
||||
|
||||
* Add a `-nolwt` output mode which simply uses strings and has
|
||||
no dependence on Lwt. For the modern user who demands ultra-convenience.
|
||||
|
||||
## v0.6.0 (2013-07-09)
|
||||
|
||||
* Adapt output to mirage-platform-0.9.2 Io_page API.
|
||||
|
||||
## v0.5.0 (2013-03-28)
|
||||
|
||||
* Added a -o option (needed for mirari)
|
||||
|
||||
## 0.4.0 (2012-12-20)
|
||||
|
||||
* Initial public release
|
||||
16
unikernel/duniverse/ocaml-crunch/LICENSE.md
Normal file
16
unikernel/duniverse/ocaml-crunch/LICENSE.md
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
(*
|
||||
* Copyright (c) <the authors, see individual headers on files>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
*)
|
||||
10
unikernel/duniverse/ocaml-crunch/Makefile
Normal file
10
unikernel/duniverse/ocaml-crunch/Makefile
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
.PHONY: build clean test
|
||||
|
||||
build:
|
||||
dune build
|
||||
|
||||
test:
|
||||
dune runtest
|
||||
|
||||
clean:
|
||||
dune clean
|
||||
68
unikernel/duniverse/ocaml-crunch/README.md
Normal file
68
unikernel/duniverse/ocaml-crunch/README.md
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
# ocaml-crunch — convert a filesystem into a static OCaml module
|
||||
|
||||
`ocaml-crunch` takes a directory of files and compiles them into a standalone
|
||||
OCaml module which serves the contents directly from memory. This can be
|
||||
convenient for libraries that need a few embedded files (such as a web server)
|
||||
and do not want to deal with all the trouble of file configuration.
|
||||
|
||||
Run `ocaml-crunch --help` for more information:
|
||||
|
||||
```
|
||||
NAME
|
||||
ocaml-crunch - Convert a directory structure into a standalone OCaml
|
||||
module that can serve the file contents without requiring an external
|
||||
filesystem to be present.
|
||||
|
||||
SYNOPSIS
|
||||
ocaml-crunch [--ext=VALID EXTENSION] [--mode=MODE] [--output=OUTPUT]
|
||||
[OPTION]… DIRECTORIES…
|
||||
|
||||
ARGUMENTS
|
||||
DIRECTORIES (required)
|
||||
Directories to recursively walk and crunch.
|
||||
|
||||
OPTIONS
|
||||
-e VALID EXTENSION, --ext=VALID EXTENSION
|
||||
If specified, only these extensions will be included in the
|
||||
crunched output. If not specified, then all files will be crunched
|
||||
into the output module.
|
||||
|
||||
-m MODE, --mode=MODE (absent=lwt)
|
||||
Interface access mode: either lwt or plain. lwt is the default.
|
||||
|
||||
-o OUTPUT, --output=OUTPUT
|
||||
Output file for the OCaml module.
|
||||
|
||||
-s, --silent
|
||||
Silent mode.
|
||||
|
||||
COMMON OPTIONS
|
||||
--help[=FMT] (default=auto)
|
||||
Show this help in format FMT. The value FMT must be one of auto,
|
||||
pager, groff or plain. With auto, the format is pager or plain
|
||||
whenever the TERM env var is dumb or undefined.
|
||||
|
||||
--version
|
||||
Show version information.
|
||||
|
||||
EXIT STATUS
|
||||
ocaml-crunch exits with the following status:
|
||||
|
||||
0 on success.
|
||||
|
||||
123 on indiscriminate errors reported on standard error.
|
||||
|
||||
124 on command line parsing errors.
|
||||
|
||||
125 on unexpected internal errors (bugs).
|
||||
|
||||
ENVIRONMENT
|
||||
These environment variables affect the execution of ocaml-crunch:
|
||||
|
||||
SOURCE_DATE_EPOCH
|
||||
Specifies the last modification of crunched files for reproducible
|
||||
output.
|
||||
|
||||
BUGS
|
||||
Email bug reports to <mirage-devel@lists.xenproject.org>.
|
||||
```
|
||||
47
unikernel/duniverse/ocaml-crunch/crunch.opam
Normal file
47
unikernel/duniverse/ocaml-crunch/crunch.opam
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
version: "4.0.0"
|
||||
opam-version: "2.0"
|
||||
maintainer: "MirageOS team"
|
||||
authors: ["Anil Madhavapeddy" "Thomas Gazagnaire" "Stefanie Schirmer" "Hannes Mehnert"]
|
||||
homepage: "https://github.com/mirage/ocaml-crunch"
|
||||
bug-reports: "https://github.com/mirage/ocaml-crunch/issues"
|
||||
doc: "https://mirage.github.io/ocaml-crunch/"
|
||||
license: "ISC"
|
||||
dev-repo: "git+https://github.com/mirage/ocaml-crunch.git"
|
||||
tags: ["org:mirage" "org:xapi-project"]
|
||||
|
||||
depends: [
|
||||
"ocaml" {>= "4.08.0"}
|
||||
"cmdliner" {>= "1.1"}
|
||||
"ptime"
|
||||
"dune" {>= "2.5"}
|
||||
"lwt" {with-test}
|
||||
"mirage-kv" {with-test & >= "3.0.0"}
|
||||
"mirage-kv-mem" {with-test & >= "4.0.0"}
|
||||
"fmt" {with-test}
|
||||
]
|
||||
conflicts: [
|
||||
"mirage-kv" {< "3.0.0"}
|
||||
"mirage-kv-mem" {< "4.0.0"}
|
||||
]
|
||||
build: [
|
||||
["dune" "subst"] {dev}
|
||||
[
|
||||
"dune"
|
||||
"build"
|
||||
"-p"
|
||||
name
|
||||
"-j"
|
||||
jobs
|
||||
"@install"
|
||||
"@runtest" {with-test}
|
||||
"@doc" {with-doc}
|
||||
]
|
||||
]
|
||||
synopsis: "Convert a filesystem into a static OCaml module"
|
||||
description: """
|
||||
`ocaml-crunch` takes a directory of files and compiles them into a standalone
|
||||
OCaml module which serves the contents directly from memory. This can be
|
||||
convenient for libraries that need a few embedded files (such as a web server)
|
||||
and do not want to deal with all the trouble of file configuration.
|
||||
"""
|
||||
x-maintenance-intent: [ "(latest)" ]
|
||||
3
unikernel/duniverse/ocaml-crunch/dune-project
Normal file
3
unikernel/duniverse/ocaml-crunch/dune-project
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
(lang dune 2.5)
|
||||
(name crunch)
|
||||
(version v4.0.0)
|
||||
227
unikernel/duniverse/ocaml-crunch/src/crunch.ml
Normal file
227
unikernel/duniverse/ocaml-crunch/src/crunch.ml
Normal file
|
|
@ -0,0 +1,227 @@
|
|||
(*
|
||||
* Copyright (c) 2009-2013 Anil Madhavapeddy <anil@recoil.org>
|
||||
* Copyright (c) 2013 Thomas Gazagnaire <thomas@gazagnaire.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*)
|
||||
|
||||
module SM = Map.Make (String)
|
||||
|
||||
type file_info = {
|
||||
chunk_digests : string list;
|
||||
file_digest : string;
|
||||
size : int;
|
||||
}
|
||||
|
||||
type t = string SM.t * file_info SM.t
|
||||
|
||||
let make () = (SM.empty, SM.empty)
|
||||
|
||||
module Filename = struct
|
||||
include Filename
|
||||
|
||||
(* Always use Unix-style filenames for keys *)
|
||||
let dir_sep = "/"
|
||||
let is_dir_sep s i = s.[i] = '/'
|
||||
|
||||
let concat dirname filename =
|
||||
let l = String.length dirname in
|
||||
if l = 0 || is_dir_sep dirname (l - 1) then dirname ^ filename
|
||||
else dirname ^ dir_sep ^ filename
|
||||
end
|
||||
|
||||
(* Walk directory and call walkfn on every file that matches extension ext *)
|
||||
let walk_directory_tree t exts walkfn root_dir =
|
||||
(* Recursive directory walker *)
|
||||
let rec walk_dir dir t =
|
||||
let dh = Unix.opendir dir in
|
||||
let rec repeat t =
|
||||
match Unix.readdir dh with
|
||||
| exception End_of_file -> t
|
||||
| "." | ".." -> repeat t
|
||||
| f -> (
|
||||
let n = Filename.concat dir f in
|
||||
if Sys.is_directory n then repeat (walk_dir n t)
|
||||
else
|
||||
let name = String.sub n 2 (String.length n - 2) in
|
||||
(* If extension list is empty then let all through, otherwise white list *)
|
||||
match (exts, Filename.extension f) with
|
||||
| [], _ -> repeat (walkfn t root_dir name)
|
||||
| exts, e
|
||||
when e <> ""
|
||||
&& List.mem (String.sub e 1 (String.length e - 1)) exts ->
|
||||
repeat (walkfn t root_dir name)
|
||||
| _ -> repeat t)
|
||||
in
|
||||
let result = repeat t in
|
||||
Unix.closedir dh;
|
||||
result
|
||||
in
|
||||
Unix.chdir root_dir;
|
||||
walk_dir "." t
|
||||
|
||||
let now () =
|
||||
try float_of_string (Sys.getenv "SOURCE_DATE_EPOCH")
|
||||
with Not_found -> Unix.gettimeofday ()
|
||||
|
||||
let output_generated_by oc binary =
|
||||
let t = now () in
|
||||
let months =
|
||||
[|
|
||||
"Jan";
|
||||
"Feb";
|
||||
"Mar";
|
||||
"Apr";
|
||||
"May";
|
||||
"Jun";
|
||||
"Jul";
|
||||
"Aug";
|
||||
"Sep";
|
||||
"Oct";
|
||||
"Nov";
|
||||
"Dec";
|
||||
|]
|
||||
in
|
||||
let days = [| "Sun"; "Mon"; "Tue"; "Wed"; "Thu"; "Fri"; "Sat" |] in
|
||||
let time = Unix.gmtime t in
|
||||
let date =
|
||||
Printf.sprintf "%s, %d %s %d %02d:%02d:%02d GMT" days.(time.Unix.tm_wday)
|
||||
time.Unix.tm_mday months.(time.Unix.tm_mon) (time.Unix.tm_year + 1900)
|
||||
time.Unix.tm_hour time.Unix.tm_min time.Unix.tm_sec
|
||||
in
|
||||
Printf.fprintf oc "(* Generated by: %s\n Creation date: %s *)\n\n" binary
|
||||
date
|
||||
|
||||
(** Generate a set of MD5 hashed blocks, abort on collision *)
|
||||
let scan_file (chunk_info, file_info) root name =
|
||||
let full_name = Filename.concat root name in
|
||||
let stats = Unix.stat full_name in
|
||||
let size = stats.Unix.st_size in
|
||||
let fin = open_in_bin full_name in
|
||||
let buf = Buffer.create size in
|
||||
Buffer.add_channel buf fin size;
|
||||
let s = Buffer.contents buf in
|
||||
close_in fin;
|
||||
let rev_chunks = ref [] in
|
||||
let calc_chunk chunk_info b =
|
||||
let digest = Digest.to_hex (Digest.string b) in
|
||||
rev_chunks := digest :: !rev_chunks;
|
||||
match SM.find_opt digest chunk_info with
|
||||
| None -> SM.add digest b chunk_info
|
||||
| Some cur ->
|
||||
if not (String.equal cur b) then
|
||||
failwith ("MD5 hash collision in file " ^ name)
|
||||
else chunk_info
|
||||
in
|
||||
(* Split the file as a series of chunks, of size up to 4096 (to simulate reading sectors) *)
|
||||
let sec = 4096 in
|
||||
(* sector size *)
|
||||
let rec consume idx chunk_info =
|
||||
if idx = size then chunk_info (* EOF *)
|
||||
else if idx + sec < size then
|
||||
let chunk_info' = calc_chunk chunk_info (String.sub s idx sec) in
|
||||
consume (idx + sec) chunk_info'
|
||||
else
|
||||
(* final chunk, short *)
|
||||
calc_chunk chunk_info (String.sub s idx (size - idx))
|
||||
in
|
||||
(* consume fills !rev_chunks as a side effect, so sequentialise this*)
|
||||
let ci = consume 0 chunk_info in
|
||||
let entry =
|
||||
{
|
||||
chunk_digests = List.rev !rev_chunks;
|
||||
file_digest = Digest.(to_hex (string s));
|
||||
size = String.length s;
|
||||
}
|
||||
in
|
||||
(ci, SM.add name entry file_info)
|
||||
|
||||
let output_implementation (chunk_info, file_info) oc =
|
||||
let pf fmt = Printf.fprintf oc fmt in
|
||||
pf "module Internal = struct\n";
|
||||
SM.iter (fun name chunk -> pf " let d_%s = %S\n\n" name chunk) chunk_info;
|
||||
pf " let file_chunks = function\n";
|
||||
SM.iter
|
||||
(fun name { chunk_digests; _ } ->
|
||||
pf " | %S | \"/%s\" -> Some [" name (String.escaped name);
|
||||
List.iter (pf " d_%s;") chunk_digests;
|
||||
pf " ]\n")
|
||||
file_info;
|
||||
pf " | _ -> None\n\n";
|
||||
pf " let file_list = [ ";
|
||||
SM.iter (fun name _ -> pf "%S; " name) file_info;
|
||||
pf "]\n";
|
||||
pf "end\n"
|
||||
|
||||
let output_plain_skeleton_ml (_, file_info) oc =
|
||||
let pf fmt = Printf.fprintf oc fmt in
|
||||
pf
|
||||
{|
|
||||
let file_list = Internal.file_list
|
||||
|
||||
let read name =
|
||||
match Internal.file_chunks name with
|
||||
| None -> None
|
||||
| Some c -> Some (String.concat "" c)
|
||||
|
||||
let hash = function
|
||||
|};
|
||||
SM.iter
|
||||
(fun name { file_digest; _ } ->
|
||||
pf " | %S | \"/%s\" -> Some \"%s\"\n" name (String.escaped name)
|
||||
file_digest)
|
||||
file_info;
|
||||
pf " | _ -> None\n\n";
|
||||
pf "let size = function\n";
|
||||
SM.iter
|
||||
(fun name { size; _ } ->
|
||||
pf " | %S | \"/%s\" -> Some %d\n" name (String.escaped name) size)
|
||||
file_info;
|
||||
pf " | _ -> None\n"
|
||||
|
||||
let output_lwt_skeleton_ml oc =
|
||||
let days, ps =
|
||||
Ptime.Span.to_d_ps
|
||||
@@ Ptime.to_span
|
||||
(match Ptime.of_float_s (now ()) with
|
||||
| None -> assert false
|
||||
| Some x -> x)
|
||||
in
|
||||
Printf.fprintf oc
|
||||
{|
|
||||
open Lwt
|
||||
|
||||
include Mirage_kv_mem
|
||||
|
||||
let file_content name =
|
||||
match Internal.file_chunks name with
|
||||
| None -> Lwt.fail_with ("expected file content, found no blocks " ^ name)
|
||||
| Some blocks -> Lwt.return (String.concat "" blocks)
|
||||
|
||||
let add store name =
|
||||
file_content name >>= fun data ->
|
||||
set store (Mirage_kv.Key.v name) data >>= function
|
||||
| Ok () -> Lwt.return_unit
|
||||
| Error e -> Lwt.fail_with (Fmt.to_to_string pp_write_error e)
|
||||
|
||||
let connect () =
|
||||
connect ~now:(fun () -> Ptime.v (%d, %LdL)) () >>= fun store ->
|
||||
Lwt_list.iter_s (add store) Internal.file_list >|= fun () -> store
|
||||
|}
|
||||
days ps
|
||||
|
||||
let output_lwt_skeleton_mli oc =
|
||||
Printf.fprintf oc {|include Mirage_kv.RO
|
||||
|
||||
val connect : unit -> t Lwt.t
|
||||
|}
|
||||
49
unikernel/duniverse/ocaml-crunch/src/crunch.mli
Normal file
49
unikernel/duniverse/ocaml-crunch/src/crunch.mli
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
(*
|
||||
* Copyright (c) 2009-2013 Anil Madhavapeddy <anil@recoil.org>
|
||||
* Copyright (c) 2013 Thomas Gazagnaire <thomas@gazagnaire.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*)
|
||||
|
||||
(** Expose the contents of a directory as a static filesystem. *)
|
||||
|
||||
type t
|
||||
(** The type of a crunch. *)
|
||||
|
||||
val make : unit -> t
|
||||
(** [make ()] is an empty crunch. *)
|
||||
|
||||
val output_generated_by : out_channel -> string -> unit
|
||||
(** [output_generated_by oc binary_name] generate a comments saying
|
||||
who generates that file. *)
|
||||
|
||||
val scan_file : t -> string -> string -> t
|
||||
(** [scan_file t root file] records the contents of [root]/[file] in [t]. *)
|
||||
|
||||
val output_implementation : t -> out_channel -> unit
|
||||
(** Output the footer. *)
|
||||
|
||||
val output_lwt_skeleton_ml : out_channel -> unit
|
||||
(** Output the Lwt helpers. *)
|
||||
|
||||
val output_lwt_skeleton_mli : out_channel -> unit
|
||||
(** Output the Lwt helpers. *)
|
||||
|
||||
val output_plain_skeleton_ml : t -> out_channel -> unit
|
||||
(** Output a simple skeleton. *)
|
||||
|
||||
val walk_directory_tree :
|
||||
t -> string list -> (t -> string -> string -> t) -> string -> t
|
||||
(** [walk t extensions fn root_dir] traverses all the directory
|
||||
structure starting from [root_dir] and keeping only the [extensions]
|
||||
provided (or do not filter anything if the list is empty). *)
|
||||
28
unikernel/duniverse/ocaml-crunch/src/dune
Normal file
28
unikernel/duniverse/ocaml-crunch/src/dune
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
(library
|
||||
; Dummy library to detect the OCaml version
|
||||
(name realpath)
|
||||
(modules)
|
||||
(enabled_if
|
||||
(< %{ocaml_version} "4.13")))
|
||||
|
||||
(library
|
||||
(name crunch)
|
||||
(wrapped false)
|
||||
(synopsis "Compile static files into a static filesystem")
|
||||
(modules crunch)
|
||||
(public_name crunch)
|
||||
(libraries unix ptime)
|
||||
(flags :standard -safe-string))
|
||||
|
||||
(executable
|
||||
(name main)
|
||||
(modules main realpath)
|
||||
(public_name ocaml-crunch)
|
||||
(libraries
|
||||
cmdliner
|
||||
crunch
|
||||
(select
|
||||
realpath.ml
|
||||
from
|
||||
(realpath -> realpath.pre_413.ml)
|
||||
(-> realpath.unix.ml))))
|
||||
118
unikernel/duniverse/ocaml-crunch/src/main.ml
Normal file
118
unikernel/duniverse/ocaml-crunch/src/main.ml
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
(*
|
||||
* Copyright (c) 2009-2013 Anil Madhavapeddy <anil@recoil.org>
|
||||
* Copyright (c) 2013 Thomas Gazagnaire <thomas@gazagnaire.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*)
|
||||
|
||||
let binary = Sys.argv.(0) |> Filename.basename |> Filename.remove_extension
|
||||
|
||||
let walker output mode dirs exts silent =
|
||||
let log fmt =
|
||||
if silent then Printf.ifprintf stdout fmt
|
||||
else Printf.fprintf stdout (fmt ^^ "%!")
|
||||
in
|
||||
let dirs = List.map Realpath.realpath dirs in
|
||||
let oc =
|
||||
match output with
|
||||
| None -> stdout
|
||||
| Some f ->
|
||||
log "Generating %s\n" f;
|
||||
open_out_bin f
|
||||
in
|
||||
let cwd = Sys.getcwd () in
|
||||
let t =
|
||||
List.fold_left
|
||||
(fun t -> Crunch.walk_directory_tree t exts Crunch.scan_file)
|
||||
(Crunch.make ()) dirs
|
||||
in
|
||||
Crunch.output_generated_by oc binary;
|
||||
Crunch.output_implementation t oc;
|
||||
(match mode with
|
||||
| `Lwt -> Crunch.output_lwt_skeleton_ml oc
|
||||
| `Plain -> Crunch.output_plain_skeleton_ml t oc);
|
||||
close_out oc;
|
||||
match output with
|
||||
| Some f when Filename.check_suffix f ".ml" && mode = `Lwt ->
|
||||
let mli = Filename.chop_extension f ^ ".mli" in
|
||||
log "Generating %s\n" mli;
|
||||
Sys.chdir cwd;
|
||||
let oc = open_out_bin mli in
|
||||
Crunch.output_generated_by oc binary;
|
||||
Crunch.output_lwt_skeleton_mli oc;
|
||||
close_out oc
|
||||
| Some _ -> log "Skipping generation of .mli\n"
|
||||
| None -> ()
|
||||
|
||||
open Cmdliner
|
||||
|
||||
let () =
|
||||
let dirs =
|
||||
Arg.(
|
||||
non_empty & pos_all dir []
|
||||
& info [] ~docv:"DIRECTORIES"
|
||||
~doc:"Directories to recursively walk and crunch.")
|
||||
in
|
||||
let output =
|
||||
Arg.(
|
||||
value
|
||||
& opt (some string) None
|
||||
& info [ "o"; "output" ] ~docv:"OUTPUT"
|
||||
~doc:"Output file for the OCaml module.")
|
||||
in
|
||||
let modes = [ ("lwt", `Lwt); ("plain", `Plain) ] in
|
||||
let mode =
|
||||
Arg.(
|
||||
value
|
||||
& opt (enum modes) `Lwt
|
||||
& info [ "m"; "mode" ] ~docv:"MODE"
|
||||
~doc:
|
||||
(Printf.sprintf
|
||||
"Interface access mode: %s. $(b,lwt) is the default."
|
||||
(Arg.doc_alts_enum modes)))
|
||||
in
|
||||
let exts =
|
||||
Arg.(
|
||||
value & opt_all string []
|
||||
& info [ "e"; "ext" ] ~docv:"VALID EXTENSION"
|
||||
~doc:
|
||||
"If specified, only these extensions will be included in the \
|
||||
crunched output. If not specified, then all files will be \
|
||||
crunched into the output module.")
|
||||
in
|
||||
let quiet = Arg.(value & flag & info [ "s"; "silent" ] ~doc:"Silent mode.") in
|
||||
let cmd_t = Term.(const walker $ output $ mode $ dirs $ exts $ quiet) in
|
||||
let info =
|
||||
let doc =
|
||||
"Convert a directory structure into a standalone OCaml module that can \
|
||||
serve the file contents without requiring an external filesystem to be \
|
||||
present."
|
||||
in
|
||||
let envs =
|
||||
[
|
||||
Cmd.Env.info
|
||||
~doc:
|
||||
"Specifies the last modification of crunched files for \
|
||||
reproducible output."
|
||||
"SOURCE_DATE_EPOCH";
|
||||
]
|
||||
in
|
||||
let man =
|
||||
[
|
||||
`S "BUGS";
|
||||
`P "Email bug reports to <mirage-devel@lists.xenproject.org>.";
|
||||
]
|
||||
in
|
||||
Cmd.info "ocaml-crunch" ~version:"v4.0.0" ~doc ~man ~envs
|
||||
in
|
||||
exit @@ Cmd.eval (Cmd.v info cmd_t)
|
||||
18
unikernel/duniverse/ocaml-crunch/src/realpath.pre_413.ml
Normal file
18
unikernel/duniverse/ocaml-crunch/src/realpath.pre_413.ml
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
(* poor-man reimplementation of realpath, from OPAM's system library *)
|
||||
let realpath p =
|
||||
let getchdir s =
|
||||
let p = Sys.getcwd () in
|
||||
Sys.chdir s;
|
||||
p
|
||||
in
|
||||
let normalize s = getchdir (getchdir s) in
|
||||
if Filename.is_relative p then
|
||||
match Sys.is_directory p with
|
||||
| exception Sys_error _ -> p
|
||||
| true -> normalize p
|
||||
| false -> (
|
||||
let dir = normalize (Filename.dirname p) in
|
||||
match Filename.basename p with
|
||||
| "." -> dir
|
||||
| base -> Filename.concat dir base)
|
||||
else p
|
||||
1
unikernel/duniverse/ocaml-crunch/src/realpath.unix.ml
Normal file
1
unikernel/duniverse/ocaml-crunch/src/realpath.unix.ml
Normal file
|
|
@ -0,0 +1 @@
|
|||
let realpath = Unix.realpath
|
||||
1
unikernel/duniverse/ocaml-crunch/test/.gitattributes
vendored
Normal file
1
unikernel/duniverse/ocaml-crunch/test/.gitattributes
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
/t1/** text eol=lf
|
||||
|
|
@ -0,0 +1 @@
|
|||
*.expected.*
|
||||
42
unikernel/duniverse/ocaml-crunch/test/consumer.ml
Normal file
42
unikernel/duniverse/ocaml-crunch/test/consumer.ml
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
open Lwt.Infix
|
||||
|
||||
let key s = Mirage_kv.Key.v s
|
||||
|
||||
let size t1 key =
|
||||
T1.get t1 key >|= function Ok r -> Ok (String.length r) | Error e -> Error e
|
||||
|
||||
let main =
|
||||
T1.connect () >>= fun src ->
|
||||
(T1.get src (key "a.ext") >|= function
|
||||
| Ok res ->
|
||||
if res = "foo\n" then print_endline "read a.ext successfully"
|
||||
else Fmt.failwith "unexpected read value, expecting foo, read: %s" res
|
||||
| Error e -> Fmt.failwith "error while reading 'a.ext': %a" T1.pp_error e)
|
||||
>>= fun () ->
|
||||
(size src (key "c") >>= function
|
||||
| Error _ -> Fmt.failwith "error while calling size on 'c'"
|
||||
| Ok l ->
|
||||
if l = 4100 then
|
||||
T1.get src (key "c") >|= function
|
||||
| Error e -> Fmt.failwith "error while reading 'c': %a" T1.pp_error e
|
||||
| Ok _ -> print_endline "read 'c' successfully"
|
||||
else failwith "invalid size while reading 'c'")
|
||||
>>= fun () ->
|
||||
(size src (key "d") >>= function
|
||||
| Error e -> Fmt.failwith "error while calling size on 'd': %a" T1.pp_error e
|
||||
| Ok l ->
|
||||
if l = 12300 then
|
||||
T1.get src (key "d") >|= function
|
||||
| Error e -> Fmt.failwith "error while reading 'd': %a" T1.pp_error e
|
||||
| Ok _ -> print_endline "read 'd' successfully"
|
||||
else Fmt.failwith "invalid size while reading 'd'")
|
||||
>>= fun () ->
|
||||
T1.get src (key "e/f") >|= function
|
||||
| Error e -> Fmt.failwith "error while reading 'd': %a" T1.pp_error e
|
||||
| Ok data ->
|
||||
if data = "hallohallo\n" then print_endline "read e/f successfully"
|
||||
else
|
||||
Fmt.failwith "unexpected read value, expecting hallohallo, read: %s"
|
||||
data
|
||||
|
||||
let () = Lwt_main.run main
|
||||
37
unikernel/duniverse/ocaml-crunch/test/dune
Normal file
37
unikernel/duniverse/ocaml-crunch/test/dune
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
(rule
|
||||
(targets t1.ml t1.mli t1_plain.ml t1_plain_ext.ml)
|
||||
(deps
|
||||
(source_tree t1))
|
||||
(action
|
||||
(setenv
|
||||
SOURCE_DATE_EPOCH
|
||||
0
|
||||
(progn
|
||||
(run %{bin:ocaml-crunch} --mode=lwt -o t1.ml t1)
|
||||
(run %{bin:ocaml-crunch} --mode=plain -o t1_plain.ml t1)
|
||||
(run %{bin:ocaml-crunch} --mode=plain -e ext -o t1_plain_ext.ml t1)))))
|
||||
|
||||
(rule
|
||||
(alias runtest)
|
||||
(action
|
||||
(diff t1.expected.ml t1.ml)))
|
||||
|
||||
(rule
|
||||
(alias runtest)
|
||||
(action
|
||||
(diff t1.expected.mli t1.mli)))
|
||||
|
||||
(rule
|
||||
(alias runtest)
|
||||
(action
|
||||
(diff t1_plain.expected.ml t1_plain.ml)))
|
||||
|
||||
(rule
|
||||
(alias runtest)
|
||||
(action
|
||||
(diff t1_plain_ext.expected.ml t1_plain_ext.ml)))
|
||||
|
||||
(test
|
||||
(name consumer)
|
||||
(libraries lwt.unix mirage-kv lwt mirage-kv-mem)
|
||||
(modules t1 consumer))
|
||||
51
unikernel/duniverse/ocaml-crunch/test/t1.expected.ml
Normal file
51
unikernel/duniverse/ocaml-crunch/test/t1.expected.ml
Normal file
File diff suppressed because one or more lines are too long
6
unikernel/duniverse/ocaml-crunch/test/t1.expected.mli
Normal file
6
unikernel/duniverse/ocaml-crunch/test/t1.expected.mli
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
(* Generated by: ocaml-crunch
|
||||
Creation date: Thu, 1 Jan 1970 00:00:00 GMT *)
|
||||
|
||||
include Mirage_kv.RO
|
||||
|
||||
val connect : unit -> t Lwt.t
|
||||
1
unikernel/duniverse/ocaml-crunch/test/t1/a.ext
Normal file
1
unikernel/duniverse/ocaml-crunch/test/t1/a.ext
Normal file
|
|
@ -0,0 +1 @@
|
|||
foo
|
||||
1
unikernel/duniverse/ocaml-crunch/test/t1/b
Normal file
1
unikernel/duniverse/ocaml-crunch/test/t1/b
Normal file
|
|
@ -0,0 +1 @@
|
|||
bar
|
||||
1
unikernel/duniverse/ocaml-crunch/test/t1/c
Normal file
1
unikernel/duniverse/ocaml-crunch/test/t1/c
Normal file
|
|
@ -0,0 +1 @@
|
|||
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
|
||||
BIN
unikernel/duniverse/ocaml-crunch/test/t1/d
Normal file
BIN
unikernel/duniverse/ocaml-crunch/test/t1/d
Normal file
Binary file not shown.
1
unikernel/duniverse/ocaml-crunch/test/t1/e/f
Normal file
1
unikernel/duniverse/ocaml-crunch/test/t1/e/f
Normal file
|
|
@ -0,0 +1 @@
|
|||
hallohallo
|
||||
55
unikernel/duniverse/ocaml-crunch/test/t1_plain.expected.ml
Normal file
55
unikernel/duniverse/ocaml-crunch/test/t1_plain.expected.ml
Normal file
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,27 @@
|
|||
(* Generated by: ocaml-crunch
|
||||
Creation date: Thu, 1 Jan 1970 00:00:00 GMT *)
|
||||
|
||||
module Internal = struct
|
||||
let d_d3b07384d113edec49eaa6238ad5ff00 = "foo\n"
|
||||
|
||||
let file_chunks = function
|
||||
| "a.ext" | "/a.ext" -> Some [ d_d3b07384d113edec49eaa6238ad5ff00; ]
|
||||
| _ -> None
|
||||
|
||||
let file_list = [ "a.ext"; ]
|
||||
end
|
||||
|
||||
let file_list = Internal.file_list
|
||||
|
||||
let read name =
|
||||
match Internal.file_chunks name with
|
||||
| None -> None
|
||||
| Some c -> Some (String.concat "" c)
|
||||
|
||||
let hash = function
|
||||
| "a.ext" | "/a.ext" -> Some "d3b07384d113edec49eaa6238ad5ff00"
|
||||
| _ -> None
|
||||
|
||||
let size = function
|
||||
| "a.ext" | "/a.ext" -> Some 4
|
||||
| _ -> None
|
||||
Loading…
Add table
Add a link
Reference in a new issue