cocci.inria.fr archive mirror
 help / color / mirror / Atom feed
* [Cocci] [PATCH V2 0/2] Add "use-patch-diff" option
@ 2021-07-13  9:27 Sumera Priyadarsini
  2021-07-13  9:28 ` [Cocci] [PATCH V2 1/2] parsing_cocci: Add feature to check only modified files Sumera Priyadarsini
  2021-07-13  9:29 ` [Cocci] [PATCH V2 2/2] docs: manual: Add option description in spatch_options Sumera Priyadarsini
  0 siblings, 2 replies; 3+ messages in thread
From: Sumera Priyadarsini @ 2021-07-13  9:27 UTC (permalink / raw)
  To: julia.lawall; +Cc: cocci

This patchset adds a feature to enable Coccinelle
to only check all those files in a directory which were
modified. It parses all the files obtained from the
output of "git diff" and checks them against the specified
cocci script.

An example for passing the "use-patchdiff" option is:

	spatch -D report --sp-file for_each_child.cocci --use-patchdiff drivers/gpu

One thing to note while using the command is that while it can be
invoked outside the target project directory, an absolute path
to the target folder should be specified in such cases.

Sumera Priyadarsini (2):
  parsing_cocci: Add feature to check only modified files
  docs: manual: Add option description in spatch_options

 Makefile                        |   2 +-
 docs/manual/spatch_options.tex  |   5 ++
 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 +++
 9 files changed, 148 insertions(+), 9 deletions(-)
 create mode 100755 parsing_cocci/patch_diff.ml
 create mode 100644 parsing_cocci/patch_diff.mli

-- 
2.32.0

_______________________________________________
Cocci mailing list
Cocci@systeme.lip6.fr
https://systeme.lip6.fr/mailman/listinfo/cocci

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [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

* [Cocci] [PATCH V2 2/2] docs: manual: Add option description in spatch_options
  2021-07-13  9:27 [Cocci] [PATCH V2 0/2] Add "use-patch-diff" option Sumera Priyadarsini
  2021-07-13  9:28 ` [Cocci] [PATCH V2 1/2] parsing_cocci: Add feature to check only modified files Sumera Priyadarsini
@ 2021-07-13  9:29 ` Sumera Priyadarsini
  1 sibling, 0 replies; 3+ messages in thread
From: Sumera Priyadarsini @ 2021-07-13  9:29 UTC (permalink / raw)
  To: julia.lawall; +Cc: cocci

Add documentation for the "use-patch-diff" option introduced in
the first patch of this patchset. This option allows for
applying a semantic patch to only those files in a directory
where code additions have been made.

Signed-off-by: Sumera Priyadarsini <sylphrenadin@gmail.com>
---
Changes in V2:
    - Change "use-patchdiff" to "use-patch-diff" (Julia)
---
 docs/manual/spatch_options.tex | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/docs/manual/spatch_options.tex b/docs/manual/spatch_options.tex
index a372aaf8a..393d254e3 100644
--- a/docs/manual/spatch_options.tex
+++ b/docs/manual/spatch_options.tex
@@ -220,6 +220,11 @@ intereted relative to the target directory.  If the filename is an absolute
 path name, beginning with /, it is used as is.
 }
 
+\normal{-{}-use-patch-diff}{ This option allows for applying a semantic patch
+  to only the files that have been modified in a directory. The directory needs
+  to be specified by the user. Note that an absolute path needs to be used if
+  spatch is called from outside the target project directory. }
+
 \normal{-{}-use-coccigrep}{ Use a version of grep implemented in Coccinelle
   to check that selected files are relevant to the semantic patch.  This
   option is only relevant to the case of working on a complete directory,
-- 
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

end of thread, other threads:[~2021-07-13  9:30 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-13  9:27 [Cocci] [PATCH V2 0/2] Add "use-patch-diff" option Sumera Priyadarsini
2021-07-13  9:28 ` [Cocci] [PATCH V2 1/2] parsing_cocci: Add feature to check only modified files Sumera Priyadarsini
2021-07-13  9:29 ` [Cocci] [PATCH V2 2/2] docs: manual: Add option description in spatch_options Sumera Priyadarsini

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).