this repo has no description

Handle error and recovery

Changed files
+51 -12
src
vendor
+20 -1
src/lib/shelter/shelter_main.mli
···
module Store = Store
module History : sig
+
type mode = Void.mode
type post = { diff : Diff.t; time : int64 } [@@deriving repr]
type pre = {
···
include Irmin.Contents.S with type t := t
end
-
include Shelter.Engine.S with type entry = History.t
+
type action =
+
(* Change modes *)
+
| Set_mode of History.mode
+
(* Fork a new branch from an existing one,
+
or switch to a branch if it exists *)
+
| Set_session of string
+
(* Run a command *)
+
| Exec of string list
+
(* Undo the last command *)
+
| Undo
+
(* Replay the current branch onto another *)
+
| Replay of string
+
(* Display info *)
+
| Info of [ `Current | `History ]
+
(* Error state *)
+
| Unknown of string list
+
[@@deriving repr]
+
+
include Shelter.Engine.S with type entry = History.t and type action := action
+23 -11
src/lib/shelter/store.ml
···
let exists = Zfs.exists t.zfs (snap :> string) Zfs.Types.snapshot in
if not exists then Zfs.snapshot t.zfs (snap :> string) true
+
let destroy t (d : Datasets.dataset) =
+
with_dataset t (d :> string) @@ fun ds -> Zfs.destroy ds false
+
let clone t (snap : Datasets.snapshot) (tgt : Datasets.dataset) =
with_dataset ~typ:Zfs.Types.snapshot t (snap :> string) @@ fun src ->
Zfs.clone src (tgt :> string)
···
let cid = cid image in
let cids = cid |> Cid.to_string in
let dataset = Datasets.build t.pool cids in
-
let dir = Eio.Path.(t.fs / ("/" ^ (Datasets.build t.pool cids :> string))) in
-
create_and_mount t dataset;
-
let _dir : string = Fetch.get_image ~dir ~proc:t.proc image in
-
snapshot t (Datasets.snapshot dataset);
let username = Fetch.get_user t.proc image in
-
( cid,
-
Fetch.get_env t.proc image,
-
get_uid_gid ~username Eio.Path.(dir / "rootfs") )
+
let dir = Eio.Path.(t.fs / ("/" ^ (Datasets.build t.pool cids :> string))) in
+
if Zfs.exists t.zfs (dataset :> string) Zfs.Types.dataset then
+
( cid,
+
Fetch.get_env t.proc image,
+
get_uid_gid ~username Eio.Path.(dir / "rootfs") )
+
else (
+
create_and_mount t dataset;
+
let _dir : string = Fetch.get_image ~dir ~proc:t.proc image in
+
snapshot t (Datasets.snapshot dataset);
+
( cid,
+
Fetch.get_env t.proc image,
+
get_uid_gid ~username Eio.Path.(dir / "rootfs") ))
module Run = struct
let with_build t cid fn =
···
(fn (`Exists ("/" ^ (tgt :> string))), diff t src_snap tgt_snap output)
else (
clone t src_snap tgt;
-
let v = with_build t new_cid fn in
-
snapshot t tgt_snap;
-
let d = diff t src_snap tgt_snap output in
-
(v, d))
+
match with_build t new_cid fn with
+
| Error _ as v ->
+
destroy t tgt;
+
(v, [])
+
| Ok _ as v ->
+
snapshot t tgt_snap;
+
let d = diff t src_snap tgt_snap output in
+
(v, d))
end
+1
vendor/zfs/src/function_description.ml
···
(Types.zfs_handle_t @-> string_opt @-> int @-> returning int)
let close = foreign "zfs_close" (Types.zfs_handle_t @-> returning void)
+
let destroy = foreign "zfs_destroy" (Types.zfs_handle_t @-> bool @-> returning int)
let get_type = foreign "zfs_get_type" (Types.zfs_handle_t @-> returning int)
module Nvlist = struct
+4
vendor/zfs/src/zfs.ml
···
let i = C.Functions.create handle path type_ (Nvlist.v props) in
if i != 0 then failwith "Failed to create" else ()
+
let destroy handle recurse =
+
let i = C.Functions.destroy handle recurse in
+
if i != 0 then invalid_arg "destroy" else ()
+
let open_ handle path (type_ : Types.t) = C.Functions.open_ handle path type_
let close : t -> unit = C.Functions.close
let get_type : t -> Types.t = C.Functions.get_type
+3
vendor/zfs/src/zfs.mli
···
val close : t -> unit
(** Close a dataset *)
+
val destroy : t -> bool -> unit
+
(** Destroy a dataset *)
+
val exists : Handle.t -> string -> Types.t -> bool
(** Check if a dataset of a specific type exists *)