Source file conex_diff_provider.ml

1
2
3
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
open Conex_utils
open Conex_io
open Conex_diff

let apply provider diff =
  let read path =
    if file diff = path_to_string path then
      match provider.read path with
      | Ok data -> Ok (patch (Some data) diff)
      | Error _ -> Ok (patch None diff)
    else
      provider.read path
  and file_type path =
    let pn = path_to_string path
    and name = file diff
    in
    if pn = name then
      Ok File
    else if Conex_utils.String.is_prefix ~prefix:(pn ^ "/") name then
      Ok Directory
    else
      provider.file_type path
  and read_dir path =
    let rec strip parent x = match parent, x with
      | [], xs -> Some xs
      | hd::tl, hd'::tl' when hd = hd' -> strip tl tl'
      | _ -> None
    in
    let local =
      match string_to_path (file diff) with
      | Ok p ->
        begin match strip path p with
          | None -> None
          | Some [] -> None
          | Some [ x ] -> Some (File, x)
          | Some (x::_) -> Some (Directory, x)
        end
      | Error _ -> None
    in
    match provider.read_dir path, local with
      | Ok files, Some data -> Ok (data :: files)
      | Ok files, None -> Ok files
      | Error _, Some data -> Ok [data]
      | Error e, None -> Error e
  and write _ _ = Error "read only"
  and exists path =
    let pn = path_to_string path
    and name = file diff
    in
    if pn = name then
      true
    else
      provider.exists path
  and basedir = provider.basedir
  and description = "Patch provider"
  in
  { basedir ; description ; file_type ; read ; write ; read_dir ; exists }

let apply_diff io data =
    let diffs = Conex_diff.to_diffs data in
    (List.fold_left apply io diffs, diffs)