Implement {set,remove,rename}_and_push and delete push function

All of these actions "shallow" the last commit. A subsequent `push`
will do nothing due to that incapacity to walk through the history
due to the shallowed commit. To be able to push the last change,
we must provide {set,remove,rename} functions with an explicit
call to push **before** the "shallow".
This commit is contained in:
Romain Calascibetta 2022-10-22 00:17:56 +02:00
parent 4734261144
commit d1cfefb53b
2 changed files with 35 additions and 25 deletions

View file

@ -92,12 +92,6 @@ let pull t =
t.head <- Some head; t.head <- Some head;
Lwt.return (Ok diff) Lwt.return (Ok diff)
let push t =
let open Lwt.Infix in
Sync.push ~capabilities ~ctx:t.ctx t.edn t.store [ `Update (t.branch, t.branch) ]
>|= Result.map_error (fun err -> `Msg (Fmt.str "error pushing branch %a: %a"
Git.Reference.pp t.branch Sync.pp_error err))
let connect ctx endpoint = let connect ctx endpoint =
let open Lwt.Infix in let open Lwt.Infix in
init_store () >>= fun store -> init_store () >>= fun store ->
@ -486,7 +480,7 @@ module Make (Pclock : Mirage_clock.PCLOCK) = struct
unroll_tree t ?head (name, hash) rest unroll_tree t ?head (name, hash) rest
| _ -> assert false ) | _ -> assert false )
let set t key contents = let set ?(push= false) t key contents =
let segs = Mirage_kv.Key.segments key in let segs = Mirage_kv.Key.segments key in
let now () = Int64.of_float (Ptime.to_float_s (Ptime.v (Pclock.now_d_ps ()))) in let now () = Int64.of_float (Ptime.to_float_s (Ptime.v (Pclock.now_d_ps ()))) in
match segs with match segs with
@ -504,6 +498,11 @@ module Make (Pclock : Mirage_clock.PCLOCK) = struct
let commit = Store.Value.Commit.make ~tree:tree_root_hash ~author ~committer let commit = Store.Value.Commit.make ~tree:tree_root_hash ~author ~committer
~parents (Some "Committed by git-kv") in ~parents (Some "Committed by git-kv") in
Store.write t.store (Git.Value.Commit commit) >>= fun (hash, _) -> Store.write t.store (Git.Value.Commit commit) >>= fun (hash, _) ->
Lwt.Infix.(if push then
Sync.push ~capabilities ~ctx:t.ctx t.edn t.store [ `Update (t.branch, t.branch) ]
>|= Result.map_error (fun err -> `Msg (Fmt.str "error pushing branch %a: %a"
Git.Reference.pp t.branch Sync.pp_error err))
else Lwt.return_ok ()) >>= fun () ->
Lwt.Infix.(Store.shallow t.store hash >|= Result.ok) >>= fun () -> Lwt.Infix.(Store.shallow t.store hash >|= Result.ok) >>= fun () ->
t.head <- Some hash ; Lwt.return_ok () t.head <- Some hash ; Lwt.return_ok ()
@ -513,9 +512,9 @@ module Make (Pclock : Mirage_clock.PCLOCK) = struct
| `Msg err -> `Msg err | `Msg err -> `Msg err
| err -> Rresult.R.msgf "%a" Store.pp_error err | err -> Rresult.R.msgf "%a" Store.pp_error err
let set t key contents = let set ?push t key contents =
let open Lwt.Infix in let open Lwt.Infix in
set t key contents >|= Rresult.R.reword_error to_write_error set ?push t key contents >|= Rresult.R.reword_error to_write_error
let set_partial t key ~offset chunk = let set_partial t key ~offset chunk =
let open Lwt_result.Infix in let open Lwt_result.Infix in
@ -529,7 +528,7 @@ module Make (Pclock : Mirage_clock.PCLOCK) = struct
let batch t ?retries:_ f = f t let batch t ?retries:_ f = f t
let remove t key = let remove ?(push= false) t key =
let segs = Mirage_kv.Key.segments key in let segs = Mirage_kv.Key.segments key in
let now () = Int64.of_float (Ptime.to_float_s (Ptime.v (Pclock.now_d_ps ()))) in let now () = Int64.of_float (Ptime.to_float_s (Ptime.v (Pclock.now_d_ps ()))) in
match List.rev segs, t.head with match List.rev segs, t.head with
@ -548,6 +547,11 @@ module Make (Pclock : Mirage_clock.PCLOCK) = struct
let commit = Store.Value.Commit.make ~tree:tree_root_hash ~author ~committer let commit = Store.Value.Commit.make ~tree:tree_root_hash ~author ~committer
~parents:[ head ] (Some "Committed by git-kv") in ~parents:[ head ] (Some "Committed by git-kv") in
Store.write t.store (Git.Value.Commit commit) >>= fun (hash, _) -> Store.write t.store (Git.Value.Commit commit) >>= fun (hash, _) ->
Lwt.Infix.(if push then
Sync.push ~capabilities ~ctx:t.ctx t.edn t.store [ `Update (t.branch, t.branch) ]
>|= Result.map_error (fun err -> `Msg (Fmt.str "error pushing branch %a: %a"
Git.Reference.pp t.branch Sync.pp_error err))
else Lwt.return_ok ()) >>= fun () ->
Lwt.Infix.(Store.shallow t.store hash >|= Result.ok) >>= fun () -> Lwt.Infix.(Store.shallow t.store hash >|= Result.ok) >>= fun () ->
t.head <- Some hash ; Lwt.return_ok () t.head <- Some hash ; Lwt.return_ok ()
| name :: pred_name :: rest, Some head -> | name :: pred_name :: rest, Some head ->
@ -565,18 +569,30 @@ module Make (Pclock : Mirage_clock.PCLOCK) = struct
let commit = Store.Value.Commit.make ~tree:tree_root_hash ~author ~committer let commit = Store.Value.Commit.make ~tree:tree_root_hash ~author ~committer
~parents:[ head ] (Some "Committed by git-kv") in ~parents:[ head ] (Some "Committed by git-kv") in
Store.write t.store (Git.Value.Commit commit) >>= fun (hash, _) -> Store.write t.store (Git.Value.Commit commit) >>= fun (hash, _) ->
Lwt.Infix.(if push then
Sync.push ~capabilities ~ctx:t.ctx t.edn t.store [ `Update (t.branch, t.branch) ]
>|= Result.map_error (fun err -> `Msg (Fmt.str "error pushing branch %a: %a"
Git.Reference.pp t.branch Sync.pp_error err))
else Lwt.return_ok ()) >>= fun () ->
Lwt.Infix.(Store.shallow t.store hash >|= Result.ok) >>= fun () -> Lwt.Infix.(Store.shallow t.store hash >|= Result.ok) >>= fun () ->
t.head <- Some hash ; Lwt.return_ok () t.head <- Some hash ; Lwt.return_ok ()
| _ -> Lwt.return_ok () | _ -> Lwt.return_ok ()
let remove t key = let remove ?push t key =
let open Lwt.Infix in let open Lwt.Infix in
remove t key >|= Rresult.R.reword_error to_write_error remove ?push t key >|= Rresult.R.reword_error to_write_error
let rename t ~source ~dest = let rename ?(push= false) t ~source ~dest =
(* TODO(dinosaure): optimize it! It was done on the naive way. *) (* TODO(dinosaure): optimize it! It was done on the naive way. *)
let open Lwt_result.Infix in let open Lwt_result.Infix in
get t source >>= fun contents -> get t source >>= fun contents ->
remove t source >>= fun () -> remove ~push t source >>= fun () ->
set t dest contents set ~push t dest contents
let set_and_push t k v = set ~push:true t k v
let set t k v = set ~push:false t k v
let remove_and_push t k = remove ~push:true t k
let remove t k = remove ~push:false t k
let rename_and_push t ~source ~dest = rename ~push:true t ~source ~dest
let rename t ~source ~dest = rename ~push:false t ~source ~dest
end end

