1 /*
  2  * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.  Oracle designates this
  8  * particular file as subject to the "Classpath" exception as provided
  9  * by Oracle in the LICENSE file that accompanied this code.
 10  *
 11  * This code is distributed in the hope that it will be useful, but WITHOUT
 12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  * version 2 for more details (a copy is included in the LICENSE file that
 15  * accompanied this code).
 16  *
 17  * You should have received a copy of the GNU General Public License version
 18  * 2 along with this work; if not, write to the Free Software Foundation,
 19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  * or visit www.oracle.com if you need additional information or have any
 23  * questions.
 24  */
 25 
 26 package jdk.code.tools.renderer;
 27 
 28 import java.io.*;
 29 import java.util.ArrayList;
 30 import java.util.List;
 31 
 32 /**
 33  * Created by gfrost
 34  */
 35 public final class Diff {
 36     private Diff() {
 37     }
 38 
 39     public static void annotate(File file, int line, int col, String msg) {
 40         List<String> lines = getLines(file);
 41         for (int i = Math.max(line - 2, 0); i < (line - 1); i++) {
 42             System.out.printf("    %2d:%s\n", i + 1, lines.get(i));
 43         }
 44         String text = lines.get(line - 1);
 45         System.out.printf(" -> %2d:%s\n      ", line, text);
 46         for (int i = 0; i < col; i++) {
 47             System.out.print(" ");
 48         }
 49         System.out.println("^ " + msg);
 50         for (int i = line; i < Math.min(line + 2, lines.size() - 1); i++) {
 51             System.out.printf("    %2d:%s\n", i + 1, lines.get(i));
 52         }
 53 
 54     }
 55 
 56     static List<String> getLines(File file) {
 57         List<String> lines = new ArrayList<>();
 58         try {
 59             BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
 60             for (String line = br.readLine(); line != null; line = br.readLine()) {
 61                 lines.add(line);
 62             }
 63             br.close();
 64         } catch (FileNotFoundException e) {
 65             e.printStackTrace();
 66         } catch (IOException e) {
 67             e.printStackTrace();
 68         }
 69         return lines;
 70     }
 71 
 72     public static class DiffResult {
 73         String lhs;
 74         String rhs;
 75         public String result;
 76         public int exitStatus;
 77 
 78         public DiffResult(String lhs, String rhs, String result, int exitStatus) {
 79             this.lhs = lhs;
 80             this.rhs = rhs;
 81             this.result = result;
 82             this.exitStatus = exitStatus;
 83         }
 84     }
 85 
 86     public static DiffResult diff(String lhs, String rhs, int width) {
 87         try {
 88             File lhsFile = File.createTempFile("lhs", "txt");
 89             FileWriter lhsw = new FileWriter(lhsFile);
 90             lhsw.append(lhs);
 91             lhsw.close();
 92             File rhsFile = File.createTempFile("rhs", "txt");
 93             FileWriter rhsw = new FileWriter(rhsFile);
 94             rhsw.append(rhs);
 95             rhsw.close();
 96 
 97             List<String> command = new ArrayList<>();
 98             command.add("sdiff");
 99             command.add("--expand-tabs");
100             command.add("--ignore-all-space");
101             command.add("--width=" + width);
102             command.add("--ignore-blank-lines");
103             command.add(lhsFile.getAbsolutePath());
104             command.add(rhsFile.getAbsolutePath());
105 
106             ProcessBuilder builder = new ProcessBuilder(command);
107             final Process process = builder.start();
108             BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
109             StringBuilder out = new StringBuilder();
110             String line;
111             while ((line = br.readLine()) != null) {
112                 if (line.contains("|")) {
113                     out.append(TerminalColors.Color.RED.colorize(line)).append("\n");
114                 } else {
115                     out.append(TerminalColors.Color.GREEN.colorize(line)).append("\n");
116                 }
117 
118             }
119             process.waitFor();
120             br.close();
121             lhsFile.delete();
122             rhsFile.delete();
123             return new DiffResult(lhs, rhs, out.toString(), process.exitValue());
124         } catch (IOException | InterruptedException ioe) {
125             ioe.printStackTrace();
126         }
127         return null;
128     }
129 
130 
131     public static File write(File file, String text) {
132         try {
133             PrintWriter pw = new PrintWriter(file);
134             pw.append(text);
135             pw.append("\n");
136             pw.close();
137         } catch (IOException e) {
138             e.printStackTrace();
139         }
140         return file;
141     }
142 
143 
144 }