diff --git a/doc/repair-tools.md b/doc/repair-tools.md index b878cc9a8..b3485521e 100644 --- a/doc/repair-tools.md +++ b/doc/repair-tools.md @@ -48,15 +48,16 @@ It can be used [in the configuration](repairnator-config.md#REPAIR_TOOLS) with t Currently this tool supports the following [rules](https://github.com/kth-tcs/sonarqube-repair/blob/master/docs/HANDLED_RULES.md) on SonarQube -It can be used [in the configuration](repairnator-config.md#REPAIR_TOOLS) with this value: `Sorald` with the corresponding handled rulenumber [in the configuration](repairnator-config.md#REPAIR_TOOLS). [Current supported ruleNumbers](https://github.com/kth-tcs/sonarqube-repair/blob/master/docs/HANDLED_RULES.md) +It can be used [in the configuration](repairnator-config.md#REPAIR_TOOLS) with this value: `SoraldBot` with the corresponding handled rulenumber [in the configuration](repairnator-config.md#REPAIR_TOOLS). [Current supported ruleNumbers](https://github.com/kth-tcs/sonarqube-repair/blob/master/docs/HANDLED_RULES.md) +Sorald resolves violations of `--sonarRules` in the files changed in a specified commit. -Moreover, Launcher choice need to be set with `--launcherChoice NEW` to use this tool. +Moreover, the launcher mode should be set to `--launcherMode GIT_REPOSITORY` to use this tool. Additional parameters: -* `--sonarRules`: the rules Sorald should analyze for warnings after input. Input format: 2116,1656... . Default: 2116 -* `--soraldRepairMode`: DEFAULT - the normal mode of Sorald, where the entire project is inputted. SEGMENT - the input project is sliced into smaller fixed-size segments. -* `--soraldMaxFixesPerRule`: specify the upper bound of the number of warning fixes. -* `--segmentSize`: the number of files per segment if Sorald runs in Segment mode. +* `--sonarRules`: the rules Sorald should analyze for warnings after input. Input format: 2116,1656... . +* `--gitrepo`: required only in the new version. +* `--gitrepourl`: the url of the target repo that should be fixed. Required only in the new version. +* `--gitcommithash`: the hash number of the commit that Sorald will fix its changed files. Required only in the new version. ## Sequencer diff --git a/src/maven-repair/pom.xml b/src/maven-repair/pom.xml index 68289eeb1..05c8e7f00 100644 --- a/src/maven-repair/pom.xml +++ b/src/maven-repair/pom.xml @@ -259,7 +259,7 @@ org.apache.maven.plugins maven-plugin-plugin - 3.5 + 3.6.1 repair true diff --git a/src/repairnator-core/src/main/java/fr/inria/spirals/repairnator/LauncherUtils.java b/src/repairnator-core/src/main/java/fr/inria/spirals/repairnator/LauncherUtils.java index b01e2de79..01d98f4f9 100644 --- a/src/repairnator-core/src/main/java/fr/inria/spirals/repairnator/LauncherUtils.java +++ b/src/repairnator-core/src/main/java/fr/inria/spirals/repairnator/LauncherUtils.java @@ -109,12 +109,6 @@ public static void registerCommonArgs(JSAP jsap) throws JSAPException { // --sonarRules jsap.registerParameter(LauncherUtils.defineArgSonarRules()); - // --soraldRepairMode - jsap.registerParameter(LauncherUtils.defineArgSoraldRepairMode()); - // --segmentSize - jsap.registerParameter(LauncherUtils.defineArgSegmentSize()); - // --soraldMaxFixesPerRule - jsap.registerParameter(LauncherUtils.defineArgSoraldMaxFixesPerRule()); // --npeSelection jsap.registerParameter(LauncherUtils.defineArgNPESelection()); @@ -231,9 +225,6 @@ public static void initCommonConfig(RepairnatorConfig config, JSAPResult argumen } config.setSonarRules(Arrays.stream(LauncherUtils.getArgSonarRules(arguments).split(",")).distinct().toArray(String[]::new)); - config.setSegmentSize(LauncherUtils.getArgSegmentSize(arguments)); - config.setSoraldRepairMode(RepairnatorConfig.SORALD_REPAIR_MODE.valueOf(LauncherUtils.getArgSoraldRepairMode(arguments))); - config.setSoraldMaxFixesPerRule(LauncherUtils.getArgSoraldMaxFixesPerRule(arguments)); config.setNPESelection(LauncherUtils.getArgNPESelection(arguments)); config.setNPENbIteration(LauncherUtils.getArgNPENbIteration(arguments)); @@ -822,7 +813,7 @@ public static String getArgGitBranch(JSAPResult arguments) { public static FlaggedOption defineArgGitCommitHash() { FlaggedOption opt = new FlaggedOption("gitcommithash"); - opt.setLongFlag("gitcommit"); + opt.setLongFlag("gitcommithash"); opt.setStringParser(JSAP.STRING_PARSER); opt.setHelp("the hash of your git commit"); return opt; @@ -872,45 +863,6 @@ public static String getArgSonarRules(JSAPResult arguments) { return arguments.getString("sonarRules"); } - public static FlaggedOption defineArgSoraldRepairMode() { - FlaggedOption opt = new FlaggedOption("soraldRepairMode"); - opt.setLongFlag("soraldRepairMode"); - opt.setStringParser(JSAP.STRING_PARSER); - opt.setDefault(RepairnatorConfig.SORALD_REPAIR_MODE.DEFAULT.name()); - opt.setHelp("DEFAULT - default mode , load everything in at once into Sorald. SEGMENT - repair segments of the projects instead, segmentsize can be specified."); - return opt; - } - - public static String getArgSoraldRepairMode(JSAPResult arguments) { - return arguments.getString("soraldRepairMode"); - } - - public static FlaggedOption defineArgSegmentSize() { - FlaggedOption opt = new FlaggedOption("segmentSize"); - opt.setLongFlag("segmentSize"); - opt.setStringParser(JSAP.INTEGER_PARSER); - opt.setDefault("200"); - opt.setHelp("Segment size for the segment repair."); - return opt; - } - - public static Integer getArgSegmentSize(JSAPResult arguments) { - return arguments.getInt("segmentSize"); - } - - public static FlaggedOption defineArgSoraldMaxFixesPerRule() { - FlaggedOption opt = new FlaggedOption("soraldMaxFixesPerRule"); - opt.setLongFlag("soraldMaxFixesPerRule"); - opt.setStringParser(JSAP.INTEGER_PARSER); - opt.setDefault("2000"); - opt.setHelp("Number of fixes per SonarQube rule."); - return opt; - } - - public static Integer getArgSoraldMaxFixesPerRule(JSAPResult arguments) { - return arguments.getInt("soraldMaxFixesPerRule"); - } - public static FlaggedOption defineArgNPESelection() { FlaggedOption opt = new FlaggedOption("npeSelection"); opt.setLongFlag("npeSelection"); diff --git a/src/repairnator-core/src/main/java/fr/inria/spirals/repairnator/config/RepairnatorConfig.java b/src/repairnator-core/src/main/java/fr/inria/spirals/repairnator/config/RepairnatorConfig.java index ef60d3712..e94f3a197 100644 --- a/src/repairnator-core/src/main/java/fr/inria/spirals/repairnator/config/RepairnatorConfig.java +++ b/src/repairnator-core/src/main/java/fr/inria/spirals/repairnator/config/RepairnatorConfig.java @@ -59,15 +59,6 @@ public enum PATCH_FILTERING_MODE { ODS_CORRECT } - /** - * DEFAULT - the project files is scanned by Sorald as a single unit. If the repair fails then it fails completely and no fixes are produced if there could have been any - * SEGMENT - the project is sliced into fix-sized segments to be scanned one by one. If the repair fails for a segment, it will salvage the situation by continuing on with other segments - */ - public enum SORALD_REPAIR_MODE { - DEFAULT, - SEGMENT - } - private String runId; private LauncherMode launcherMode = LauncherMode.REPAIR; @@ -125,9 +116,6 @@ public enum SORALD_REPAIR_MODE { private String[] sonarRules; private boolean isStaticAnalysis; - private int soraldMaxFixesPerRule; - private int segmentSize; - private SORALD_REPAIR_MODE soraldRepairMode; private boolean measureSoraldTime; private String npeSelection; @@ -753,30 +741,6 @@ public boolean isStaticAnalysis() { return this.isStaticAnalysis; } - public void setSegmentSize(int segmentSize) { - this.segmentSize = segmentSize; - } - - public int getSegmentSize() { - return this.segmentSize; - } - - public void setSoraldRepairMode(SORALD_REPAIR_MODE soraldRepairMode) { - this.soraldRepairMode = soraldRepairMode; - } - - public SORALD_REPAIR_MODE getSoraldRepairMode() { - return this.soraldRepairMode; - } - - public void setSoraldMaxFixesPerRule(int soraldMaxFixesPerRule) { - this.soraldMaxFixesPerRule = soraldMaxFixesPerRule; - } - - public int getSoraldMaxFixesPerRule() { - return this.soraldMaxFixesPerRule; - } - public String getNPESelection() { return npeSelection; } diff --git a/src/repairnator-jenkins-plugin/src/main/java/io/jenkins/plugins/main/Config.java b/src/repairnator-jenkins-plugin/src/main/java/io/jenkins/plugins/main/Config.java index f67c564cd..e1ef8927e 100644 --- a/src/repairnator-jenkins-plugin/src/main/java/io/jenkins/plugins/main/Config.java +++ b/src/repairnator-jenkins-plugin/src/main/java/io/jenkins/plugins/main/Config.java @@ -11,9 +11,6 @@ public class Config { private HashMap stringConfig; private String[] tools; private String sonarRules; - private String soraldRepairMode; - private int soraldMaxFixesPerRule; - private int segmentSize; private File workspaceDir; public Config(){ @@ -151,30 +148,6 @@ public void switchQuiet() { this.quiet = !this.quiet; } - public void setSoraldRepairMode(String soraldRepairMode) { - this.soraldRepairMode = soraldRepairMode; - } - - public String getSoraldRepairMode() { - return this.soraldRepairMode; - } - - public void setSoraldMaxFixesPerRule(int soraldMaxFixesPerRule) { - this.soraldMaxFixesPerRule = soraldMaxFixesPerRule; - } - - public int getSoraldMaxFixesPerRule() { - return this.soraldMaxFixesPerRule; - } - - public void setSegmentSize(int segmentSize) { - this.segmentSize = segmentSize; - } - - public int getSegmentSize() { - return this.segmentSize; - } - public void setWorkspaceDir(File workspaceDir) { this.workspaceDir = workspaceDir; } diff --git a/src/repairnator-jenkins-plugin/src/main/java/io/jenkins/plugins/main/RepairnatorPostBuild.java b/src/repairnator-jenkins-plugin/src/main/java/io/jenkins/plugins/main/RepairnatorPostBuild.java index 3f43580fd..17bc4d0e0 100644 --- a/src/repairnator-jenkins-plugin/src/main/java/io/jenkins/plugins/main/RepairnatorPostBuild.java +++ b/src/repairnator-jenkins-plugin/src/main/java/io/jenkins/plugins/main/RepairnatorPostBuild.java @@ -111,12 +111,9 @@ public class RepairnatorPostBuild extends Recorder { private boolean rule4973; private SonarRulesBlock sonarRulesBlock; - private String soraldRepairMode; - private int soraldMaxFixesPerRule; - private int segmentSize; @DataBoundConstructor - public RepairnatorPostBuild(String gitUrl,String gitOAuthToken,String gitBranch,String notifyTo, String soraldRepairMode, int segmentSize, int soraldMaxFixesPerRule,SonarRulesBlock sonarRulesBlock) { + public RepairnatorPostBuild(String gitUrl,String gitOAuthToken,String gitBranch,String notifyTo,SonarRulesBlock sonarRulesBlock) { this.gitUrl = gitUrl; this.gitOAuthToken = gitOAuthToken; this.gitBranch = gitBranch; @@ -126,23 +123,6 @@ public RepairnatorPostBuild(String gitUrl,String gitOAuthToken,String gitBranch, sonarRulesBlock.rulesProvided = true; } - if (soraldRepairMode == null) { - this.soraldRepairMode = "DEFAULT"; - } else { - this.soraldRepairMode = soraldRepairMode; - } - - if (soraldMaxFixesPerRule <= 0) { - this.soraldMaxFixesPerRule = 2000; - } else { - this.soraldMaxFixesPerRule = soraldMaxFixesPerRule; - } - - if (segmentSize <= 0) { - this.segmentSize = 200; - } else { - this.segmentSize = segmentSize; - } } public RepairnatorPostBuild() { @@ -247,30 +227,6 @@ public boolean getRule4973() { return SonarRulesBlock.rule4973; } - public void setSoraldRepairMode(String soraldRepairMode) { - this.soraldRepairMode = soraldRepairMode; - } - - public String getSoraldRepairMode() { - return this.soraldRepairMode; - } - - public void setSoraldMaxFixesPerRule(int soraldMaxFixesPerRule) { - this.soraldMaxFixesPerRule = soraldMaxFixesPerRule; - } - - public int getSoraldMaxFixesPerRule() { - return this.soraldMaxFixesPerRule; - } - - public void setSegmentSize(int segmentSize) { - this.segmentSize = segmentSize; - } - - public int getSegmentSize() { - return this.segmentSize; - } - public void setGitUrl(String gitUrl) { this.gitUrl = gitUrl; } @@ -402,10 +358,7 @@ public void runRepairnator(EnvVars env) throws IOException,InterruptedException{ .alsoCreatePR() .withMavenHome(config.getMavenHome()) .atWorkSpace(config.getWorkspaceDir().getAbsolutePath()) - .withOutputDir(config.getWorkspaceDir().getAbsolutePath()) - .withSegmentSize(config.getSegmentSize()) - .withSoraldRepairMode(config.getSoraldRepairMode()) - .withSoraldMaxFixesPerRule(config.getSoraldMaxFixesPerRule()); + .withOutputDir(config.getWorkspaceDir().getAbsolutePath()); ProcessBuilder builder = repProcBuilder.build().directory(config.getWorkspaceDir()); builder.redirectErrorStream(true); @@ -522,9 +475,6 @@ public void configure(String url,String branch, EnvVars env) { config.setTools(this.getTools()); config.setNotifyTo(this.notifyTo); config.setSonarRules(SonarRulesBlock.constructCmdStr4Rules()); - config.setSoraldRepairMode(this.soraldRepairMode); - config.setSoraldMaxFixesPerRule(this.soraldMaxFixesPerRule); - config.setSegmentSize(this.segmentSize); config.setWorkspaceDir(workspaceDir); } diff --git a/src/repairnator-jenkins-plugin/src/main/java/io/jenkins/plugins/main/RepairnatorProcessBuilder.java b/src/repairnator-jenkins-plugin/src/main/java/io/jenkins/plugins/main/RepairnatorProcessBuilder.java index 3d602240c..ba64213dc 100644 --- a/src/repairnator-jenkins-plugin/src/main/java/io/jenkins/plugins/main/RepairnatorProcessBuilder.java +++ b/src/repairnator-jenkins-plugin/src/main/java/io/jenkins/plugins/main/RepairnatorProcessBuilder.java @@ -26,9 +26,6 @@ public class RepairnatorProcessBuilder { private String mavenHome; private String outputDir; private String sonarRules; - private String segmentSize; - private String soraldMaxFixesPerRule; - private String soraldRepairMode; private boolean createPR; private boolean useSmtpTLS; private boolean noTravisRepair; @@ -127,21 +124,6 @@ public RepairnatorProcessBuilder withSonarRules(String sonarRules) { } - public RepairnatorProcessBuilder withSegmentSize(int segmentSize) { - this.segmentSize = "" + segmentSize; - return this; - } - - public RepairnatorProcessBuilder withSoraldRepairMode(String soraldRepairMode) { - this.soraldRepairMode = soraldRepairMode; - return this; - } - - public RepairnatorProcessBuilder withSoraldMaxFixesPerRule(int soraldMaxFixesPerRule) { - this.soraldMaxFixesPerRule = "" + soraldMaxFixesPerRule; - return this; - } - public void checkValid() { if (this.javaExec == null || this.javaExec.equals("")) { throw new IllegalArgumentException("Repairnator Process building failed: java executable location is null"); @@ -176,13 +158,7 @@ public ProcessBuilder build() { cmdList.add("NEW"); cmdList.add("--launcherMode"); cmdList.add("GIT_REPOSITORY"); - cmdList.add("--soraldRepairMode"); - cmdList.add(this.soraldRepairMode); - cmdList.add("--segmentSize"); - cmdList.add(this.segmentSize); - cmdList.add("--soraldMaxFixesPerRule"); - cmdList.add(this.soraldMaxFixesPerRule); - + cmdList.add("--output"); cmdList.add(this.outputDir); cmdList.add("--MavenHome"); diff --git a/src/repairnator-jenkins-plugin/src/main/resources/io/jenkins/plugins/main/RepairnatorPostBuild/config.jelly b/src/repairnator-jenkins-plugin/src/main/resources/io/jenkins/plugins/main/RepairnatorPostBuild/config.jelly index c43ea3aec..19aa9c808 100644 --- a/src/repairnator-jenkins-plugin/src/main/resources/io/jenkins/plugins/main/RepairnatorPostBuild/config.jelly +++ b/src/repairnator-jenkins-plugin/src/main/resources/io/jenkins/plugins/main/RepairnatorPostBuild/config.jelly @@ -85,15 +85,5 @@ - - - - - - - - - - diff --git a/src/repairnator-pipeline/pom.xml b/src/repairnator-pipeline/pom.xml index fd8245dca..4719eb96e 100644 --- a/src/repairnator-pipeline/pom.xml +++ b/src/repairnator-pipeline/pom.xml @@ -41,7 +41,7 @@ se.kth.castor sorald - 17f106c8e7b3aea25542966410c0b26c2e6c2e43-SNAPSHOT + 0.3.0 fr.inria.repairnator diff --git a/src/repairnator-pipeline/src/main/java/fr/inria/spirals/repairnator/pipeline/MainProcessFactory.java b/src/repairnator-pipeline/src/main/java/fr/inria/spirals/repairnator/pipeline/MainProcessFactory.java index dd1cdb49a..fa78058d7 100644 --- a/src/repairnator-pipeline/src/main/java/fr/inria/spirals/repairnator/pipeline/MainProcessFactory.java +++ b/src/repairnator-pipeline/src/main/java/fr/inria/spirals/repairnator/pipeline/MainProcessFactory.java @@ -2,6 +2,7 @@ import fr.inria.spirals.repairnator.GithubInputBuild; import fr.inria.spirals.repairnator.config.RepairnatorConfig; +import fr.inria.spirals.repairnator.process.step.repair.soraldbot.SoraldConstants; import fr.inria.spirals.repairnator.states.LauncherMode; import java.util.List; @@ -12,7 +13,6 @@ import fr.inria.spirals.repairnator.process.inspectors.InspectorFactory; import fr.inria.spirals.repairnator.process.inspectors.ProjectInspector; import fr.inria.spirals.repairnator.process.inspectors.GitRepositoryProjectInspector; -import fr.inria.spirals.repairnator.process.step.repair.Sorald; import fr.inria.spirals.repairnator.serializer.HardwareInfoSerializer; import fr.inria.spirals.repairnator.serializer.InspectorSerializer; @@ -138,7 +138,8 @@ private static void serializeHardwareInfoSerializer(List engin /* These methods below should be called after all other inits */ /* move serializer into project inspector and get to construct */ private static GitRepositoryProjectInspector constructInspector4Github(List engines,List notifiers) { - boolean shouldStaticAnalysis = getConfig().getRepairTools().contains(Sorald.TOOL_NAME) && getConfig().getRepairTools().size() == 1; + boolean shouldStaticAnalysis = + getConfig().getRepairTools().contains(SoraldConstants.SORALD_TOOL_NAME) && getConfig().getRepairTools().size() == 1; GitRepositoryProjectInspector inspector = InspectorFactory.getGithubInspector( new GithubInputBuild( @@ -166,7 +167,8 @@ private static GitRepositoryProjectInspector constructInspector4Github(List engines, List notifiers) { ProjectInspector inspector; - boolean shouldStaticAnalysis = getConfig().getRepairTools().contains(Sorald.TOOL_NAME) && getConfig().getRepairTools().size() == 1; + boolean shouldStaticAnalysis = + getConfig().getRepairTools().contains(SoraldConstants.SORALD_TOOL_NAME) && getConfig().getRepairTools().size() == 1; LauncherMode launcherMode = getConfig().getLauncherMode(); String workspacePath = getConfig().getWorkspacePath(); diff --git a/src/repairnator-pipeline/src/main/java/fr/inria/spirals/repairnator/pipeline/RepairToolsManager.java b/src/repairnator-pipeline/src/main/java/fr/inria/spirals/repairnator/pipeline/RepairToolsManager.java index 6ef98af7b..74fce6b55 100644 --- a/src/repairnator-pipeline/src/main/java/fr/inria/spirals/repairnator/pipeline/RepairToolsManager.java +++ b/src/repairnator-pipeline/src/main/java/fr/inria/spirals/repairnator/pipeline/RepairToolsManager.java @@ -2,7 +2,6 @@ import fr.inria.spirals.repairnator.process.step.repair.AbstractRepairStep; import fr.inria.spirals.repairnator.process.step.repair.NPERepair; -import fr.inria.spirals.repairnator.process.step.repair.Sorald; import fr.inria.spirals.repairnator.process.step.repair.NPERepairSafe; import fr.inria.spirals.repairnator.process.step.repair.AssertFixerRepair; import fr.inria.spirals.repairnator.process.step.repair.sequencer.SequencerRepair; @@ -12,11 +11,12 @@ import fr.inria.spirals.repairnator.process.step.repair.astor.AstorJKaliRepair; import fr.inria.spirals.repairnator.process.step.repair.astor.AstorJGenProgRepair; import fr.inria.spirals.repairnator.process.step.repair.astor.AstorJMutRepair; +import fr.inria.spirals.repairnator.process.step.repair.soraldbot.SoraldBot; + import java.util.HashMap; import java.util.Map; import java.util.ServiceLoader; import java.util.Set; -import java.util.ArrayList; /** * This class defines a java ServiceLoader to automatically discover the available @@ -76,8 +76,8 @@ public void manualLoadRepairTools() { this.repairTools.put(astorJKali.getRepairToolName(),astorJKali); AbstractRepairStep astorJMut = new AstorJMutRepair(); this.repairTools.put(astorJMut.getRepairToolName(),astorJMut); - AbstractRepairStep sorald = new Sorald(); - this.repairTools.put(sorald.getRepairToolName(),sorald); + AbstractRepairStep soraldBot = new SoraldBot(); + this.repairTools.put(soraldBot.getRepairToolName(),soraldBot); } public static AbstractRepairStep getStepFromName(String name) { diff --git a/src/repairnator-pipeline/src/main/java/fr/inria/spirals/repairnator/process/step/repair/Sorald.java b/src/repairnator-pipeline/src/main/java/fr/inria/spirals/repairnator/process/step/repair/Sorald.java deleted file mode 100644 index 339a120b3..000000000 --- a/src/repairnator-pipeline/src/main/java/fr/inria/spirals/repairnator/process/step/repair/Sorald.java +++ /dev/null @@ -1,177 +0,0 @@ -package fr.inria.spirals.repairnator.process.step.repair; - -import fr.inria.spirals.repairnator.process.inspectors.RepairPatch; -import fr.inria.spirals.repairnator.process.step.StepStatus; -import fr.inria.spirals.repairnator.process.maven.MavenHelper; -import fr.inria.spirals.repairnator.process.testinformation.FailureLocation; -import fr.inria.spirals.repairnator.process.testinformation.FailureType; -import fr.inria.spirals.repairnator.process.git.GitHelper; - -import org.apache.commons.io.FileUtils; -import org.eclipse.jgit.api.errors.GitAPIException; -import org.eclipse.jgit.api.Git; - -import java.io.File; -import java.io.FileReader; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.lang.StringBuilder; -import java.nio.file.Paths; -import java.util.Arrays; -import java.util.Map; -import java.util.HashMap; -import java.net.URISyntaxException; -import java.util.Date; - -import fr.inria.spirals.repairnator.utils.DateUtils; -import fr.inria.spirals.repairnator.config.RepairnatorConfig; - -import org.apache.commons.lang3.text.StrSubstitutor; - -import sorald.Main; - -public class Sorald extends AbstractRepairStep { - public static final String TOOL_NAME = "Sorald"; - public static final String RULE_LINK_TEMPLATE = "https://rules.sonarsource.com/java/RSPEC-"; - private List allPatches = new ArrayList(); - private Git forkedGit; - private String forkedRepo; - - @Override - public String getRepairToolName() { - return TOOL_NAME; - } - - - @Override - protected StepStatus businessExecute() { - boolean patchFound = false; - this.getLogger().info("Entrance in Sorald step..."); - String pathToRepoDir = this.getInspector().getRepoLocalPath(); - - Map values = new HashMap(); - values.put("tools", String.join(",", this.getConfig().getRepairTools())); - StrSubstitutor sub = new StrSubstitutor(values, "%(", ")"); - StringBuilder prTextBuilder = new StringBuilder().append("This PR fixes the violations for the following Sorald rules: \n"); - String newBranchName = "repairnator-patch-" + DateUtils.formatFilenameDate(new Date()); - - for (String rule : RepairnatorConfig.getInstance().getSonarRules()) { - this.getLogger().info("Repo: " + pathToRepoDir); - this.getLogger().info("Try to repair rule " + rule); - String[] args = new String[]{ - "--originalFilesPath",pathToRepoDir, - "--ruleKeys",rule, - "--workspace", this.getConfig().getWorkspacePath(), - "--gitRepoPath",pathToRepoDir, - "--prettyPrintingStrategy","SNIPER", - "--maxFixesPerRule","" + getConfig().getSoraldMaxFixesPerRule(), - "--repairStrategy",RepairnatorConfig.getInstance().getSoraldRepairMode().name(), - "--maxFilesPerSegment","" + RepairnatorConfig.getInstance().getSegmentSize()}; - try { - Main.main(args); - } catch(Exception e) { - return StepStatus.buildSkipped(this,"Error while repairing with Sorald"); - } - - File patchDir = new File(RepairnatorConfig.getInstance().getWorkspacePath() + File.separator + "SoraldGitPatches"); - - - if (patchDir.exists()) { - File[] patchFiles = patchDir.listFiles(); - this.getLogger().info("Number of patches found: " + patchFiles.length); - if (patchFiles.length != 0) { - List repairPatches = new ArrayList(); - for (File patchFile : patchFiles) { - try { - String content = new String(Files.readAllBytes(patchFile.toPath()), StandardCharsets.UTF_8); - RepairPatch repairPatch = new RepairPatch(this.getRepairToolName(), "", content); - repairPatches.add(repairPatch); - } catch (Exception e) { - return StepStatus.buildSkipped(this,"Error while retrieving patches"); - } - patchFile.delete(); - } - prTextBuilder.append(RULE_LINK_TEMPLATE).append(rule + "\n"); - this.performApplyPatch(repairPatches,repairPatches.size(),rule,newBranchName); - if (!patchFound) { - patchFound = true; - this.allPatches.addAll(repairPatches); // Only mailing patches will only support single rule repair - FIXME - } - } - } - } - - prTextBuilder.append("If you do no want to receive automated PRs for Sorald warnings, reply to this PR with 'STOP'"); - if (!patchFound) { - return StepStatus.buildPatchNotFound(this); - } - - allPatches = this.performPatchAnalysis(allPatches); - if (allPatches.isEmpty()) { - return StepStatus.buildPatchNotFound(this); - } - this.recordPatches(allPatches, MAX_PATCH_PER_TOOL); - if (this.getConfig().isCreatePR()) { - this.setPrText(prTextBuilder.toString()); - try { - this.pushPatches(this.forkedGit,this.forkedRepo,newBranchName); - this.setPRTitle("Fix Sorald violations"); - this.createPullRequest(this.getInspector().getGitRepositoryBranch(),newBranchName); - } catch(IOException | GitAPIException | URISyntaxException e) { - e.printStackTrace(); - return StepStatus.buildSkipped(this,"Error while creating pull request"); - } - } - System.out.println("All patches : " + allPatches.size()); - return StepStatus.buildSuccess(this); - } - - private void performApplyPatch(List patchList,int patchNbsLimit,String ruleNumber,String newBranchName) { - if (!patchList.isEmpty()) { - this.getInspector().getJobStatus().setHasBeenPatched(true); - List serializedPatches = null; - try { - serializedPatches = this.serializePatches(patchList); - } catch (IOException e) { - this.addStepError("Error while serializing patches", e); - } - if (serializedPatches != null) { - try { - if (this.forkedGit == null) { - this.forkedRepo = this.getForkedRepoName(); - if (this.forkedRepo == null) { - return; - } - this.forkedGit = this.createGitBranch4Push(newBranchName); - } - this.applyPatches4Sonar(this.forkedGit,serializedPatches,patchNbsLimit,ruleNumber); - } catch (IOException | GitAPIException | URISyntaxException e) { - this.addStepError("Error while creating the PR", e); - } - } else { - this.addStepError("No file has been serialized, so no PR will be created"); - } - - } - } - - private void applyPatches4Sonar(Git git,List patchList,int nbPatch,String ruleNumber) throws IOException, GitAPIException, URISyntaxException { - for (int i = 0; i < nbPatch && i < patchList.size(); i++) { - File patch = patchList.get(i); - ProcessBuilder processBuilder = new ProcessBuilder("git", "apply", patch.getAbsolutePath()) - .directory(new File(this.getInspector().getRepoLocalPath())).inheritIO(); - - try { - Process p = processBuilder.start(); - p.waitFor(); - } catch (InterruptedException|IOException e) { - this.addStepError("Error while executing git command to apply patch " + patch.getPath(), e); - } - } - git.commit().setAll(true).setAuthor(GitHelper.getCommitterIdent()).setCommitter(GitHelper.getCommitterIdent()).setMessage("Proposal for patching Sorald rule " + ruleNumber).call(); - } -} diff --git a/src/repairnator-pipeline/src/main/java/fr/inria/spirals/repairnator/process/step/repair/soraldbot/SoraldAdapter.java b/src/repairnator-pipeline/src/main/java/fr/inria/spirals/repairnator/process/step/repair/soraldbot/SoraldAdapter.java new file mode 100644 index 000000000..56c0ab311 --- /dev/null +++ b/src/repairnator-pipeline/src/main/java/fr/inria/spirals/repairnator/process/step/repair/soraldbot/SoraldAdapter.java @@ -0,0 +1,233 @@ +package fr.inria.spirals.repairnator.process.step.repair.soraldbot; + +import fr.inria.spirals.repairnator.process.step.repair.soraldbot.models.SoraldTargetCommit; +import org.apache.commons.io.FileUtils; +import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.api.errors.GitAPIException; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import sorald.Constants; +import sorald.Main; + +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; + +import static fr.inria.spirals.repairnator.process.step.repair.soraldbot.SoraldConstants.SORALD_GIT_PATCHES_DIR; + +public class SoraldAdapter { + private static final Logger logger = LoggerFactory.getLogger(SoraldAdapter.class); + private static final String MINING_STATS_FILENAME = "mining_stats.json"; + private static final String MINING_TMP_DIR_PATH = "mining_tmp_dir"; + private static final String MINED_RULES_KEY = "minedRules"; + private static final String PREVIOUS_COMMIT_REF = "HEAD^"; + private static SoraldAdapter _instance; + + private String patchPrintingMode; + private String tmpdir; + + public SoraldAdapter(String tmpdir, String patchPrintingMode) { + this.tmpdir = tmpdir; + this.patchPrintingMode = patchPrintingMode; + } + + public static SoraldAdapter getInstance(String tmpdir, String patchPrintingMode) { + if (_instance == null) + _instance = new SoraldAdapter(tmpdir, patchPrintingMode); + return _instance; + } + + // Clones the repo in @repoPath, fixes all violations, returns violation introducing file paths. + public Set repairRepoAndReturnViolationIntroducingFiles (SoraldTargetCommit commit, String rule, String repoPath) + throws ParseException, GitAPIException, IOException, InterruptedException { + logger.info("repairing: " + commit.getCommitUrl()); + + File repoDir = cloneRepo(commit.getRepoUrl(), commit.getCommitId(), repoPath); + logger.info("repo cloned: " + commit.getRepoName()); + + Map> ruleToIntroducingFiles = getIntroducedViolations(repoDir); + logger.info("number of introduced rules: " + ruleToIntroducingFiles.entrySet().size()); + + if(!ruleToIntroducingFiles.containsKey(rule)) + return null; + + repair(rule, repoDir, patchPrintingMode); + + return ruleToIntroducingFiles.get(rule); + } + + + // returns patch files + public void repair(String rule, File repoDir, String patchPrintingMode) { + String[] args = new String[]{ + Constants.REPAIR_COMMAND_NAME, + Constants.ARG_SOURCE, repoDir.getPath(), + Constants.ARG_RULE_KEY, rule, +// Constants.ARG_TEMP_DIR, tmpdir, + Constants.ARG_PRETTY_PRINTING_STRATEGY, patchPrintingMode}; + + Main.main(args); + } + + /** + * @return A map from ruleNumber to the set of files with more violation locations in the new version. + */ + public Map> getIntroducedViolations(File repoDir) + throws IOException, GitAPIException, ParseException, InterruptedException { + File copyRepoDir = new File(tmpdir + File.separator + "copy_repo"); + if (copyRepoDir.exists()) + FileUtils.deleteDirectory(copyRepoDir); + + copyRepoDir.mkdirs(); + + FileUtils.copyDirectory(repoDir, copyRepoDir); + + Map> lastRuleToLocations = listViolationLocations(copyRepoDir); +// Map> lastRuleToLocations = null; + + ProcessBuilder processBuilder = + new ProcessBuilder("git", "stash") + .directory(copyRepoDir).inheritIO(); + Process p = processBuilder.start(); + int res = p.waitFor(); + if (res != 0) { + logger.error("cannot stash"); + return new HashMap>(); + } + + processBuilder = + new ProcessBuilder("git", "checkout", PREVIOUS_COMMIT_REF) + .directory(copyRepoDir).inheritIO(); + p = processBuilder.start(); + res = p.waitFor(); + if (res != 0) { + logger.error("cannot checkout to " + PREVIOUS_COMMIT_REF); + return new HashMap>(); + } + + Map> previousRuleToLocations = listViolationLocations(copyRepoDir); +// Map> previousRuleToLocations = null; + + FileUtils.deleteDirectory(copyRepoDir); + + Map> ret = new HashMap>(); + + for (Map.Entry> e : lastRuleToLocations.entrySet()) { + String ruleNumber = e.getKey(); + + // a map from the filename to the number of violations of this type in that file + Map newFileToViolationCnt = + e.getValue().stream().map(specifier -> specifier.split(File.pathSeparator)[1]) + .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); + + Map oldFileToViolationCnt = + !previousRuleToLocations.containsKey(ruleNumber) ? new HashMap() : + previousRuleToLocations.get(ruleNumber).stream() + .map(specifier -> specifier.split(File.pathSeparator)[1]) + .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); + + ret.put(ruleNumber, newFileToViolationCnt.entrySet().stream() + .filter(x -> !oldFileToViolationCnt.containsKey(x.getKey()) + || x.getValue() > oldFileToViolationCnt.get(x.getKey())) + .map(Map.Entry::getKey).collect(Collectors.toSet())); + + if (ret.containsKey(ruleNumber) && ret.get(ruleNumber).size() == 0) + ret.remove(ruleNumber); + } + + return ret; + } + + /** + * @param repoDir . + * @return A map from ruleNumber to the set of corresponding violation locations. + */ + public Map> listViolationLocations(File repoDir) throws IOException, ParseException { + Map> ret = new HashMap>(); + + File stats = new File(tmpdir + File.separator + MINING_STATS_FILENAME); +// miningTmpFile = new File(tmpdir + File.separator + MINING_TMP_DIR_PATH); + + if (stats.exists()) + stats.delete(); + +// if (miningTmpFile.exists()) +// FileUtils.deleteDirectory(miningTmpFile); + + stats.createNewFile(); + +// miningTmpFile.mkdirs(); + + String[] args = + new String[]{ + Constants.MINE_COMMAND_NAME, + Constants.ARG_SOURCE, + repoDir.getPath(), +// Constants.ARG_TEMP_DIR, +// miningTmpFile.getPath(), + Constants.ARG_STATS_OUTPUT_FILE, + stats.getPath(), + Constants.ARG_HANDLED_RULES + }; + +// FileUtils.deleteDirectory(miningTmpFile); + + Main.main(args); + + JSONParser parser = new JSONParser(); + JSONObject jo = (JSONObject) parser.parse(new FileReader(stats)); + JSONArray ja = (JSONArray) jo.get(MINED_RULES_KEY); + for (int i = 0; i < ja.size(); i++) { + Set violationLocations = new HashSet(); + + jo = (JSONObject) ja.get(i); + String rule = jo.get("ruleKey").toString(); + + JSONArray warningLocations = (JSONArray) jo.get("warningLocations"); + for (int j = 0; j < warningLocations.size(); j++) { + jo = (JSONObject) warningLocations.get(j); + String location = jo.get("violationSpecifier").toString(); + violationLocations.add(location); + } + + if (violationLocations.size() > 0) { + ret.put(rule, violationLocations); + } + } + + stats.delete(); + + return ret; + } + + + + public File cloneRepo(String repoUrl, String commitId, String dirname) + throws IOException, GitAPIException { + File repoDir = new File(tmpdir + File.separator + dirname); + + if (repoDir.exists()) + FileUtils.deleteDirectory(repoDir); + + repoDir.mkdirs(); + + Git git = Git.cloneRepository() + .setURI(repoUrl) + .setDirectory(repoDir) + .call(); + + if (commitId != null) + git.checkout().setName(commitId).call(); + + git.close(); + + return repoDir; + } +} diff --git a/src/repairnator-pipeline/src/main/java/fr/inria/spirals/repairnator/process/step/repair/soraldbot/SoraldBot.java b/src/repairnator-pipeline/src/main/java/fr/inria/spirals/repairnator/process/step/repair/soraldbot/SoraldBot.java new file mode 100644 index 000000000..f281ede47 --- /dev/null +++ b/src/repairnator-pipeline/src/main/java/fr/inria/spirals/repairnator/process/step/repair/soraldbot/SoraldBot.java @@ -0,0 +1,227 @@ +package fr.inria.spirals.repairnator.process.step.repair.soraldbot; + +import fr.inria.spirals.repairnator.config.RepairnatorConfig; +import fr.inria.spirals.repairnator.process.git.GitHelper; +import fr.inria.spirals.repairnator.process.inspectors.RepairPatch; +import fr.inria.spirals.repairnator.process.step.StepStatus; +import fr.inria.spirals.repairnator.process.step.repair.AbstractRepairStep; +import fr.inria.spirals.repairnator.process.step.repair.soraldbot.models.SoraldTargetCommit; +import fr.inria.spirals.repairnator.utils.DateUtils; +import org.apache.commons.io.FileUtils; +import org.eclipse.jgit.api.AddCommand; +import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.api.errors.GitAPIException; +import org.eclipse.jgit.diff.DiffFormatter; +import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.lib.ObjectReader; +import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.revwalk.RevCommit; +import org.eclipse.jgit.revwalk.RevWalk; +import org.eclipse.jgit.treewalk.AbstractTreeIterator; +import org.eclipse.jgit.treewalk.CanonicalTreeParser; +import org.kohsuke.github.GHBranch; +import org.kohsuke.github.GHRepository; +import org.kohsuke.github.GitHub; +import org.kohsuke.github.GitHubBuilder; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.net.URISyntaxException; +import java.util.*; + +/* + Performs Sorald repair on a given commit for a given sonar_rule. + Note: getConfig().isCreate should be set to true to create a PR. + */ +public class SoraldBot extends AbstractRepairStep { + private static final String REPO_PATH = "tmp_repo"; + private static final String RULE_LINK_TEMPLATE = "https://rules.sonarsource.com/java/RSPEC-"; + private SoraldTargetCommit commit; + private String originalBranchName; + + private String workingRepoPath; + + /** + * {@return if the initialization is successful} + */ + private boolean init() { + commit = new SoraldTargetCommit(getConfig().getGitCommitHash(), getInspector().getRepoSlug()); + workingRepoPath = getInspector().getWorkspace() + File.separator + REPO_PATH; + + try { + originalBranchName = getOriginalBranch(); + } catch (IOException e) { + getLogger().error("IOException while looking for the original branch"); + } + + return commit != null && workingRepoPath != null && originalBranchName != null; + } + + @Override + public String getRepairToolName() { + return SoraldConstants.SORALD_TOOL_NAME; + } + + @Override + protected StepStatus businessExecute() { + boolean successfulInit = init(); + if(!successfulInit){ + return StepStatus.buildSkipped(this, "Error while repairing with Sorald"); + } + + List rules = Arrays.asList(RepairnatorConfig.getInstance().getSonarRules()); + try { + for (String rule : rules) { + Set patchedFiles = + SoraldAdapter.getInstance(getInspector().getWorkspace(), SoraldConstants.SPOON_SNIPER_MODE) + .repairRepoAndReturnViolationIntroducingFiles(commit, rule, REPO_PATH); + + if(patchedFiles != null && !patchedFiles.isEmpty()){ + this.getInspector().getJobStatus().setHasBeenPatched(true); + createPRWithSpecificPatchedFiles(patchedFiles, rule); + } + } + } catch (Exception e) { + return StepStatus.buildSkipped(this, "Error while repairing with Sorald"); + } + + return StepStatus.buildSuccess(this); + } + + private void createPRWithSpecificPatchedFiles(Set violationIntroducingFiles, String rule) + throws GitAPIException, IOException, URISyntaxException { + + String diffStr = applyPatches4SonarAndGetDiffStr(violationIntroducingFiles, rule); + List repairPatches = new ArrayList(); + RepairPatch repairPatch = new RepairPatch(this.getRepairToolName(), "", diffStr); + repairPatches.add(repairPatch); + + notify(repairPatches); + + + String newBranchName = "repairnator-patch-" + DateUtils.formatFilenameDate(new Date()); + String forkedRepo = null; + Git forkedGit = null; + if (forkedGit == null) { + forkedRepo = this.getForkedRepoName(); + if (forkedRepo == null) { + return; + } + } + + + forkedGit = this.createGitBranch4Push(newBranchName); + + StringBuilder prTextBuilder = new StringBuilder() + .append("This PR fixes the violations for the following Sorald rule: \n"); + prTextBuilder.append(RULE_LINK_TEMPLATE).append(rule + "\n"); + prTextBuilder.append("If you do no want to receive automated PRs for Sorald warnings, reply to this PR with 'STOP'"); + setPrText(prTextBuilder.toString()); + setPRTitle("Fix Sorald violations"); + + + pushPatches(forkedGit, forkedRepo, newBranchName); + createPullRequest(originalBranchName, newBranchName); + } + + private String getOriginalBranch() throws IOException { + GitHub github = new GitHubBuilder().withOAuthToken(RepairnatorConfig.getInstance().getGithubToken()).build(); + GHRepository repo = github.getRepository(getInspector().getRepoSlug()); + Map branches = repo.getBranches(); + Optional branch = branches + .keySet().stream() + .filter(key -> branches.get(key).getSHA1().equals(commit.getCommitId())) + .findFirst(); + + if(!branch.isPresent()){ + getLogger().error("The branch of the commit was not found"); + return null; + } + return branch.get(); + } + + private String applyPatches4SonarAndGetDiffStr(Set violationIntroducingFiles, String ruleNumber) + throws IOException, GitAPIException, URISyntaxException { + FileUtils.copyDirectory(new File(workingRepoPath), new File(getInspector().getRepoLocalPath())); + + Git git = Git.open(new File(this.getInspector().getRepoLocalPath())); + AddCommand addCommand = git.add(); + violationIntroducingFiles.forEach(f -> addCommand.addFilepattern(f)); + addCommand.setUpdate(true); + addCommand.call(); + + git.commit().setAuthor(GitHelper.getCommitterIdent()).setCommitter(GitHelper.getCommitterIdent()) + .setMessage("Proposal for patching Sorald rule " + ruleNumber).call(); + + String diffStr = getDiffStrForLatestCommit(git.getRepository()); + + git.close(); + + return diffStr; + } + + private String getDiffStrForLatestCommit(Repository repo) throws IOException { + String hashID = repo.getAllRefs().get("HEAD").getObjectId().getName(); + + RevCommit newCommit; + try (RevWalk walk = new RevWalk(repo)) { + newCommit = walk.parseCommit(repo.resolve(hashID)); + } + + return getDiffOfCommit(newCommit, repo); + } + + + //Helper gets the diff as a string. + private String getDiffOfCommit(RevCommit newCommit, Repository repo) throws IOException { + + //Get commit that is previous to the current one. + RevCommit oldCommit = getPrevHash(newCommit, repo); + if(oldCommit == null){ + return "Start of repo"; + } + //Use treeIterator to diff. + AbstractTreeIterator oldTreeIterator = getCanonicalTreeParser(oldCommit, repo); + AbstractTreeIterator newTreeIterator = getCanonicalTreeParser(newCommit, repo); + OutputStream outputStream = new ByteArrayOutputStream(); + try (DiffFormatter formatter = new DiffFormatter(outputStream)) { + formatter.setRepository(repo); + formatter.format(oldTreeIterator, newTreeIterator); + } + String diff = outputStream.toString(); + return diff; + } + + //Helper function to get the previous commit. + public RevCommit getPrevHash(RevCommit commit, Repository repo) throws IOException { + + try (RevWalk walk = new RevWalk(repo)) { + // Starting point + walk.markStart(commit); + int count = 0; + for (RevCommit rev : walk) { + // got the previous commit. + if (count == 1) { + return rev; + } + count++; + } + walk.dispose(); + } + //Reached end and no previous commits. + return null; + } + + //Helper function to get the tree of the changes in a commit. Written by RĂ¼diger Herrmann + private AbstractTreeIterator getCanonicalTreeParser(ObjectId commitId, Repository repo) throws IOException { + try (RevWalk walk = new RevWalk(repo)) { + RevCommit commit = walk.parseCommit(commitId); + ObjectId treeId = commit.getTree().getId(); + try (ObjectReader reader = repo.newObjectReader()) { + return new CanonicalTreeParser(null, reader, treeId); + } + } + } +} diff --git a/src/repairnator-pipeline/src/main/java/fr/inria/spirals/repairnator/process/step/repair/soraldbot/SoraldConstants.java b/src/repairnator-pipeline/src/main/java/fr/inria/spirals/repairnator/process/step/repair/soraldbot/SoraldConstants.java new file mode 100644 index 000000000..b40b38231 --- /dev/null +++ b/src/repairnator-pipeline/src/main/java/fr/inria/spirals/repairnator/process/step/repair/soraldbot/SoraldConstants.java @@ -0,0 +1,7 @@ +package fr.inria.spirals.repairnator.process.step.repair.soraldbot; + +public class SoraldConstants { + public static final String SORALD_GIT_PATCHES_DIR = "SoraldGitPatches"; + public static final String SPOON_SNIPER_MODE = "SNIPER"; + public static final String SORALD_TOOL_NAME = "SoraldBot"; +} diff --git a/src/repairnator-pipeline/src/main/java/fr/inria/spirals/repairnator/process/step/repair/soraldbot/models/SoraldTargetCommit.java b/src/repairnator-pipeline/src/main/java/fr/inria/spirals/repairnator/process/step/repair/soraldbot/models/SoraldTargetCommit.java new file mode 100644 index 000000000..6f50b0635 --- /dev/null +++ b/src/repairnator-pipeline/src/main/java/fr/inria/spirals/repairnator/process/step/repair/soraldbot/models/SoraldTargetCommit.java @@ -0,0 +1,51 @@ +package fr.inria.spirals.repairnator.process.step.repair.soraldbot.models; + +public class SoraldTargetCommit { + private static final String REPO_URL_TEMPLATE = "https://github.com/{slug}/"; + private static final String COMMIT_URL_TEMPLATE = REPO_URL_TEMPLATE + "commit/{commit-id}"; + + private String commitUrl; + private String commitId; + private String repoUrl; + private String repoName; + + public SoraldTargetCommit(String commitId, String repoName){ + this.repoName = repoName; + this.commitId = commitId; + + this.repoUrl = REPO_URL_TEMPLATE.replace("{slug}", repoName); + this.commitUrl = COMMIT_URL_TEMPLATE.replace("{slug}", repoName).replace("{commit-id}", commitId); + } + + public String getCommitUrl() { + return commitUrl; + } + + public void setCommitUrl(String commitUrl) { + this.commitUrl = commitUrl; + } + + public String getCommitId() { + return commitId; + } + + public void setCommitId(String commitId) { + this.commitId = commitId; + } + + public String getRepoUrl() { + return repoUrl; + } + + public void setRepoUrl(String repoUrl) { + this.repoUrl = repoUrl; + } + + public String getRepoName() { + return repoName; + } + + public void setRepoName(String repoName) { + this.repoName = repoName; + } +} diff --git a/src/repairnator-pipeline/src/main/resources/META-INF/services/fr.inria.spirals.repairnator.process.step.repair.AbstractRepairStep b/src/repairnator-pipeline/src/main/resources/META-INF/services/fr.inria.spirals.repairnator.process.step.repair.AbstractRepairStep index 1c5e798ae..728f51f6a 100644 --- a/src/repairnator-pipeline/src/main/resources/META-INF/services/fr.inria.spirals.repairnator.process.step.repair.AbstractRepairStep +++ b/src/repairnator-pipeline/src/main/resources/META-INF/services/fr.inria.spirals.repairnator.process.step.repair.AbstractRepairStep @@ -7,5 +7,5 @@ fr.inria.spirals.repairnator.process.step.repair.nopol.NopolMultiWithTestExclusi fr.inria.spirals.repairnator.process.step.repair.nopol.NopolSingleTestRepair fr.inria.spirals.repairnator.process.step.repair.nopol.NopolAllTestsRepair fr.inria.spirals.repairnator.process.step.repair.NPERepair -fr.inria.spirals.repairnator.process.step.repair.Sorald +fr.inria.spirals.repairnator.process.step.repair.soraldbot.SoraldBot fr.inria.spirals.repairnator.process.step.repair.sequencer.SequencerRepair diff --git a/src/repairnator-pipeline/src/test/java/fr/inria/spirals/repairnator/pipeline/TestPipelineArgs.java b/src/repairnator-pipeline/src/test/java/fr/inria/spirals/repairnator/pipeline/TestPipelineArgs.java index ef5675050..c3296be4f 100644 --- a/src/repairnator-pipeline/src/test/java/fr/inria/spirals/repairnator/pipeline/TestPipelineArgs.java +++ b/src/repairnator-pipeline/src/test/java/fr/inria/spirals/repairnator/pipeline/TestPipelineArgs.java @@ -155,15 +155,6 @@ public void testDefaultArgsLauncher() throws Exception { String defaultSonarRules = "2116"; assertEquals(defaultSonarRules, LauncherUtils.getArgSonarRules(arguments)); assertArrayEquals(Arrays.stream(defaultSonarRules.split(",")).distinct().toArray(String[]::new), config.getSonarRules()); - RepairnatorConfig.SORALD_REPAIR_MODE defaultSoraldRepairMode = RepairnatorConfig.SORALD_REPAIR_MODE.DEFAULT; - assertEquals(defaultSoraldRepairMode.name(), LauncherUtils.getArgSoraldRepairMode(arguments)); - assertEquals(defaultSoraldRepairMode, config.getSoraldRepairMode()); - Integer defaultSegmentSize = 200; - assertEquals(defaultSegmentSize, LauncherUtils.getArgSegmentSize(arguments)); - assertEquals((int) defaultSegmentSize, config.getSegmentSize()); - Integer defaultMaxFixesPerRule = 2000; - assertEquals(defaultMaxFixesPerRule, LauncherUtils.getArgSoraldMaxFixesPerRule(arguments)); - assertEquals((int) defaultMaxFixesPerRule, config.getSoraldMaxFixesPerRule()); // default NPEFix rules String defaultNPESelection = "exploration"; diff --git a/src/repairnator-pipeline/src/test/java/fr/inria/spirals/repairnator/pipeline/TestPipelineSoraldBot.java b/src/repairnator-pipeline/src/test/java/fr/inria/spirals/repairnator/pipeline/TestPipelineSoraldBot.java new file mode 100644 index 000000000..1f83e4b1c --- /dev/null +++ b/src/repairnator-pipeline/src/test/java/fr/inria/spirals/repairnator/pipeline/TestPipelineSoraldBot.java @@ -0,0 +1,72 @@ +package fr.inria.spirals.repairnator.pipeline; + +import fr.inria.spirals.repairnator.config.RepairnatorConfig; +import fr.inria.spirals.repairnator.notifier.PatchNotifier; +import fr.inria.spirals.repairnator.process.inspectors.ProjectInspector; +import fr.inria.spirals.repairnator.process.inspectors.RepairPatch; +import fr.inria.spirals.repairnator.process.step.AbstractStep; +import org.junit.After; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class TestPipelineSoraldBot { + @Rule + public TemporaryFolder workspaceFolder = new TemporaryFolder(); + + @Rule + public TemporaryFolder outputFolder = new TemporaryFolder(); + + @After + public void tearDown() throws IOException { + RepairnatorConfig.deleteInstance(); + } + + @Test + public void TestPipelineSoraldRepairTool() throws Exception { + Launcher launcher = new Launcher(new String[]{ + "--gitrepo", + "--gitrepourl", "https://github.com/khaes-kth/Sorald-CI-Sample", + "--gitcommithash", "e2e0e568412cd05efb4475715f457473b3777437", + "--sonarRules", "1217", + "--repairTools", "SoraldBot", + "--launcherMode", "GIT_REPOSITORY", + "--workspace", workspaceFolder.getRoot().getAbsolutePath(), + "--output", outputFolder.getRoot().getAbsolutePath() + }); + + // config is forced to use SoraldBot as the only repair tool. + assertEquals(1, launcher.getConfig().getRepairTools().size()); + assertTrue(launcher.getConfig().getRepairTools().contains("SoraldBot")); + + Patches patchNotifier = new Patches(); + launcher.setPatchNotifier(patchNotifier); + + launcher.mainProcess(); + + List steps = launcher.getInspector().getSteps() + .stream() + .filter(step -> step.getName().equals("SoraldBot")) + .collect(Collectors.toList()); //test fix sorald-bot repair + + assertEquals(1, steps.size()); + assertEquals(1, patchNotifier.allpatches.size()); + } + + class Patches implements PatchNotifier { + List allpatches = new ArrayList<>(); + + @Override + public void notify(ProjectInspector inspector, String toolname, List patches) { + allpatches.addAll(patches); + } + } +} diff --git a/src/repairnator-pipeline/src/test/java/fr/inria/spirals/repairnator/pipelineb/TestPipelinebGithubMode.java b/src/repairnator-pipeline/src/test/java/fr/inria/spirals/repairnator/pipelineb/TestPipelinebGithubMode.java index 7d59f21d6..3a5bc6268 100644 --- a/src/repairnator-pipeline/src/test/java/fr/inria/spirals/repairnator/pipelineb/TestPipelinebGithubMode.java +++ b/src/repairnator-pipeline/src/test/java/fr/inria/spirals/repairnator/pipelineb/TestPipelinebGithubMode.java @@ -95,26 +95,6 @@ public void testPipelineGitRepositoryAndCommitIdWithSuccess() throws Exception { assertTrue("patch is found", patchNotifier.allpatches.get(0).getDiff().contains("list == null")); } - @Test - public void testSoraldWithSuccess() throws Exception { - GithubMainProcess mainProc = (GithubMainProcess) MainProcessFactory.getGithubMainProcess(new String[]{ - "--gitrepo", - "--gitrepourl", "https://github.com/henry-lp/SonarQubeRepairTests", - "--gitrepobranch", "master", - "--sonarRules", "2116", - "--repairTools", "Sorald", - "--soraldMaxFixesPerRule", "1", - "--workspace", workspaceFolder.getRoot().getAbsolutePath(), - "--output", outputFolder.getRoot().getAbsolutePath(), - }); - - Patches patchNotifier = new Patches(); - mainProc.setPatchNotifier(patchNotifier); - mainProc.run(); - assertEquals("PATCHED", mainProc.getInspector().getFinding()); - assertEquals(1, patchNotifier.allpatches.size()); - } - @Test public void testPipelineGitRepositoryFirstCommit() throws Exception { GithubMainProcess mainProc = (GithubMainProcess) MainProcessFactory.getGithubMainProcess(new String[]{ diff --git a/src/repairnator-realtime/src/main/java/fr/inria/spirals/repairnator/realtime/GithubScanner.java b/src/repairnator-realtime/src/main/java/fr/inria/spirals/repairnator/realtime/GithubScanner.java index f35fb46a1..a92401ab4 100644 --- a/src/repairnator-realtime/src/main/java/fr/inria/spirals/repairnator/realtime/GithubScanner.java +++ b/src/repairnator-realtime/src/main/java/fr/inria/spirals/repairnator/realtime/GithubScanner.java @@ -15,6 +15,8 @@ import java.util.concurrent.TimeUnit; public class GithubScanner { + private final static String SORALD_NAME = "Sorald_Bot", + SEQUENCER_NAME = "SequencerRepair"; static long scanIntervalDelay = 60 * 60 * 1000; // 1 hour static long scanIntervalLength = 60 * 60 * 1000; // 1 hour static long frequency = 60 * 60 * 1000; // 1 hour @@ -62,19 +64,25 @@ public GithubScanner(FetchMode fetchMode) { public List fetch() throws Exception { long endTime = System.currentTimeMillis() - scanIntervalDelay; - long startTime = endTime - scanIntervalLength; +// long startTime = endTime - scanIntervalLength; + long startTime = 0L; return fetch(startTime, endTime); } public void setup(){ Set repairTools = new HashSet(); - repairTools.add(getEnvOrDefault("REPAIR_TOOL", "SequencerRepair")); + String repairTool = getEnvOrDefault("REPAIR_TOOL", SEQUENCER_NAME); + repairTools.add(repairTool); RepairnatorConfig.getInstance().setRepairTools(repairTools); RepairnatorConfig.getInstance().setNbThreads(16); RepairnatorConfig.getInstance().setPipelineMode(RepairnatorConfig.PIPELINE_MODE.DOCKER.name()); RepairnatorConfig.getInstance().setGithubToken(System.getenv("GITHUB_OAUTH")); - RepairnatorConfig.getInstance().setLauncherMode(LauncherMode.SEQUENCER_REPAIR); + if(repairTool.equals(SORALD_NAME)) { + RepairnatorConfig.getInstance().setLauncherMode(LauncherMode.GIT_REPOSITORY); + } else if(repairTool.equals(SEQUENCER_NAME)) { + RepairnatorConfig.getInstance().setLauncherMode(LauncherMode.SEQUENCER_REPAIR); + } } public List fetch(long startTime, long endTime) throws Exception { diff --git a/src/repairnator-realtime/src/main/java/fr/inria/spirals/repairnator/realtime/githubapi/commits/GithubAPICommitAdapter.java b/src/repairnator-realtime/src/main/java/fr/inria/spirals/repairnator/realtime/githubapi/commits/GithubAPICommitAdapter.java index b058edd91..86ac7a977 100644 --- a/src/repairnator-realtime/src/main/java/fr/inria/spirals/repairnator/realtime/githubapi/commits/GithubAPICommitAdapter.java +++ b/src/repairnator-realtime/src/main/java/fr/inria/spirals/repairnator/realtime/githubapi/commits/GithubAPICommitAdapter.java @@ -80,7 +80,8 @@ public static GithubAPICommitAdapter getInstance() { repositories.parallelStream().forEach( repoName -> { try { GHRepository repo = GAA.g().getRepository(repoName); - System.out.println("Checking commits for: " + repo.getName() + " " + cnt.incrementAndGet() + " " + repositories.size() + System.out.println("Checking commits for: " + repo.getName() + " " + cnt.incrementAndGet() + " from " + + fixedRepos.size() + " " + new Date(intervalStart)); boolean isMaven = false; for (GHTreeEntry treeEntry : repo.getTree("HEAD").getTree()) { @@ -105,4 +106,5 @@ public static GithubAPICommitAdapter getInstance() { return selectedCommits; } + } diff --git a/src/repairnator-realtime/src/test/java/fr/inria/spirals/repairnator/realtime/TestGithubScanner.java b/src/repairnator-realtime/src/test/java/fr/inria/spirals/repairnator/realtime/TestGithubScanner.java index 52c4da8d4..f739f1a18 100644 --- a/src/repairnator-realtime/src/test/java/fr/inria/spirals/repairnator/realtime/TestGithubScanner.java +++ b/src/repairnator-realtime/src/test/java/fr/inria/spirals/repairnator/realtime/TestGithubScanner.java @@ -1,6 +1,7 @@ package fr.inria.spirals.repairnator.realtime; import fr.inria.spirals.repairnator.InputBuild; +import fr.inria.spirals.repairnator.realtime.githubapi.commits.GithubAPICommitAdapter; import fr.inria.spirals.repairnator.realtime.githubapi.commits.models.SelectedCommit; import org.apache.commons.io.FileUtils; import org.junit.Test;