* [Cocci] [PATCH V2 1/2] parsing_cocci: Add feature to check only modified files
2021-07-13 9:27 [Cocci] [PATCH V2 0/2] Add "use-patch-diff" option Sumera Priyadarsini
@ 2021-07-13 9:28 ` Sumera Priyadarsini
2021-07-13 9:29 ` [Cocci] [PATCH V2 2/2] docs: manual: Add option description in spatch_options Sumera Priyadarsini
1 sibling, 0 replies; 3+ messages in thread
From: Sumera Priyadarsini @ 2021-07-13 9:28 UTC (permalink / raw)
To: julia.lawall; +Cc: cocci
This patch adds an option "use-patch-diff" to allow for
applying a semantic patch to only those files in a directory
where code additions have been made.
Usage: spatch -D <mode> --sp-file <cocci script> --use-patch-diff <target
directory>
Example: spatch -D report --sp-file for_each_child.cocci --use-patch-diff drivers/gpu
Signed-off-by: Sumera Priyadarsini <sylphrenadin@gmail.com>
---
Changes in V2:
- Change "use-patchdiff" to "use-patch-diff" (Julia)
---
Makefile | 2 +-
enter.ml | 17 +++--
globals/flag.ml | 2 +-
globals/flag.mli | 2 +-
ocaml/coccilib.mli | 1 +
parsing_cocci/get_constants2.ml | 1 +
parsing_cocci/patch_diff.ml | 118 ++++++++++++++++++++++++++++++++
parsing_cocci/patch_diff.mli | 9 +++
8 files changed, 143 insertions(+), 9 deletions(-)
create mode 100755 parsing_cocci/patch_diff.ml
create mode 100644 parsing_cocci/patch_diff.mli
diff --git a/Makefile b/Makefile
index f8d3424c0..455e92395 100644
--- a/Makefile
+++ b/Makefile
@@ -44,7 +44,7 @@ SOURCES_parsing_cocci := \
parse_printf.ml parse_aux.ml cleanup_rules.ml disjdistr.ml \
parser_cocci_menhir.mly lexer_cocci.mll \
lexer_cli.mll lexer_script.mll \
- cocci_grep.ml dpll.ml get_constants2.ml id_utils.ml git_grep.ml \
+ cocci_grep.ml dpll.ml get_constants2.ml id_utils.ml git_grep.ml patch_diff.ml \
adjacency.ml commas_on_lists.ml re_constraints.ml parse_cocci.ml \
command_line.ml cocci_args.ml
SOURCES_parsing_c := \
diff --git a/enter.ml b/enter.ml
index 77e1540fd..1219c027d 100644
--- a/enter.ml
+++ b/enter.ml
@@ -18,9 +18,7 @@ module Inc = Includes
* globals/config.ml, mainly a standard.h and standard.iso file *)
let cocci_file = ref ""
-
let opt_c_files = ref []
-
let output_file = ref "" (* resulting code *)
let tmp_dir = ref "" (* temporary files for parallelism *)
let aux_file_suffix =
@@ -283,7 +281,6 @@ let print_version () =
let short_options = [
"--sp-file", Arg.Set_string cocci_file,
" <file> the semantic patch file";
-
"--opt-c",
Arg.String (fun filename ->
if Sys.file_exists filename
@@ -370,6 +367,9 @@ let short_options = [
"--use-coccigrep",
Arg.Unit (function _ -> Flag.scanner := Flag.CocciGrep),
" find relevant files using cocci grep";
+ "--use-patch-diff",
+ Arg.Unit (function _ -> Flag.scanner := Flag.PatchDiff),
+ " process files in the diff for a directory";
"--patch",
Arg.String (function s -> Flag.patch := Some (Cocci.normalize_path s)),
(" <dir> path name with respect to which a patch should be created\n"^
@@ -940,13 +940,18 @@ let idutils_filter (_,_,_,query) dir =
Some
(files +>
List.filter
- (fun file -> List.mem (Common.filesuffix file) suffixes))
+ (fun file -> List.mem (Common.filesuffix file) suffixes))
+
+let patchdiff_filter _ dir =
+ let struc = Patch_diff.getpatchdiff dir in
+ Some (List.map (function x -> x.Patch_diff.file_name) struc)
let scanner_to_interpreter = function
Flag.Glimpse -> glimpse_filter
| Flag.IdUtils -> idutils_filter
| Flag.CocciGrep -> coccigrep_filter
| Flag.GitGrep -> gitgrep_filter
+ | Flag.PatchDiff -> patchdiff_filter
| _ -> failwith "impossible"
(*****************************************************************************)
@@ -1079,7 +1084,7 @@ let rec main_action xs =
" or multiple files")
| _, false, _, _, _ -> [List.map (fun x -> (x,None)) (x::xs)]
| _, true, "",
- (Flag.Glimpse|Flag.IdUtils|Flag.CocciGrep|Flag.GitGrep),
+ (Flag.Glimpse|Flag.IdUtils|Flag.CocciGrep|Flag.GitGrep|Flag.PatchDiff),
[] ->
let interpreter = scanner_to_interpreter !Flag.scanner in
let files =
@@ -1088,7 +1093,7 @@ let rec main_action xs =
| Some files -> files in
files +> List.map (fun x -> [(x,None)])
| _, true, s,
- (Flag.Glimpse|Flag.IdUtils|Flag.CocciGrep|Flag.GitGrep), _
+ (Flag.Glimpse|Flag.IdUtils|Flag.CocciGrep|Flag.GitGrep|Flag.PatchDiff), _
when s <> "" ->
failwith "--use-xxx filters do not work with --kbuild"
(* normal *)
diff --git a/globals/flag.ml b/globals/flag.ml
index e1d01cb4c..dffe6cd80 100644
--- a/globals/flag.ml
+++ b/globals/flag.ml
@@ -16,7 +16,7 @@ let track_iso_usage = ref false
let worth_trying_opt = ref true
-type scanner = IdUtils | Glimpse | CocciGrep | GitGrep | NoScanner
+type scanner = IdUtils | Glimpse | CocciGrep | GitGrep | PatchDiff | NoScanner
let scanner = ref NoScanner
let pyoutput = ref "coccilib.output.Console"
diff --git a/globals/flag.mli b/globals/flag.mli
index dadc7b6fc..0e8a3b063 100644
--- a/globals/flag.mli
+++ b/globals/flag.mli
@@ -4,7 +4,7 @@ val show_transinfo : bool ref
val show_trying : bool ref
val track_iso_usage : bool ref
val worth_trying_opt : bool ref
-type scanner = IdUtils | Glimpse | CocciGrep | GitGrep | NoScanner
+type scanner = IdUtils | Glimpse | CocciGrep | GitGrep | PatchDiff | NoScanner
val scanner : scanner ref
val pyoutput : string ref
val ocamlc : string ref
diff --git a/ocaml/coccilib.mli b/ocaml/coccilib.mli
index c0f844ea5..1f1714cb5 100644
--- a/ocaml/coccilib.mli
+++ b/ocaml/coccilib.mli
@@ -1377,6 +1377,7 @@ module Flag :
| Glimpse
| CocciGrep
| GitGrep
+ | PatchDiff
| NoScanner
val scanner : scanner ref
val pyoutput : string ref
diff --git a/parsing_cocci/get_constants2.ml b/parsing_cocci/get_constants2.ml
index bc99aa231..a0daeb902 100644
--- a/parsing_cocci/get_constants2.ml
+++ b/parsing_cocci/get_constants2.ml
@@ -866,5 +866,6 @@ let get_constants rules neg_pos_vars virt =
| Flag.IdUtils ->
(grep,None,coccigrep,interpret_idutils res)
| Flag.CocciGrep | Flag.GitGrep -> (grep,None,coccigrep,None)
+ | Flag.PatchDiff -> (None, None, None, None)
end
else (None,None,None,None)
diff --git a/parsing_cocci/patch_diff.ml b/parsing_cocci/patch_diff.ml
new file mode 100755
index 000000000..52a04db68
--- /dev/null
+++ b/parsing_cocci/patch_diff.ml
@@ -0,0 +1,118 @@
+open Printf
+open Str
+
+(*Read file contents*)
+let read_whole_file filename =
+ let ch = open_in filename in
+ let s = really_input_string ch (in_channel_length ch) in
+ close_in ch;
+ s
+
+(*Breakdown split_result_list type to primtive type*)
+let rec decompose_list (l: Str.split_result list) =
+ match l with
+ | [] -> []
+ | Text hd :: tl -> decompose_list tl
+ | Delim hd :: tl -> hd :: decompose_list tl
+;;
+
+(*Fetch output for bash commands*)
+let read_bash_help command =
+ let ic = Unix.open_process_in command in
+ let all_input = ref [] in
+ try
+ while true do
+ all_input := input_line ic :: !all_input
+ done;
+ !all_input
+ with
+ End_of_file -> close_in ic;
+ List.rev !all_input;;
+
+let get_root fpath =
+ let current_dir = List.hd (read_bash_help "pwd") in
+ let command_get_root = "cd " ^ fpath ^ " && git rev-parse --show-toplevel" in
+ let root = List.hd (read_bash_help command_get_root) in
+ let command_return = "cd " ^ current_dir in
+ let ic = Unix.open_process_in command_return in
+ close_in ic;
+ root
+
+ let extract_numbers line =
+ let sep = String.split_on_char ',' line in
+ match sep with
+ | [l] -> (int_of_string l, int_of_string l)
+ | [f ; e] -> (int_of_string f, int_of_string e)
+ | _ -> failwith "no line numbers found, sorry"
+;;
+
+let fetch_file_name line =
+ let pat_filename = Str.regexp "\\(+++ b\\)/\\(.+\\)\\.[a-z]+" in
+ let s = Str.full_split pat_filename line in
+ decompose_list s
+;;
+
+let fetch_line_number line =
+ let pat_line_num = Str.regexp "\\(\\+\\([0-9]+,[0-9]+\\)\\)" in
+ let s = Str.full_split pat_line_num line in
+ let fa = List.hd (decompose_list s) in
+ let (b, e) = extract_numbers fa in
+ (b, (b + e)) (*start of diff, end of diff *)
+;;
+
+type diff_info =
+{
+ file_name: string;
+ line_no: (int * int) list;
+}
+
+type patch_info = No_info | File_info of string list | Line_info of (int * int)
+
+(*check line and extract file name or file number*)
+let extract_info line =
+ if Str.string_match (Str.regexp_string "+++") line 0 then
+ File_info (fetch_file_name line)
+ else if Str.string_match (Str.regexp_string "@@ ") line 0 then
+ Line_info (fetch_line_number line)
+ else
+ No_info
+
+let rec reorg_helper new_list = function
+[] -> (List.rev new_list, [])
+| No_info :: tl -> reorg_helper new_list tl
+| File_info file_list :: tl -> (List.rev new_list, File_info file_list :: tl)
+| Line_info line_list :: tl -> reorg_helper (line_list :: new_list) tl
+;;
+
+let rec reorg fpath toproot = function
+[] -> []
+| No_info :: tl -> reorg fpath toproot tl
+| File_info [file] :: tl ->
+ let lines, rest = reorg_helper [] tl in
+ {
+ file_name = Str.replace_first (Str.regexp "+++ b") toproot file;
+ line_no = lines;
+ } :: reorg fpath toproot rest
+| File_info file_list :: tl ->
+ let lines, rest = reorg_helper [] tl in
+ reorg fpath toproot rest
+| Line_info line_list :: tl -> failwith "bad case"
+
+let rec mlines lines =
+ match lines with
+ | [] -> []
+ | hd :: tl -> extract_info hd :: mlines tl
+
+let final_info dir =
+ let git_root = get_root dir in
+ let git_read_command = "cd " ^ git_root ^ " && git diff " ^ dir ^ " | egrep '^+++|^@'" in
+ let list_diff = reorg dir git_root (mlines (read_bash_help git_read_command)) in
+ list_diff;;
+
+let rec print_tuple_list l =
+ match l with
+ | [] -> ()
+ | (a,b) :: tl -> printf "\n%d, %d" a b; print_tuple_list tl
+
+let getpatchdiff dir = final_info dir
+
diff --git a/parsing_cocci/patch_diff.mli b/parsing_cocci/patch_diff.mli
new file mode 100644
index 000000000..b059509ef
--- /dev/null
+++ b/parsing_cocci/patch_diff.mli
@@ -0,0 +1,9 @@
+
+
+type diff_info =
+{
+ file_name: string;
+ line_no: (int * int) list;
+}
+
+val getpatchdiff : string -> diff_info list
--
2.32.0
_______________________________________________
Cocci mailing list
Cocci@systeme.lip6.fr
https://systeme.lip6.fr/mailman/listinfo/cocci
^ permalink raw reply related [flat|nested] 3+ messages in thread