diff options
Diffstat (limited to 'sonar-batch')
4 files changed, 121 insertions, 12 deletions
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scm/DefaultBlameOutput.java b/sonar-batch/src/main/java/org/sonar/batch/scm/DefaultBlameOutput.java index de873b135db..9f1e33b423c 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scm/DefaultBlameOutput.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scm/DefaultBlameOutput.java @@ -28,6 +28,7 @@ import org.sonar.api.measures.CoreMetrics; import org.sonar.api.measures.Metric; import org.sonar.api.measures.PropertiesBuilder; import org.sonar.api.utils.DateUtils; +import org.sonar.batch.util.ProgressReport; import javax.annotation.Nullable; @@ -36,6 +37,7 @@ import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.concurrent.TimeUnit; import java.util.regex.Pattern; class DefaultBlameOutput implements BlameOutput { @@ -45,14 +47,21 @@ class DefaultBlameOutput implements BlameOutput { private final SensorContext context; private final Set<InputFile> allFilesToBlame = new HashSet<InputFile>(); + private ProgressReport progressReport; + private int count; + private int total; DefaultBlameOutput(SensorContext context, List<InputFile> filesToBlame) { this.context = context; this.allFilesToBlame.addAll(filesToBlame); + count = 0; + total = filesToBlame.size(); + progressReport = new ProgressReport("Report about progress of SCM blame", TimeUnit.SECONDS.toMillis(10)); + progressReport.start(total + " files to be analyzed"); } @Override - public void blameResult(InputFile file, List<BlameLine> lines) { + public synchronized void blameResult(InputFile file, List<BlameLine> lines) { Preconditions.checkNotNull(file); Preconditions.checkNotNull(lines); Preconditions.checkArgument(allFilesToBlame.contains(file), "It was not expected to blame file " + file.relativePath()); @@ -73,6 +82,8 @@ class DefaultBlameOutput implements BlameOutput { } ScmSensor.saveMeasures(context, file, authors.buildData(), dates.buildData(), revisions.buildData()); allFilesToBlame.remove(file); + count++; + progressReport.message(count + "/" + total + " files analyzed, last one was " + file.absolutePath()); } private String normalizeString(@Nullable String inputString) { @@ -97,7 +108,10 @@ class DefaultBlameOutput implements BlameOutput { return new PropertiesBuilder<Integer, String>(metric); } - public Set<InputFile> remainingFiles() { - return allFilesToBlame; + public void finish() { + if (!allFilesToBlame.isEmpty()) { + throw new IllegalStateException("Some files were not blamed"); + } + progressReport.stop(count + "/" + count + " files analyzed"); } } diff --git a/sonar-batch/src/main/java/org/sonar/batch/scm/ScmConfiguration.java b/sonar-batch/src/main/java/org/sonar/batch/scm/ScmConfiguration.java index bc4e7208f1b..468b29e04a5 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scm/ScmConfiguration.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scm/ScmConfiguration.java @@ -29,8 +29,11 @@ import org.sonar.api.batch.InstantiationStrategy; import org.sonar.api.batch.bootstrap.ProjectReactor; import org.sonar.api.batch.scm.ScmProvider; import org.sonar.api.config.Settings; +import org.sonar.batch.phases.Phases; import org.sonar.core.DryRunIncompatible; +import javax.annotation.Nullable; + import java.util.LinkedHashMap; import java.util.Map; @@ -42,23 +45,38 @@ public final class ScmConfiguration implements BatchComponent, Startable { private final ProjectReactor projectReactor; private final Settings settings; private final Map<String, ScmProvider> providerPerKey = new LinkedHashMap<String, ScmProvider>(); + private final Phases phases; private ScmProvider provider; - public ScmConfiguration(ProjectReactor projectReactor, Settings settings, ScmProvider... providers) { + public ScmConfiguration(ProjectReactor projectReactor, Settings settings, @Nullable Phases phases, ScmProvider... providers) { this.projectReactor = projectReactor; this.settings = settings; + this.phases = phases; for (ScmProvider scmProvider : providers) { providerPerKey.put(scmProvider.key(), scmProvider); } } + // Scan 2 + public ScmConfiguration(ProjectReactor projectReactor, Settings settings, ScmProvider... providers) { + this(projectReactor, settings, null, providers); + } + + public ScmConfiguration(ProjectReactor projectReactor, Settings settings, Phases phases) { + this(projectReactor, settings, phases, new ScmProvider[0]); + } + + // Scan2 public ScmConfiguration(ProjectReactor projectReactor, Settings settings) { - this(projectReactor, settings, new ScmProvider[0]); + this(projectReactor, settings, null, new ScmProvider[0]); } @Override public void start() { + if (phases != null && !phases.isEnabled(Phases.Phase.SENSOR)) { + return; + } if (isDisabled()) { LOG.debug("SCM Step is disabled by configuration"); return; diff --git a/sonar-batch/src/main/java/org/sonar/batch/scm/ScmSensor.java b/sonar-batch/src/main/java/org/sonar/batch/scm/ScmSensor.java index 4480938a7a2..445fd2bf39e 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scm/ScmSensor.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scm/ScmSensor.java @@ -86,9 +86,7 @@ public final class ScmSensor implements Sensor { TimeProfiler profiler = new TimeProfiler().start("Retrieve SCM blame information"); DefaultBlameOutput output = new DefaultBlameOutput(context, filesToBlame); configuration.provider().blameCommand().blame(new DefaultBlameInput(fs, filesToBlame), output); - if (!output.remainingFiles().isEmpty()) { - throw new IllegalStateException("Some files were not blamed"); - } + output.finish(); profiler.stop(); } } @@ -112,10 +110,7 @@ public final class ScmSensor implements Sensor { } } - /** - * This method is synchronized since it is allowed for plugins to compute blame in parallel. - */ - static synchronized void saveMeasures(SensorContext context, InputFile f, String scmAuthorsByLine, String scmLastCommitDatetimesByLine, String scmRevisionsByLine) { + static void saveMeasures(SensorContext context, InputFile f, String scmAuthorsByLine, String scmLastCommitDatetimesByLine, String scmRevisionsByLine) { ((DefaultMeasure<String>) context.<String>newMeasure() .onFile(f) .forMetric(CoreMetrics.SCM_AUTHORS_BY_LINE) diff --git a/sonar-batch/src/main/java/org/sonar/batch/util/ProgressReport.java b/sonar-batch/src/main/java/org/sonar/batch/util/ProgressReport.java new file mode 100644 index 00000000000..80be1cead2e --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/util/ProgressReport.java @@ -0,0 +1,82 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.batch.util; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ProgressReport implements Runnable { + + private final long period; + private final Logger logger; + private String message = ""; + private final Thread thread; + private String stopMessage = ""; + + public ProgressReport(String threadName, long period, Logger logger) { + this.period = period; + this.logger = logger; + thread = new Thread(this); + thread.setName(threadName); + } + + public ProgressReport(String threadName, long period) { + this(threadName, period, LoggerFactory.getLogger(ProgressReport.class)); + } + + @Override + public void run() { + while (!Thread.interrupted()) { + try { + Thread.sleep(period); + log(message); + } catch (InterruptedException e) { + thread.interrupt(); + } + } + log(stopMessage); + } + + public void start(String startMessage) { + log(startMessage); + thread.start(); + } + + public void message(String message) { + this.message = message; + } + + public void stop(String stopMessage) { + this.stopMessage = stopMessage; + thread.interrupt(); + } + + public void join() throws InterruptedException { + thread.join(); + } + + private void log(String message) { + synchronized (logger) { + logger.info(message); + logger.notifyAll(); + } + } + +} |