Skip to content

Commit 020d9a5

Browse files
authored
Merge pull request #89 from mbarbin/files-with-curly-braces
Files with curly braces
2 parents 2222653 + 2366210 commit 020d9a5

11 files changed

+522
-15
lines changed

CHANGES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
### Fixed
1212

13+
- Improve handling of diff when filenames have curly-braces (#89, @mbarbin).
1314
- Handle file type changes in `name-status` diff computation (#88, @mbarbin).
1415
- Allow char '#' in branch names (#88, @mbarbin).
1516

lib/volgo_git_backend/src/munged_path.ml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,12 @@ let parse_exn str =
4646
| '{' | '}' -> true
4747
| _ -> false)
4848
then
49-
raise (Err.E (Err.create [ Pp.text "Unexpected '{' or '}' in simple path." ]))
49+
(* Files with these characters are actually useful, such as in some
50+
templating systems. *)
51+
One_file (Vcs.Path_in_repo.v str)
5052
else One_file (Vcs.Path_in_repo.v str)
5153
| [ left; right ] ->
52-
(match String.rsplit2 left ~on:'{' with
54+
(match String.lsplit2 left ~on:'{' with
5355
| None ->
5456
if
5557
String.exists str ~f:(function
@@ -60,7 +62,7 @@ let parse_exn str =
6062
Two_files { src = Vcs.Path_in_repo.v left; dst = Vcs.Path_in_repo.v right }
6163
| Some (prefix, left_of_arrow) ->
6264
let right_of_arrow, suffix =
63-
match String.lsplit2 right ~on:'}' with
65+
match String.rsplit2 right ~on:'}' with
6466
| Some split -> split
6567
| None -> raise (Err.E (Err.create [ Pp.text "Matching '}' not found." ]))
6668
in

lib/volgo_git_backend/test/dune

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,13 @@
6262

6363
(rule
6464
(copy %{project_root}/test/data/eio.num-status eio.num-status))
65+
66+
(rule
67+
(copy
68+
%{project_root}/test/data/opam-package-template.name-status
69+
opam-package-template.name-status))
70+
71+
(rule
72+
(copy
73+
%{project_root}/test/data/opam-package-template.num-status
74+
opam-package-template.num-status))

lib/volgo_git_backend/test/test__munged_path.ml

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -42,18 +42,12 @@ let%expect_test "parse" =
4242
Volgo_git_backend.Munged_path.parse_exn ((path "tmp => tmp2 => tmp3"))))
4343
(error "Too many ['=>']."))
4444
|}];
45-
require_does_raise [%here] (fun () -> test "}");
46-
[%expect
47-
{|
48-
((context (Volgo_git_backend.Munged_path.parse_exn ((path }))))
49-
(error "Unexpected '{' or '}' in simple path."))
50-
|}];
51-
require_does_raise [%here] (fun () -> test "{");
52-
[%expect
53-
{|
54-
((context (Volgo_git_backend.Munged_path.parse_exn ((path {))))
55-
(error "Unexpected '{' or '}' in simple path."))
56-
|}];
45+
require_does_not_raise [%here] (fun () -> test "}");
46+
[%expect {| (One_file }) |}];
47+
require_does_not_raise [%here] (fun () -> test "{");
48+
[%expect {| (One_file {) |}];
49+
require_does_not_raise [%here] (fun () -> test "template/with-with-{{ variable }}.txt");
50+
[%expect {| (One_file "template/with-with-{{ variable }}.txt") |}];
5751
require_does_raise [%here] (fun () -> test "a/{dir => b");
5852
[%expect
5953
{|

lib/volgo_git_backend/test/test__name_status.ml

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,3 +303,63 @@ let%expect_test "parse_lines_exn" =
303303
|}];
304304
()
305305
;;
306+
307+
let%expect_test "parse_exn" =
308+
Eio_main.run
309+
@@ fun env ->
310+
let path = Eio.Path.(Eio.Stdenv.fs env / "opam-package-template.name-status") in
311+
let contents = Eio.Path.load path in
312+
let lines = String.split_lines contents in
313+
let name_status = Volgo_git_backend.Name_status.parse_lines_exn ~lines in
314+
print_s [%sexp (name_status : Vcs.Name_status.t)];
315+
[%expect
316+
{|
317+
((Modified .github/workflows/ci.yml)
318+
(Modified example/.github/workflows/ci.yml)
319+
(Modified example/.ocamlformat)
320+
(Modified example/LICENSE)
321+
(Modified example/bin/dune)
322+
(Modified example/dune-project)
323+
(Added example/example-dev.opam)
324+
(Modified example/example-tests.opam)
325+
(Modified example/example.opam)
326+
(Added example/example.opam.template)
327+
(Modified example/lib/example/test/dune)
328+
(Modified template/.ocamlformat)
329+
(Modified template/LICENSE)
330+
(Modified template/bin/dune)
331+
(Modified template/dune-project)
332+
(Modified template/github/workflows/ci.yml)
333+
(Modified "template/lib/{{ project_snake }}/test/dune")
334+
(Added "template/{{ project_slug }}-dev.opam")
335+
(Modified "template/{{ project_slug }}-tests.opam")
336+
(Modified "template/{{ project_slug }}.opam")
337+
(Added "template/{{ project_slug }}.opam.template"))
338+
|}];
339+
print_s [%sexp (Vcs.Name_status.files name_status : Vcs.Path_in_repo.t list)];
340+
[%expect
341+
{|
342+
(.github/workflows/ci.yml
343+
example/.github/workflows/ci.yml
344+
example/.ocamlformat
345+
example/LICENSE
346+
example/bin/dune
347+
example/dune-project
348+
example/example-dev.opam
349+
example/example-tests.opam
350+
example/example.opam
351+
example/example.opam.template
352+
example/lib/example/test/dune
353+
template/.ocamlformat
354+
template/LICENSE
355+
template/bin/dune
356+
template/dune-project
357+
template/github/workflows/ci.yml
358+
"template/lib/{{ project_snake }}/test/dune"
359+
"template/{{ project_slug }}-dev.opam"
360+
"template/{{ project_slug }}-tests.opam"
361+
"template/{{ project_slug }}.opam"
362+
"template/{{ project_slug }}.opam.template")
363+
|}];
364+
()
365+
;;

lib/volgo_git_backend/test/test__num_status.ml

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,9 @@ let%expect_test "parse_lines_exn" =
469469
; "7\t-\tfile"
470470
; "-2\t-10\tfile"
471471
; "1985\t0\tfile1 => /tmp/file2"
472+
; "12\t6\ttemplate/{{ project_slug }}.opam"
473+
; "12\t6\ttemplate/{{{ project_slug }}.opam => pkg.template.opam}"
474+
; "12\t6\ttemplate/{{{ project_slug }} => pkg}.opam"
472475
]
473476
in
474477
List.iter lines ~f:(fun line ->
@@ -555,6 +558,152 @@ let%expect_test "parse_lines_exn" =
555558
((line "1985\t0\tfile1 => /tmp/file2")))
556559
(Volgo_git_backend.Munged_path.parse_exn ((path "file1 => /tmp/file2"))))
557560
(error (Invalid_argument "\"/tmp/file2\": not a relative path")))))
561+
("12\t6\ttemplate/{{ project_slug }}.opam" (
562+
Ok (
563+
(key (One_file "template/{{ project_slug }}.opam"))
564+
(num_stat (
565+
Num_lines_in_diff (
566+
(insertions 12)
567+
(deletions 6)))))))
568+
("12\t6\ttemplate/{{{ project_slug }}.opam => pkg.template.opam}"
569+
(Ok (
570+
(key (
571+
Two_files
572+
(src "template/{{ project_slug }}.opam")
573+
(dst template/pkg.template.opam)))
574+
(num_stat (
575+
Num_lines_in_diff (
576+
(insertions 12)
577+
(deletions 6)))))))
578+
("12\t6\ttemplate/{{{ project_slug }} => pkg}.opam"
579+
(Ok (
580+
(key (
581+
Two_files
582+
(src "template/{{ project_slug }}.opam")
583+
(dst template/pkg.opam)))
584+
(num_stat (
585+
Num_lines_in_diff (
586+
(insertions 12)
587+
(deletions 6)))))))
588+
|}];
589+
()
590+
;;
591+
592+
let%expect_test "parse_exn - opam-package-template" =
593+
Eio_main.run
594+
@@ fun env ->
595+
let path = Eio.Path.(Eio.Stdenv.fs env / "opam-package-template.num-status") in
596+
let contents = Eio.Path.load path in
597+
let lines = String.split_lines contents in
598+
let num_status = Volgo_git_backend.Num_status.parse_lines_exn ~lines in
599+
print_s [%sexp (num_status : Vcs.Num_status.t)];
600+
[%expect
601+
{|
602+
(((key (One_file .github/workflows/ci.yml))
603+
(num_stat (
604+
Num_lines_in_diff (
605+
(insertions 1)
606+
(deletions 1)))))
607+
((key (One_file example/.github/workflows/ci.yml))
608+
(num_stat (
609+
Num_lines_in_diff (
610+
(insertions 9)
611+
(deletions 5)))))
612+
((key (One_file example/.ocamlformat))
613+
(num_stat (
614+
Num_lines_in_diff (
615+
(insertions 3)
616+
(deletions 1)))))
617+
((key (One_file example/LICENSE))
618+
(num_stat (
619+
Num_lines_in_diff (
620+
(insertions 1)
621+
(deletions 1)))))
622+
((key (One_file example/bin/dune))
623+
(num_stat (
624+
Num_lines_in_diff (
625+
(insertions 1)
626+
(deletions 1)))))
627+
((key (One_file example/dune-project))
628+
(num_stat (
629+
Num_lines_in_diff (
630+
(insertions 86)
631+
(deletions 20)))))
632+
((key (One_file example/example-dev.opam))
633+
(num_stat (
634+
Num_lines_in_diff (
635+
(insertions 49)
636+
(deletions 0)))))
637+
((key (One_file example/example-tests.opam))
638+
(num_stat (
639+
Num_lines_in_diff (
640+
(insertions 4)
641+
(deletions 7)))))
642+
((key (One_file example/example.opam))
643+
(num_stat (
644+
Num_lines_in_diff (
645+
(insertions 12)
646+
(deletions 6)))))
647+
((key (One_file example/example.opam.template))
648+
(num_stat (
649+
Num_lines_in_diff (
650+
(insertions 9)
651+
(deletions 0)))))
652+
((key (One_file example/lib/example/test/dune))
653+
(num_stat (
654+
Num_lines_in_diff (
655+
(insertions 1)
656+
(deletions 1)))))
657+
((key (One_file template/.ocamlformat))
658+
(num_stat (
659+
Num_lines_in_diff (
660+
(insertions 3)
661+
(deletions 1)))))
662+
((key (One_file template/LICENSE))
663+
(num_stat (
664+
Num_lines_in_diff (
665+
(insertions 1)
666+
(deletions 1)))))
667+
((key (One_file template/bin/dune))
668+
(num_stat (
669+
Num_lines_in_diff (
670+
(insertions 1)
671+
(deletions 1)))))
672+
((key (One_file template/dune-project))
673+
(num_stat (
674+
Num_lines_in_diff (
675+
(insertions 86)
676+
(deletions 20)))))
677+
((key (One_file template/github/workflows/ci.yml))
678+
(num_stat (
679+
Num_lines_in_diff (
680+
(insertions 9)
681+
(deletions 5)))))
682+
((key (One_file "template/lib/{{ project_snake }}/test/dune"))
683+
(num_stat (
684+
Num_lines_in_diff (
685+
(insertions 1)
686+
(deletions 1)))))
687+
((key (One_file "template/{{ project_slug }}-dev.opam"))
688+
(num_stat (
689+
Num_lines_in_diff (
690+
(insertions 49)
691+
(deletions 0)))))
692+
((key (One_file "template/{{ project_slug }}-tests.opam"))
693+
(num_stat (
694+
Num_lines_in_diff (
695+
(insertions 4)
696+
(deletions 7)))))
697+
((key (One_file "template/{{ project_slug }}.opam"))
698+
(num_stat (
699+
Num_lines_in_diff (
700+
(insertions 12)
701+
(deletions 6)))))
702+
((key (One_file "template/{{ project_slug }}.opam.template"))
703+
(num_stat (
704+
Num_lines_in_diff (
705+
(insertions 9)
706+
(deletions 0))))))
558707
|}];
559708
()
560709
;;

