Skip to content

Commit 4bdda2d

Browse files
committed
Add a ~p parameter to Patch.to_diffs mimicking the behaviour of patch -p<num>
1 parent 8cb4d08 commit 4bdda2d

File tree

2 files changed

+30
-20
lines changed

2 files changed

+30
-20
lines changed

src/patch.ml

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ module String = struct
4141
let length = String.length
4242

4343
let equal = String.equal
44+
45+
let index_from = String.index_from
46+
47+
let sub = String.sub
4448
end
4549

4650
type hunk = {
@@ -219,36 +223,42 @@ let pp ~git ppf t =
219223
pp_operation ~git ppf t.operation ;
220224
List.iter (pp_hunk ppf) t.hunks
221225

222-
let operation_of_strings git mine their =
226+
let operation_of_strings ~p mine their =
227+
let open (struct
228+
type t =
229+
| Dev_null
230+
| Ignore
231+
| File of string
232+
end) in
223233
let get_filename_opt n =
224234
let s = match String.cut '\t' n with None -> n | Some (x, _) -> x in
225-
if s = no_file then None else
226-
if git && (String.is_prefix ~prefix:"a/" s || String.is_prefix ~prefix:"b/" s) then
227-
Some (String.slice ~start:2 s)
228-
else Some s
235+
if s = no_file then Dev_null else
236+
let rec iter idx = function
237+
| 0 -> String.sub s idx (String.length s - idx)
238+
| p -> iter (String.index_from s idx '/') (p - 1)
239+
in
240+
try File (iter 0 p) with Not_found -> Ignore
229241
in
230242
match get_filename_opt mine, get_filename_opt their with
231-
| None, Some n -> Create n
232-
| Some n, None -> Delete n
233-
| Some a, Some b -> if String.equal a b then Edit a else Rename (a, b)
234-
| None, None -> assert false (* ??!?? *)
243+
| Dev_null, File n -> Some (Create n)
244+
| File n, Dev_null -> Some (Delete n)
245+
| File a, File b -> Some (if String.equal a b then Edit a else Rename (a, b))
246+
| Dev_null, Dev_null | Ignore, _ | _, Ignore -> None
235247

236248
(* parses a list of lines to a diff.t list *)
237-
let to_diff data =
249+
let to_diff ~p data =
238250
(* first locate --- and +++ lines *)
239-
let rec find_start git ?hdr = function
251+
let rec find_start ?hdr = function
240252
| [] -> hdr, []
241-
| x::xs when String.is_prefix ~prefix:"diff --git " x ->
242-
begin match hdr with None -> find_start true xs | Some _ -> hdr, x::xs end
243253
| x::y::xs when String.is_prefix ~prefix:"rename from " x && String.is_prefix ~prefix:"rename to " y ->
244254
let hdr = Rename_only (String.slice ~start:12 x, String.slice ~start:10 y) in
245-
find_start git ~hdr xs
255+
find_start ~hdr xs
246256
| x::y::xs when String.is_prefix ~prefix:"--- " x ->
247257
let mine = String.slice ~start:4 x and their = String.slice ~start:4 y in
248-
Some (operation_of_strings git mine their), xs
249-
| _::xs -> find_start git ?hdr xs
258+
operation_of_strings ~p mine their, xs
259+
| _::xs -> find_start ?hdr xs
250260
in
251-
match find_start false data with
261+
match find_start data with
252262
| Some (Rename_only _ as operation), rest ->
253263
let hunks = [] and mine_no_nl = false and their_no_nl = false in
254264
Some ({ operation ; hunks ; mine_no_nl ; their_no_nl }, rest)
@@ -260,11 +270,11 @@ let to_diff data =
260270

261271
let to_lines = String.cuts '\n'
262272

263-
let to_diffs data =
273+
let to_diffs ~p data =
264274
let lines = to_lines data in
265275
let rec doit acc = function
266276
| [] -> List.rev acc
267-
| xs -> match to_diff xs with
277+
| xs -> match to_diff ~p xs with
268278
| None -> List.rev acc
269279
| Some (diff, rest) -> doit (diff :: acc) rest
270280
in

src/patch.mli

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,6 @@ type t = {
2929

3030
val pp : git:bool -> Format.formatter -> t -> unit
3131

32-
val to_diffs : string -> t list
32+
val to_diffs : p:int -> string -> t list
3333

3434
val patch : string option -> t -> string option

0 commit comments

Comments
 (0)