View file

@ -51,16 +51,6 @@ val pull : t -> (change list, [> `Msg of string ]) result Lwt.t
[store] Git repository. It returns a list of changes between the old state [store] Git repository. It returns a list of changes between the old state
of your store and what you have remotely. *) of your store and what you have remotely. *)
val push : t -> (unit, [> `Msg of string ]) result Lwt.t
(** [push store] tries to push any changes from your local Git repository
[store] to the remoe Git repository. The [push] function can fails for many
reasons. Currently, we don't handle merge politics and how we can resolve
conflicts between local and remote Git repositories. That mostly means that
if you are the only one who push to the Git repository (into a specific
branch), everything should be fine. But, if someone else push into the same
remote Git repository, your change can be discarded by the remote server
(due to conflicts). *)
module Make (Pclock : Mirage_clock.PCLOCK) : sig module Make (Pclock : Mirage_clock.PCLOCK) : sig
include Mirage_kv.RW include Mirage_kv.RW
with type t = t with type t = t
@ -68,4 +58,8 @@ module Make (Pclock : Mirage_clock.PCLOCK) : sig
| `Hash_not_found of Digestif.SHA1.t | `Hash_not_found of Digestif.SHA1.t
| `Reference_not_found of Git.Reference.t | `Reference_not_found of Git.Reference.t
| Mirage_kv.write_error ] | Mirage_kv.write_error ]
val set_and_push : t -> key -> string -> (unit, write_error) result Lwt.t
val remove_and_push : t -> key -> (unit, write_error) result Lwt.t
val rename_and_push : t -> source:key -> dest:key -> (unit, write_error) result Lwt.t
end end