test/data/README.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ The repos were chosen somewhat arbitrarily, or given as part of a bug report, et
1010

1111
- [super-master-mind](https://github.com/mbarbin/super-master-mind)
1212
- [eio](https://github.com/ocaml-multicore/eio.git)
13+
- [opam-package-template](https://github.com/mbarbin/opam-package-template)
1314

1415
## Files
1516

@@ -52,3 +53,19 @@ This file was created by capturing the output of:
5253
```sh
5354
git diff --numstat ef415fbdfe1c60cb046a89db4fd48663fc61b77e..3be614e86fb4c7b70f2547972491dd7fb170f01a
5455
```
56+
57+
### opam-package-template.name-status
58+
59+
This file was created by capturing the output of:
60+
61+
```sh
62+
$ git diff --name-status 9f9ce346061935b2fbcd88ad09e93bb4da1a14dd..df36196adff434341b5d019c2494b992f23a5fe1
63+
```
64+
65+
### opam-package-template.num-status
66+
67+
This file was created by capturing the output of:
68+
69+
```sh
70+
$ git diff --numstat 9f9ce346061935b2fbcd88ad09e93bb4da1a14dd..df36196adff434341b5d019c2494b992f23a5fe1
71+
```
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
M .github/workflows/ci.yml
2+
M example/.github/workflows/ci.yml
3+
M example/.ocamlformat
4+
M example/LICENSE
5+
M example/bin/dune
6+
M example/dune-project
7+
A example/example-dev.opam
8+
M example/example-tests.opam
9+
M example/example.opam
10+
A example/example.opam.template
11+
M example/lib/example/test/dune
12+
M template/.ocamlformat
13+
M template/LICENSE
14+
M template/bin/dune
15+
M template/dune-project
16+
M template/github/workflows/ci.yml
17+
M template/lib/{{ project_snake }}/test/dune
18+
A template/{{ project_slug }}-dev.opam
19+
M template/{{ project_slug }}-tests.opam
20+
M template/{{ project_slug }}.opam
21+
A template/{{ project_slug }}.opam.template
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
1 1 .github/workflows/ci.yml
2+
9 5 example/.github/workflows/ci.yml
3+
3 1 example/.ocamlformat
4+
1 1 example/LICENSE
5+
1 1 example/bin/dune
6+
86 20 example/dune-project
7+
49 0 example/example-dev.opam
8+
4 7 example/example-tests.opam
9+
12 6 example/example.opam
10+
9 0 example/example.opam.template
11+
1 1 example/lib/example/test/dune
12+
3 1 template/.ocamlformat
13+
1 1 template/LICENSE
14+
1 1 template/bin/dune
15+
86 20 template/dune-project
16+
9 5 template/github/workflows/ci.yml
17+
1 1 template/lib/{{ project_snake }}/test/dune
18+
49 0 template/{{ project_slug }}-dev.opam
19+
4 7 template/{{ project_slug }}-tests.opam
20+
12 6 template/{{ project_slug }}.opam
21+
9 0 template/{{ project_slug }}.opam.template

0 commit comments

Comments
 (0)