Esempio n. 1
0
  /**
   * There are two things we need to check
   *
   * <ul>
   *   <li>files created or modified since last build time, we only need to check the source folder
   *   <li>file deleted since last build time, we have to compare source and destination folder
   * </ul>
   */
  @Override
  public boolean pollChanges(
      AbstractProject project, Launcher launcher, FilePath workspace, TaskListener listener)
      throws IOException, InterruptedException {

    long start = System.currentTimeMillis();

    PrintStream log = launcher.getListener().getLogger();
    log.println("FSSCM.pollChange: " + path);

    AllowDeleteList allowDeleteList = new AllowDeleteList(project.getRootDir());
    // we will only delete a file if it is listed in the allowDeleteList
    // ie. we will only delete a file if it is copied by us
    if (allowDeleteList.fileExists()) {
      allowDeleteList.load();
    } else {
      // watch list save file doesn't exist
      // we will assuem all existing files are under watch
      // ie. everything can be deleted
      Set<String> existingFiles = workspace.act(new RemoteListDir());
      allowDeleteList.setList(existingFiles);
    }

    RemoteFolderDiff.PollChange callable = new RemoteFolderDiff.PollChange();
    setupRemoteFolderDiff(callable, project, allowDeleteList.getList());

    boolean changed = workspace.act(callable);
    String str = callable.getLog();
    if (str.length() > 0) log.println(str);
    log.println("FSSCM.pollChange return " + changed);

    log.println(
        "FSSCM.poolChange completed in " + formatDurration(System.currentTimeMillis() - start));
    return changed;
  }
Esempio n. 2
0
  @Override
  public boolean checkout(
      AbstractBuild build,
      Launcher launcher,
      FilePath workspace,
      BuildListener listener,
      File changelogFile)
      throws IOException, InterruptedException {

    long start = System.currentTimeMillis();
    PrintStream log = launcher.getListener().getLogger();
    log.println("FSSCM.checkout " + path + " to " + workspace);
    Boolean b = Boolean.TRUE;

    AllowDeleteList allowDeleteList = new AllowDeleteList(build.getProject().getRootDir());

    if (clearWorkspace) {
      log.println("FSSCM.clearWorkspace...");
      workspace.deleteRecursive();
    }

    // we will only delete a file if it is listed in the allowDeleteList
    // ie. we will only delete a file if it is copied by us
    if (allowDeleteList.fileExists()) {
      allowDeleteList.load();
    } else {
      // watch list save file doesn't exist
      // we will assuem all existing files are under watch
      // ie. everything can be deleted
      Set<String> existingFiles = workspace.act(new RemoteListDir());
      allowDeleteList.setList(existingFiles);
    }

    RemoteFolderDiff.CheckOut callable = new RemoteFolderDiff.CheckOut();
    setupRemoteFolderDiff(callable, build.getProject(), allowDeleteList.getList());
    List<FolderDiff.Entry> list = workspace.act(callable);

    // maintain the watch list
    for (FolderDiff.Entry entry : list) {
      if (FolderDiff.Entry.Type.DELETED.equals(entry.getType())) {
        allowDeleteList.remove(entry.getFilename());
      } else {
        // added or modified
        allowDeleteList.add(entry.getFilename());
      }
    }
    allowDeleteList.save();

    // raw log
    String str = callable.getLog();
    if (str.length() > 0) log.println(str);

    ChangelogSet.XMLSerializer handler = new ChangelogSet.XMLSerializer();
    ChangelogSet changeLogSet = new ChangelogSet(build, list);
    handler.save(changeLogSet, changelogFile);

    log.println("FSSCM.check completed in " + formatDurration(System.currentTimeMillis() - start));
    return b;
  }
Esempio n. 3
0
  @Override
  public void perform(Run<?, ?> build, FilePath ws, Launcher launcher, TaskListener listener)
      throws InterruptedException {
    if (artifacts.length() == 0) {
      listener.error(Messages.ArtifactArchiver_NoIncludes());
      build.setResult(Result.FAILURE);
      return;
    }

    if (onlyIfSuccessful
        && build.getResult() != null
        && build.getResult().isWorseThan(Result.UNSTABLE)) {
      listener.getLogger().println(Messages.ArtifactArchiver_SkipBecauseOnlyIfSuccessful());
      return;
    }

    listener.getLogger().println(Messages.ArtifactArchiver_ARCHIVING_ARTIFACTS());
    try {
      String artifacts = build.getEnvironment(listener).expand(this.artifacts);

      Map<String, String> files =
          ws.act(new ListFiles(artifacts, excludes, defaultExcludes, caseSensitive));
      if (!files.isEmpty()) {
        build
            .pickArtifactManager()
            .archive(ws, launcher, BuildListenerAdapter.wrap(listener), files);
        if (fingerprint) {
          new Fingerprinter(artifacts).perform(build, ws, launcher, listener);
        }
      } else {
        Result result = build.getResult();
        if (result != null && result.isBetterOrEqualTo(Result.UNSTABLE)) {
          // If the build failed, don't complain that there was no matching artifact.
          // The build probably didn't even get to the point where it produces artifacts.
          listenerWarnOrError(listener, Messages.ArtifactArchiver_NoMatchFound(artifacts));
          String msg = null;
          try {
            msg =
                ws.validateAntFileMask(
                    artifacts, FilePath.VALIDATE_ANT_FILE_MASK_BOUND, caseSensitive);
          } catch (Exception e) {
            listenerWarnOrError(listener, e.getMessage());
          }
          if (msg != null) listenerWarnOrError(listener, msg);
        }
        if (!allowEmptyArchive) {
          build.setResult(Result.FAILURE);
        }
        return;
      }
    } catch (IOException e) {
      Util.displayIOException(e, listener);
      e.printStackTrace(listener.error(Messages.ArtifactArchiver_FailedToArchive(artifacts)));
      build.setResult(Result.FAILURE);
      return;
    }
  }
Esempio n. 4
0
  /**
   * Start from scratch and clone the whole repository. Cloning into an existing directory is not
   * allowed, so the workspace is first deleted entirely, then <tt>git clone</tt> is performed.
   *
   * @param remoteConfig remote config
   * @throws GitException if deleting or cloning the workspace fails
   */
  public void clone(final RemoteConfig remoteConfig) throws GitException {
    listener.getLogger().println("Cloning repository " + remoteConfig.getName());
    final int[] gitVer = getGitVersion();

    // TODO: Not here!
    try {
      workspace.deleteRecursive();
    } catch (Exception e) {
      e.printStackTrace(listener.error("Failed to clean the workspace"));
      throw new GitException("Failed to delete workspace", e);
    }

    // Assume only 1 URL for this repository
    final String source = remoteConfig.getURIs().get(0).toPrivateString();

    try {
      workspace.act(
          new FileCallable<String>() {

            private static final long serialVersionUID = 1L;

            public String invoke(File workspace, VirtualChannel channel) throws IOException {
              final ArgumentListBuilder args = new ArgumentListBuilder();
              args.add("clone");
              if ((gitVer[0] >= 1) && (gitVer[1] >= 7)) {
                args.add("--progress");
              }
              if (reference != null) {
                File referencePath = new File(reference);
                if (referencePath.exists() && referencePath.isDirectory()) {
                  args.add("--reference", reference);
                }
              }
              args.add("-o", remoteConfig.getName());
              args.add(source);
              args.add(workspace.getAbsolutePath());
              return launchCommandIn(args, null);
            }
          });
    } catch (Exception e) {
      throw new GitException("Could not clone " + source, e);
    }
  }
Esempio n. 5
0
  public void labelBuild(TaskListener listener, String name, String description) throws Exception {
    // Expand label name and description
    name = expand.format(name, false);
    description = expand.format(description, false);

    TaggingTask task = new TaggingTask(name, description);
    task.setListener(listener);
    task.setCredential(credential);
    task.setWorkspace(workspace);
    task.setBuildChange(buildChange);

    // Invoke the Label Task
    FilePath buildWorkspace = build.getWorkspace();
    buildWorkspace.act(task);

    // save label
    if (!tags.contains(name)) {
      tags.add(name);
      getRun().save();
    }
  }
  @Override
  public void perform(
      Run<?, ?> run, FilePath buildWorkspace, Launcher launcher, TaskListener listener)
      throws InterruptedException, IOException {

    TagAction tagAction = (TagAction) run.getAction(TagAction.class);

    String credential = tagAction.getCredential();
    Workspace workspace = tagAction.getWorkspace();
    String client = tagAction.getClient();

    // Setup Unshelve Task
    RemoveClientTask task = new RemoveClientTask(client);
    task.setListener(listener);
    task.setCredential(credential);

    // Set workspace used for the Task
    Workspace ws = task.setEnvironment(run, workspace, buildWorkspace);
    task.setWorkspace(ws);

    buildWorkspace.act(task);
  }
  /**
   * Downloads and extracts the basic Android SDK on a given Node, if it hasn't already been done.
   *
   * @param node Node to install the SDK on.
   * @return Path where the SDK is installed, regardless of whether it was installed right now.
   * @throws SdkUnavailableException If the Android SDK is not available on this platform.
   */
  private static FilePath installBasicSdk(final BuildListener listener, Node node)
      throws SdkUnavailableException, IOException, InterruptedException {
    // Locate where the SDK should be installed to on this node
    final FilePath installDir = Utils.getSdkInstallDirectory(node);

    // Get the OS-specific download URL for the SDK
    AndroidInstaller installer = AndroidInstaller.fromNode(node);
    final URL downloadUrl = installer.getUrl(SDK_VERSION);

    // Download the SDK, if required
    boolean wasNowInstalled =
        installDir.act(
            new FileCallable<Boolean>() {
              public Boolean invoke(File f, VirtualChannel channel)
                  throws InterruptedException, IOException {
                String msg = Messages.DOWNLOADING_SDK_FROM(downloadUrl);
                return installDir.installIfNecessaryFrom(downloadUrl, listener, msg);
              }

              private static final long serialVersionUID = 1L;
            });

    if (wasNowInstalled) {
      // If the SDK was required, pull files up from the intermediate directory
      installDir.listDirectories().get(0).moveAllChildrenTo(installDir);

      // Java's ZipEntry doesn't preserve the executable bit...
      if (installer == AndroidInstaller.MAC_OS_X) {
        setPermissions(installDir.child("tools"));
      }

      // Success!
      log(listener.getLogger(), Messages.BASE_SDK_INSTALLED());
    }

    return installDir;
  }
Esempio n. 8
0
  @Override
  public boolean checkout(
      final AbstractBuild build,
      Launcher launcher,
      final FilePath workspace,
      final BuildListener listener,
      File changelogFile)
      throws IOException, InterruptedException {

    listener
        .getLogger()
        .println(
            "Checkout:"
                + workspace.getName()
                + " / "
                + workspace.getRemote()
                + " - "
                + workspace.getChannel());

    final String projectName = build.getProject().getName();
    final int buildNumber = build.getNumber();
    final String gitExe = getDescriptor().getGitExe();

    final String buildnumber = "hudson-" + projectName + "-" + buildNumber;

    final BuildData buildData = getBuildData(build.getPreviousBuild(), true);

    if (buildData != null && buildData.lastBuild != null) {
      listener.getLogger().println("Last Built Revision: " + buildData.lastBuild.revision);
    }

    EnvVars tmp = new EnvVars();
    try {
      tmp = build.getEnvironment(listener);
    } catch (InterruptedException e) {
      listener.error("Interrupted exception getting environment .. using empty environment");
    }
    final EnvVars environment = tmp;

    final String singleBranch = getSingleBranch(build);

    final Revision revToBuild =
        workspace.act(
            new FileCallable<Revision>() {
              private static final long serialVersionUID = 1L;

              public Revision invoke(File localWorkspace, VirtualChannel channel)
                  throws IOException {
                FilePath ws = new FilePath(localWorkspace);
                listener
                    .getLogger()
                    .println(
                        "Checkout:"
                            + ws.getName()
                            + " / "
                            + ws.getRemote()
                            + " - "
                            + ws.getChannel());

                IGitAPI git = new GitAPI(gitExe, ws, listener, environment);

                if (git.hasGitRepo()) {
                  // It's an update

                  listener.getLogger().println("Fetching changes from the remote Git repository");

                  for (RemoteConfig remoteRepository : getRepositories()) {
                    fetchFrom(git, localWorkspace, listener, remoteRepository);
                  }

                } else {
                  listener.getLogger().println("Cloning the remote Git repository");

                  // Go through the repositories, trying to clone from one
                  //
                  boolean successfullyCloned = false;
                  for (RemoteConfig rc : remoteRepositories) {
                    try {
                      git.clone(rc);
                      successfullyCloned = true;
                      break;
                    } catch (GitException ex) {
                      listener.error(
                          "Error cloning remote repo '%s' : %s", rc.getName(), ex.getMessage());
                      if (ex.getCause() != null) {
                        listener.error("Cause: %s", ex.getCause().getMessage());
                      }
                      // Failed. Try the next one
                      listener.getLogger().println("Trying next repository");
                    }
                  }

                  if (!successfullyCloned) {
                    listener.error("Could not clone from a repository");
                    throw new GitException("Could not clone");
                  }

                  // Also do a fetch
                  for (RemoteConfig remoteRepository : getRepositories()) {
                    fetchFrom(git, localWorkspace, listener, remoteRepository);
                  }

                  if (git.hasGitModules()) {
                    git.submoduleInit();
                    git.submoduleUpdate();
                  }
                }

                IBuildChooser buildChooser =
                    new BuildChooser(GitSCM.this, git, new GitUtils(listener, git), buildData);

                Collection<Revision> candidates =
                    buildChooser.getCandidateRevisions(false, singleBranch);
                if (candidates.size() == 0) return null;
                return candidates.iterator().next();
              }
            });

    if (revToBuild == null) {
      // getBuildCandidates should make the last item the last build, so a re-build
      // will build the last built thing.
      listener.error("Nothing to do");
      return false;
    }
    listener.getLogger().println("Commencing build of " + revToBuild);
    Object[] returnData; // Changelog, BuildData

    if (mergeOptions.doMerge()) {
      if (!revToBuild.containsBranchName(mergeOptions.getMergeTarget())) {
        returnData =
            workspace.act(
                new FileCallable<Object[]>() {
                  private static final long serialVersionUID = 1L;

                  public Object[] invoke(File localWorkspace, VirtualChannel channel)
                      throws IOException {
                    EnvVars environment;
                    try {
                      environment = build.getEnvironment(listener);
                    } catch (Exception e) {
                      listener.error("Exception reading environment - using empty environment");
                      environment = new EnvVars();
                    }
                    IGitAPI git =
                        new GitAPI(gitExe, new FilePath(localWorkspace), listener, environment);

                    IBuildChooser buildChooser =
                        new BuildChooser(GitSCM.this, git, new GitUtils(listener, git), buildData);

                    // Do we need to merge this revision onto MergeTarget

                    // Only merge if there's a branch to merge that isn't
                    // us..
                    listener
                        .getLogger()
                        .println(
                            "Merging " + revToBuild + " onto " + mergeOptions.getMergeTarget());

                    // checkout origin/blah
                    ObjectId target = git.revParse(mergeOptions.getMergeTarget());
                    git.checkout(target.name());

                    try {
                      git.merge(revToBuild.getSha1().name());
                    } catch (Exception ex) {
                      listener
                          .getLogger()
                          .println(
                              "Branch not suitable for integration as it does not merge cleanly");

                      // We still need to tag something to prevent
                      // repetitive builds from happening - tag the
                      // candidate
                      // branch.
                      git.checkout(revToBuild.getSha1().name());

                      git.tag(buildnumber, "Hudson Build #" + buildNumber);

                      buildChooser.revisionBuilt(revToBuild, buildNumber, Result.FAILURE);

                      return new Object[] {null, buildChooser.getData()};
                    }

                    if (git.hasGitModules()) {
                      git.submoduleUpdate();
                    }

                    // Tag the successful merge
                    git.tag(buildnumber, "Hudson Build #" + buildNumber);

                    StringBuilder changeLog = new StringBuilder();

                    if (revToBuild.getBranches().size() > 0)
                      listener
                          .getLogger()
                          .println("Warning : There are multiple branch changesets here");

                    try {
                      for (Branch b : revToBuild.getBranches()) {
                        Build lastRevWas =
                            buildData == null ? null : buildData.getLastBuildOfBranch(b.getName());
                        if (lastRevWas != null) {
                          changeLog.append(
                              putChangelogDiffsIntoFile(
                                  git,
                                  b.name,
                                  lastRevWas.getSHA1().name(),
                                  revToBuild.getSha1().name()));
                        }
                      }
                    } catch (GitException ge) {
                      changeLog.append("Unable to retrieve changeset");
                    }

                    Build buildData = buildChooser.revisionBuilt(revToBuild, buildNumber, null);
                    GitUtils gu = new GitUtils(listener, git);
                    buildData.mergeRevision = gu.getRevisionForSHA1(target);

                    // Fetch the diffs into the changelog file
                    return new Object[] {changeLog, buildChooser.getData()};
                  }
                });
        BuildData returningBuildData = (BuildData) returnData[1];
        build.addAction(returningBuildData);
        return changeLogResult((String) returnData[0], changelogFile);
      }
    }

    // No merge

    returnData =
        workspace.act(
            new FileCallable<Object[]>() {
              private static final long serialVersionUID = 1L;

              public Object[] invoke(File localWorkspace, VirtualChannel channel)
                  throws IOException {
                IGitAPI git =
                    new GitAPI(gitExe, new FilePath(localWorkspace), listener, environment);
                IBuildChooser buildChooser =
                    new BuildChooser(GitSCM.this, git, new GitUtils(listener, git), buildData);

                // Straight compile-the-branch
                listener.getLogger().println("Checking out " + revToBuild);
                git.checkout(revToBuild.getSha1().name());

                // if( compileSubmoduleCompares )
                if (doGenerateSubmoduleConfigurations) {
                  SubmoduleCombinator combinator =
                      new SubmoduleCombinator(git, listener, localWorkspace, submoduleCfg);
                  combinator.createSubmoduleCombinations();
                }

                if (git.hasGitModules()) {
                  git.submoduleInit();

                  // Git submodule update will only 'fetch' from where it
                  // regards as 'origin'. However,
                  // it is possible that we are building from a
                  // RemoteRepository with changes
                  // that are not in 'origin' AND it may be a new module that
                  // we've only just discovered.
                  // So - try updating from all RRs, then use the submodule
                  // Update to do the checkout

                  for (RemoteConfig remoteRepository : getRepositories()) {
                    fetchFrom(git, localWorkspace, listener, remoteRepository);
                  }

                  // Update to the correct checkout
                  git.submoduleUpdate();
                }

                // Tag the successful merge
                git.tag(buildnumber, "Hudson Build #" + buildNumber);

                StringBuilder changeLog = new StringBuilder();

                int histories = 0;

                try {
                  for (Branch b : revToBuild.getBranches()) {
                    Build lastRevWas =
                        buildData == null ? null : buildData.getLastBuildOfBranch(b.getName());

                    if (lastRevWas != null) {
                      listener.getLogger().println("Recording changes in branch " + b.getName());
                      changeLog.append(
                          putChangelogDiffsIntoFile(
                              git,
                              b.name,
                              lastRevWas.getSHA1().name(),
                              revToBuild.getSha1().name()));
                      histories++;
                    } else {
                      listener.getLogger().println("No change to record in branch " + b.getName());
                    }
                  }
                } catch (GitException ge) {
                  changeLog.append("Unable to retrieve changeset");
                }

                if (histories > 1)
                  listener
                      .getLogger()
                      .println("Warning : There are multiple branch changesets here");

                buildChooser.revisionBuilt(revToBuild, buildNumber, null);

                if (getClean()) {
                  listener.getLogger().println("Cleaning workspace");
                  git.clean();
                }

                // Fetch the diffs into the changelog file
                return new Object[] {changeLog.toString(), buildChooser.getData()};
              }
            });
    build.addAction((Action) returnData[1]);

    return changeLogResult((String) returnData[0], changelogFile);
  }
Esempio n. 9
0
  @Override
  public boolean pollChanges(
      final AbstractProject project,
      Launcher launcher,
      final FilePath workspace,
      final TaskListener listener)
      throws IOException, InterruptedException {
    // Poll for changes. Are there any unbuilt revisions that Hudson ought to build ?

    final String gitExe = getDescriptor().getGitExe();

    AbstractBuild lastBuild = (AbstractBuild) project.getLastBuild();

    if (lastBuild != null) {
      listener.getLogger().println("[poll] Last Build : #" + lastBuild.getNumber());
    }

    final BuildData buildData = getBuildData(lastBuild, false);

    if (buildData != null && buildData.lastBuild != null) {
      listener.getLogger().println("[poll] Last Built Revision: " + buildData.lastBuild.revision);
    }

    /* TODO: Breaks serialization somehow.
    EnvVars tmp = new EnvVars();
          try {
              tmp = lastBuild.getEnvironment(listener);
          } catch (InterruptedException e) {
              listener.error("Interrupted exception getting environment .. using empty environment");
          }
          final EnvVars environment = tmp;
    */

    final String singleBranch = getSingleBranch(lastBuild);

    // listener.getLogger().println("[poll] Branch: " + singleBranch);

    boolean pollChangesResult =
        workspace.act(
            new FileCallable<Boolean>() {

              private static final long serialVersionUID = 1L;

              public Boolean invoke(File localWorkspace, VirtualChannel channel)
                  throws IOException {

                FilePath ws = new FilePath(localWorkspace);

                IGitAPI git = new GitAPI(gitExe, ws, listener, new EnvVars());

                IBuildChooser buildChooser =
                    new BuildChooser(GitSCM.this, git, new GitUtils(listener, git), buildData);

                if (git.hasGitRepo()) {
                  // Fetch updates
                  for (RemoteConfig remoteRepository : getRepositories()) {
                    fetchFrom(git, localWorkspace, listener, remoteRepository);
                  }
                  Collection<Revision> candidates =
                      buildChooser.getCandidateRevisions(true, singleBranch);
                  return (candidates.size() > 0);
                } else {
                  listener
                      .getLogger()
                      .println("No Git repository yet, an initial checkout is required");
                  return true;
                }
              }
            });

    return pollChangesResult;
  }
  /** {@inheritDoc} */
  @Override
  public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener)
      throws InterruptedException, IOException {
    Result threshold = onlyStable ? Result.SUCCESS : Result.UNSTABLE;
    if (build.getResult().isWorseThan(threshold)) {
      listener
          .getLogger()
          .println(
              "Skipping Cobertura coverage report as build was not "
                  + threshold.toString()
                  + " or better ...");
      return true;
    }

    listener.getLogger().println("[Cobertura] Publishing Cobertura coverage report...");
    final FilePath[] moduleRoots = build.getModuleRoots();
    final boolean multipleModuleRoots = moduleRoots != null && moduleRoots.length > 1;
    final FilePath moduleRoot = multipleModuleRoots ? build.getWorkspace() : build.getModuleRoot();
    final File buildCoberturaDir = build.getRootDir();
    FilePath buildTarget = new FilePath(buildCoberturaDir);

    FilePath[] reports = new FilePath[0];
    try {
      reports = moduleRoot.act(new ParseReportCallable(coberturaReportFile));

      // if the build has failed, then there's not
      // much point in reporting an error
      if (build.getResult().isWorseOrEqualTo(Result.FAILURE) && reports.length == 0) {
        return true;
      }

    } catch (IOException e) {
      Util.displayIOException(e, listener);
      e.printStackTrace(listener.fatalError("Unable to find coverage results"));
      build.setResult(Result.FAILURE);
    }

    if (reports.length == 0) {
      String msg =
          "[Cobertura] No coverage results were found using the pattern '"
              + coberturaReportFile
              + "' relative to '"
              + moduleRoot.getRemote()
              + "'."
              + "  Did you enter a pattern relative to the correct directory?"
              + "  Did you generate the XML report(s) for Cobertura?";
      listener.getLogger().println(msg);
      if (failNoReports) {
        build.setResult(Result.FAILURE);
      } else {
        listener.getLogger().println("[Cobertura] Skipped cobertura reports.");
      }
      return true;
    }

    for (int i = 0; i < reports.length; i++) {
      final FilePath targetPath =
          new FilePath(buildTarget, "coverage" + (i == 0 ? "" : i) + ".xml");
      try {
        reports[i].copyTo(targetPath);
      } catch (IOException e) {
        Util.displayIOException(e, listener);
        e.printStackTrace(
            listener.fatalError(
                "Unable to copy coverage from " + reports[i] + " to " + buildTarget));
        build.setResult(Result.FAILURE);
      }
    }

    listener.getLogger().println("Publishing Cobertura coverage results...");
    Set<String> sourcePaths = new HashSet<String>();
    CoverageResult result = null;
    for (File coberturaXmlReport : getCoberturaReports(build)) {
      try {
        result = CoberturaCoverageParser.parse(coberturaXmlReport, result, sourcePaths);
      } catch (IOException e) {
        Util.displayIOException(e, listener);
        e.printStackTrace(listener.fatalError("Unable to parse " + coberturaXmlReport));
        build.setResult(Result.FAILURE);
      }
    }
    if (result != null) {
      listener.getLogger().println("Cobertura coverage report found.");
      result.setOwner(build);
      final FilePath paintedSourcesPath =
          new FilePath(new File(build.getProject().getRootDir(), "cobertura"));
      paintedSourcesPath.mkdirs();

      if (sourcePaths.contains(".")) {
        sourcePaths.remove(".");
        for (FilePath f : reports) {
          FilePath p = f.getParent();
          if (p != null && p.isDirectory()) {
            sourcePaths.add(p.getRemote());
          }
        }
      }

      SourceCodePainter painter =
          new SourceCodePainter(
              paintedSourcesPath,
              sourcePaths,
              result.getPaintedSources(),
              listener,
              getSourceEncoding());

      moduleRoot.act(painter);

      final CoberturaBuildAction action =
          CoberturaBuildAction.load(
              build,
              result,
              healthyTarget,
              unhealthyTarget,
              getOnlyStable(),
              getFailUnhealthy(),
              getFailUnstable(),
              getAutoUpdateHealth(),
              getAutoUpdateStability());

      build.getActions().add(action);
      Set<CoverageMetric> failingMetrics = failingTarget.getFailingMetrics(result);
      if (!failingMetrics.isEmpty()) {
        listener.getLogger().println("Code coverage enforcement failed for the following metrics:");
        float oldStabilityPercent;
        float setStabilityPercent;
        for (CoverageMetric metric : failingMetrics) {
          oldStabilityPercent = failingTarget.getObservedPercent(result, metric);
          setStabilityPercent = failingTarget.getSetPercent(result, metric);
          listener
              .getLogger()
              .println(
                  "    "
                      + metric.getName()
                      + "'s stability is "
                      + roundDecimalFloat(oldStabilityPercent * 100f)
                      + " and set mininum stability is "
                      + roundDecimalFloat(setStabilityPercent * 100f)
                      + ".");
        }
        if (!getFailUnstable()) {
          listener.getLogger().println("Setting Build to unstable.");
          build.setResult(Result.UNSTABLE);
        } else {
          listener.getLogger().println("Failing build due to unstability.");
          build.setResult(Result.FAILURE);
        }
      }
      if (getFailUnhealthy()) {
        Set<CoverageMetric> unhealthyMetrics = unhealthyTarget.getFailingMetrics(result);
        if (!unhealthyMetrics.isEmpty()) {
          listener.getLogger().println("Unhealthy for the following metrics:");
          float oldHealthyPercent;
          float setHealthyPercent;
          for (CoverageMetric metric : unhealthyMetrics) {
            oldHealthyPercent = unhealthyTarget.getObservedPercent(result, metric);
            setHealthyPercent = unhealthyTarget.getSetPercent(result, metric);
            listener
                .getLogger()
                .println(
                    "    "
                        + metric.getName()
                        + "'s health is "
                        + roundDecimalFloat(oldHealthyPercent * 100f)
                        + " and set minimum health is "
                        + roundDecimalFloat(setHealthyPercent * 100f)
                        + ".");
          }
          listener.getLogger().println("Failing build because it is unhealthy.");
          build.setResult(Result.FAILURE);
        }
      }
      if (build.getResult() == Result.SUCCESS) {
        if (getAutoUpdateHealth()) {
          setNewPercentages(result, true, listener);
        }

        if (getAutoUpdateStability()) {
          setNewPercentages(result, false, listener);
        }
      }
    } else {
      listener
          .getLogger()
          .println(
              "No coverage results were successfully parsed.  Did you generate "
                  + "the XML report(s) for Cobertura?");
      build.setResult(Result.FAILURE);
    }

    return true;
  }
Esempio n. 11
0
  @Override
  public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, final BuildListener listener)
      throws InterruptedException {

    // during matrix build, the push back would happen at the very end only once for the whole
    // matrix,
    // not for individual configuration build.
    if (build instanceof MatrixRun) {
      return true;
    }

    SCM scm = build.getProject().getScm();

    if (!(scm instanceof GitSCM)) {
      return false;
    }

    final GitSCM gitSCM = (GitSCM) scm;

    if (gitSCM.getUseShallowClone()) {
      listener.getLogger().println("GitPublisher disabled while using shallow clone.");
      return true;
    }

    final String projectName = build.getProject().getName();
    final FilePath workspacePath = build.getWorkspace();
    final int buildNumber = build.getNumber();
    final Result buildResult = build.getResult();

    // If pushOnlyIfSuccess is selected and the build is not a success, don't push.
    if (pushOnlyIfSuccess && buildResult.isWorseThan(Result.SUCCESS)) {
      listener
          .getLogger()
          .println(
              "Build did not succeed and the project is configured to only push after a successful build, so no pushing will occur.");
      return true;
    } else {
      final String gitExe = gitSCM.getGitExe(build.getBuiltOn(), listener);
      EnvVars tempEnvironment;
      try {
        tempEnvironment = build.getEnvironment(listener);
      } catch (IOException e) {
        e.printStackTrace(listener.error("Failed to build up environment"));
        tempEnvironment = new EnvVars();
      }

      String confName = gitSCM.getGitConfigNameToUse();
      if ((confName != null) && (!confName.equals(""))) {
        tempEnvironment.put("GIT_COMMITTER_NAME", confName);
        tempEnvironment.put("GIT_AUTHOR_NAME", confName);
      }
      String confEmail = gitSCM.getGitConfigEmailToUse();
      if ((confEmail != null) && (!confEmail.equals(""))) {
        tempEnvironment.put("GIT_COMMITTER_EMAIL", confEmail);
        tempEnvironment.put("GIT_AUTHOR_EMAIL", confEmail);
      }

      final EnvVars environment = tempEnvironment;
      final FilePath workingDirectory = gitSCM.workingDirectory(workspacePath, environment);

      boolean pushResult = true;
      // If we're pushing the merge back...
      if (pushMerge) {
        boolean mergeResult;
        try {
          mergeResult =
              workingDirectory.act(
                  new FileCallable<Boolean>() {
                    private static final long serialVersionUID = 1L;

                    public Boolean invoke(File workspace, VirtualChannel channel)
                        throws IOException {

                      IGitAPI git =
                          new GitAPI(gitExe, new FilePath(workspace), listener, environment);

                      // We delete the old tag generated by the SCM plugin
                      String buildnumber = "jenkins-" + projectName + "-" + buildNumber;
                      git.deleteTag(buildnumber);

                      // And add the success / fail state into the tag.
                      buildnumber += "-" + buildResult.toString();

                      git.tag(buildnumber, "Jenkins Build #" + buildNumber);

                      PreBuildMergeOptions mergeOptions = gitSCM.getMergeOptions();

                      if (mergeOptions.doMerge() && buildResult.isBetterOrEqualTo(Result.SUCCESS)) {
                        RemoteConfig remote = mergeOptions.getMergeRemote();
                        listener
                            .getLogger()
                            .println(
                                "Pushing HEAD to branch "
                                    + mergeOptions.getMergeTarget()
                                    + " of "
                                    + remote.getName()
                                    + " repository");

                        git.push(remote, "HEAD:" + mergeOptions.getMergeTarget());
                      } else {
                        // listener.getLogger().println("Pushing result " + buildnumber + " to
                        // origin repository");
                        // git.push(null);
                      }

                      return true;
                    }
                  });
        } catch (Throwable e) {
          e.printStackTrace(listener.error("Failed to push merge to origin repository"));
          build.setResult(Result.FAILURE);
          mergeResult = false;
        }

        if (!mergeResult) {
          pushResult = false;
        }
      }
      if (isPushTags()) {
        boolean allTagsResult = true;
        for (final TagToPush t : tagsToPush) {
          boolean tagResult = true;
          if (t.getTagName() == null) {
            listener.getLogger().println("No tag to push defined");
            tagResult = false;
          }
          if (t.getTargetRepoName() == null) {
            listener.getLogger().println("No target repo to push to defined");
            tagResult = false;
          }
          if (tagResult) {
            final String tagName = environment.expand(t.getTagName());
            final String targetRepo = environment.expand(t.getTargetRepoName());

            try {
              tagResult =
                  workingDirectory.act(
                      new FileCallable<Boolean>() {
                        private static final long serialVersionUID = 1L;

                        public Boolean invoke(File workspace, VirtualChannel channel)
                            throws IOException {

                          IGitAPI git =
                              new GitAPI(gitExe, new FilePath(workspace), listener, environment);

                          RemoteConfig remote = gitSCM.getRepositoryByName(targetRepo);

                          if (remote == null) {
                            listener
                                .getLogger()
                                .println("No repository found for target repo name " + targetRepo);
                            return false;
                          }

                          if (t.isCreateTag()) {
                            if (git.tagExists(tagName)) {
                              listener
                                  .getLogger()
                                  .println(
                                      "Tag "
                                          + tagName
                                          + " already exists and Create Tag is specified, so failing.");
                              return false;
                            }
                            git.tag(tagName, "Jenkins Git plugin tagging with " + tagName);
                          } else if (!git.tagExists(tagName)) {
                            listener
                                .getLogger()
                                .println(
                                    "Tag "
                                        + tagName
                                        + " does not exist and Create Tag is not specified, so failing.");
                            return false;
                          }

                          listener
                              .getLogger()
                              .println("Pushing tag " + tagName + " to repo " + targetRepo);
                          git.push(remote, tagName);

                          return true;
                        }
                      });
            } catch (Throwable e) {
              e.printStackTrace(
                  listener.error("Failed to push tag " + tagName + " to " + targetRepo));
              build.setResult(Result.FAILURE);
              tagResult = false;
            }
          }

          if (!tagResult) {
            allTagsResult = false;
          }
        }
        if (!allTagsResult) {
          pushResult = false;
        }
      }

      if (isPushBranches()) {
        boolean allBranchesResult = true;
        for (final BranchToPush b : branchesToPush) {
          boolean branchResult = true;
          if (b.getBranchName() == null) {
            listener.getLogger().println("No branch to push defined");
            return false;
          }
          if (b.getTargetRepoName() == null) {
            listener.getLogger().println("No branch repo to push to defined");
            return false;
          }
          final String branchName = environment.expand(b.getBranchName());
          final String targetRepo = environment.expand(b.getTargetRepoName());

          if (branchResult) {
            try {
              branchResult =
                  workingDirectory.act(
                      new FileCallable<Boolean>() {
                        private static final long serialVersionUID = 1L;

                        public Boolean invoke(File workspace, VirtualChannel channel)
                            throws IOException {

                          IGitAPI git =
                              new GitAPI(gitExe, new FilePath(workspace), listener, environment);

                          RemoteConfig remote = gitSCM.getRepositoryByName(targetRepo);

                          if (remote == null) {
                            listener
                                .getLogger()
                                .println("No repository found for target repo name " + targetRepo);
                            return false;
                          }

                          listener
                              .getLogger()
                              .println(
                                  "Pushing HEAD to branch "
                                      + branchName
                                      + " at repo "
                                      + targetRepo);
                          git.push(remote, "HEAD:" + branchName);

                          return true;
                        }
                      });
            } catch (Throwable e) {
              e.printStackTrace(
                  listener.error("Failed to push branch " + branchName + " to " + targetRepo));
              build.setResult(Result.FAILURE);
              branchResult = false;
            }
          }

          if (!branchResult) {
            allBranchesResult = false;
          }
        }
        if (!allBranchesResult) {
          pushResult = false;
        }
      }

      if (isPushNotes()) {
        boolean allNotesResult = true;
        for (final NoteToPush b : notesToPush) {
          boolean noteResult = true;
          if (b.getnoteMsg() == null) {
            listener.getLogger().println("No note to push defined");
            return false;
          }

          b.setEmptyTargetRepoToOrigin();
          final String noteMsg = environment.expand(b.getnoteMsg());
          final String noteNamespace = environment.expand(b.getnoteNamespace());
          final String targetRepo = environment.expand(b.getTargetRepoName());
          final boolean noteReplace = b.getnoteReplace();

          if (noteResult) {
            try {
              noteResult =
                  workingDirectory.act(
                      new FileCallable<Boolean>() {
                        private static final long serialVersionUID = 1L;

                        public Boolean invoke(File workspace, VirtualChannel channel)
                            throws IOException {

                          IGitAPI git =
                              new GitAPI(gitExe, new FilePath(workspace), listener, environment);

                          RemoteConfig remote = gitSCM.getRepositoryByName(targetRepo);

                          if (remote == null) {
                            listener
                                .getLogger()
                                .println("No repository found for target repo name " + targetRepo);
                            return false;
                          }

                          listener
                              .getLogger()
                              .println(
                                  "Adding note \""
                                      + noteMsg
                                      + "\" to namespace \""
                                      + noteNamespace
                                      + "\"");

                          if (noteReplace) git.addNote(noteMsg, noteNamespace);
                          else git.appendNote(noteMsg, noteNamespace);

                          git.push(remote, "refs/notes/*");

                          return true;
                        }
                      });
            } catch (Throwable e) {
              e.printStackTrace(
                  listener.error(
                      "Failed to add note \"" + noteMsg + "\" to \"" + noteNamespace + "\""));
              build.setResult(Result.FAILURE);
              noteResult = false;
            }
          }

          if (!noteResult) {
            allNotesResult = false;
          }
        }
        if (!allNotesResult) {
          pushResult = false;
        }
      }

      return pushResult;
    }
  }
Esempio n. 12
0
  /**
   * Serves a file from the file system (Maps the URL to a directory in a file system.)
   *
   * @param icon The icon file name, like "folder-open.gif"
   * @param serveDirIndex True to generate the directory index. False to serve "index.html"
   * @deprecated as of 1.297 Instead of calling this method explicitly, just return the {@link
   *     DirectoryBrowserSupport} object from the {@code doXYZ} method and let Stapler generate a
   *     response for you.
   */
  public void serveFile(
      StaplerRequest req, StaplerResponse rsp, FilePath root, String icon, boolean serveDirIndex)
      throws IOException, ServletException, InterruptedException {
    // handle form submission
    String pattern = req.getParameter("pattern");
    if (pattern == null) pattern = req.getParameter("path"); // compatibility with Hudson<1.129
    if (pattern != null) {
      rsp.sendRedirect2(pattern);
      return;
    }

    String path = getPath(req);
    if (path.replace('\\', '/').indexOf("/../") != -1) {
      // don't serve anything other than files in the artifacts dir
      rsp.sendError(HttpServletResponse.SC_BAD_REQUEST);
      return;
    }

    // split the path to the base directory portion "abc/def/ghi" which doesn't include any
    // wildcard,
    // and the GLOB portion "**/*.xml" (the rest)
    StringBuilder _base = new StringBuilder();
    StringBuilder _rest = new StringBuilder();
    int restSize = -1; // number of ".." needed to go back to the 'base' level.
    boolean zip = false; // if we are asked to serve a zip file bundle
    boolean plain = false; // if asked to serve a plain text directory listing
    {
      boolean inBase = true;
      StringTokenizer pathTokens = new StringTokenizer(path, "/");
      while (pathTokens.hasMoreTokens()) {
        String pathElement = pathTokens.nextToken();
        // Treat * and ? as wildcard unless they match a literal filename
        if ((pathElement.contains("?") || pathElement.contains("*"))
            && inBase
            && !(new FilePath(root, (_base.length() > 0 ? _base + "/" : "") + pathElement)
                .exists())) inBase = false;
        if (pathElement.equals("*zip*")) {
          // the expected syntax is foo/bar/*zip*/bar.zip
          // the last 'bar.zip' portion is to causes browses to set a good default file name.
          // so the 'rest' portion ends here.
          zip = true;
          break;
        }
        if (pathElement.equals("*plain*")) {
          plain = true;
          break;
        }

        StringBuilder sb = inBase ? _base : _rest;
        if (sb.length() > 0) sb.append('/');
        sb.append(pathElement);
        if (!inBase) restSize++;
      }
    }
    restSize = Math.max(restSize, 0);
    String base = _base.toString();
    String rest = _rest.toString();

    // this is the base file/directory
    FilePath baseFile = new FilePath(root, base);

    if (baseFile.isDirectory()) {
      if (zip) {
        rsp.setContentType("application/zip");
        baseFile.zip(rsp.getOutputStream(), rest);
        return;
      }
      if (plain) {
        rsp.setContentType("text/plain;charset=UTF-8");
        OutputStream os = rsp.getOutputStream();
        try {
          for (String kid : baseFile.act(new SimpleChildList())) {
            os.write(kid.getBytes("UTF-8"));
            os.write('\n');
          }
          os.flush();
        } finally {
          os.close();
        }
        return;
      }

      if (rest.length() == 0) {
        // if the target page to be displayed is a directory and the path doesn't end with '/',
        // redirect
        StringBuffer reqUrl = req.getRequestURL();
        if (reqUrl.charAt(reqUrl.length() - 1) != '/') {
          rsp.sendRedirect2(reqUrl.append('/').toString());
          return;
        }
      }

      FileCallable<List<List<Path>>> glob = null;

      if (rest.length() > 0) {
        // the rest is Ant glob pattern
        glob = new PatternScanner(rest, createBackRef(restSize));
      } else if (serveDirIndex) {
        // serve directory index
        glob = new ChildPathBuilder();
      }

      if (glob != null) {
        // serve glob
        req.setAttribute("it", this);
        List<Path> parentPaths = buildParentPath(base, restSize);
        req.setAttribute("parentPath", parentPaths);
        req.setAttribute("backPath", createBackRef(restSize));
        req.setAttribute("topPath", createBackRef(parentPaths.size() + restSize));
        req.setAttribute("files", baseFile.act(glob));
        req.setAttribute("icon", icon);
        req.setAttribute("path", path);
        req.setAttribute("pattern", rest);
        req.setAttribute("dir", baseFile);
        req.getView(this, "dir.jelly").forward(req, rsp);
        return;
      }

      // convert a directory service request to a single file service request by serving
      // 'index.html'
      baseFile = baseFile.child(indexFileName);
    }

    // serve a single file
    if (!baseFile.exists()) {
      rsp.sendError(HttpServletResponse.SC_NOT_FOUND);
      return;
    }

    boolean view = rest.equals("*view*");

    if (rest.equals("*fingerprint*")) {
      rsp.forward(Hudson.getInstance().getFingerprint(baseFile.digest()), "/", req);
      return;
    }

    ContentInfo ci = baseFile.act(new ContentInfo());

    if (LOGGER.isLoggable(Level.FINE))
      LOGGER.fine(
          "Serving "
              + baseFile
              + " with lastModified="
              + ci.lastModified
              + ", contentLength="
              + ci.contentLength);

    InputStream in = baseFile.read();
    if (view) {
      // for binary files, provide the file name for download
      rsp.setHeader("Content-Disposition", "inline; filename=" + baseFile.getName());

      // pseudo file name to let the Stapler set text/plain
      rsp.serveFile(req, in, ci.lastModified, -1, ci.contentLength, "plain.txt");
    } else {
      rsp.serveFile(req, in, ci.lastModified, -1, ci.contentLength, baseFile.getName());
    }
  }
Esempio n. 13
0
  @Override
  public boolean perform(final AbstractBuild build, Launcher launcher, final BuildListener listener)
      throws IOException, InterruptedException {

    FilePath ws = build.getWorkspace();

    return ws.act(
        new FileCallable<Boolean>() {
          // if 'file' is on a different node, this FileCallable will
          // be transfered to that node and executed there.

          public Boolean invoke(File workspace, VirtualChannel channel) {
            // f and file represents the same thing
            File git_home_directory = getGitHome(workspace);
            if (git_home_directory == null) {
              listener
                  .getLogger()
                  .println(
                      "Failed to find GIT_HOME in "
                          + workspace.getAbsolutePath()
                          + File.separatorChar
                          + GerritNotifier.this.git_home);

              build.setResult(Result.ABORTED);
              return false;
            }
            Repository repo = getRepository(git_home_directory);
            if (repo == null) {
              listener
                  .getLogger()
                  .println(
                      "Failed to read repository from " + git_home_directory.getAbsolutePath());
              build.setResult(Result.ABORTED);
              return false;
            }
            ObjectId head = getHead(repo);
            if (head == null) {
              listener
                  .getLogger()
                  .println(
                      "HEAD is null for "
                          + repo.getDirectory().getAbsolutePath()
                          + ", are you sure that you're using git?");
              build.setResult(Result.ABORTED);
              return null;
            }

            try {
              Result r = build.getResult();
              EnvVars vars = null;
              try {
                vars = build.getEnvironment(listener);
              } catch (InterruptedException e) {
                listener.getLogger().println(e.getMessage());
                e.printStackTrace();
              }
              String buildUrl = "No build url.";
              if (vars.containsKey("BUILD_URL")) {
                buildUrl = vars.get("BUILD_URL");
              }
              if (r.isBetterOrEqualTo(Result.SUCCESS)) {
                listener.getLogger().println("Approving " + head.name());
                verifyGerrit(approve_value, buildUrl, head.name());
              } else if (r.isBetterOrEqualTo(Result.UNSTABLE)) {
                listener.getLogger().println("Rejecting unstable " + head.name());
                verifyGerrit(reject_value, "Build is unstable " + buildUrl, head.name());
              } else {
                listener.getLogger().println("Rejecting failed " + head.name());
                verifyGerrit(reject_value, "Build failed " + buildUrl, head.name());
              }

            } catch (IOException e) {
              listener.getLogger().println(e.getMessage());
              e.printStackTrace(listener.getLogger());
              build.setResult(Result.ABORTED);
              return false;
            }

            return true;
          }
        });
  }
Esempio n. 14
0
  private void checkVersions() throws InterruptedException, IOException {
    updated = false;
    solutionDir.act(
        new FileCallable<Void>() {
          public Void invoke(File file, VirtualChannel vc)
              throws IOException, InterruptedException {
            try {
              final String root = file.getAbsolutePath();
              DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
              final DocumentBuilder builder = dbFactory.newDocumentBuilder();

              Files.walkFileTree(
                  Paths.get(file.getPath()),
                  new SimpleFileVisitor<Path>() {
                    @Override
                    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
                        throws IOException {
                      if (file.getFileName().toString().equalsIgnoreCase("packages.config")) {
                        log.info(
                            String.format(
                                "Checking packages file: %s", file.toAbsolutePath().toString()));
                        try {
                          Document doc = builder.parse(file.toFile());

                          doc.getDocumentElement().normalize();
                          NodeList elems = doc.getElementsByTagName("package");
                          for (int idx = 0; idx < elems.getLength(); idx++) {
                            Element p = (Element) elems.item(idx);
                            String id = p.getAttribute("id");
                            String version = p.getAttribute("version");
                            String latest = getPackageVersion(root, id);

                            if (latest == null || !version.equals(latest)) {
                              log.info(
                                  String.format(
                                      "Package %s v%s should update to v%s.", id, version, latest));
                              updated = true;
                              return FileVisitResult.TERMINATE;
                            }
                          }
                        } catch (SAXException ex) {
                          log.error(ex.toString());
                        }
                      }
                      return FileVisitResult.CONTINUE;
                    }

                    @Override
                    public FileVisitResult visitFileFailed(Path file, IOException exc)
                        throws IOException {
                      log.error(exc.toString());
                      return FileVisitResult.CONTINUE;
                    }
                  });
            } catch (ParserConfigurationException ex) {
              log.error(ex.toString());
            }
            return null;
          }
        });
  }
Esempio n. 15
0
  @Override
  public boolean pollChanges(
      final AbstractProject project,
      Launcher launcher,
      final FilePath workspace,
      final TaskListener listener)
      throws IOException, InterruptedException {
    // Poll for changes. Are there any unbuilt revisions that Hudson ought to build ?

    final String gitExe = getDescriptor().getGitExe();
    listener.getLogger().println("Using strategy: " + choosingStrategy);

    AbstractBuild lastBuild = (AbstractBuild) project.getLastBuild();

    if (lastBuild != null) {
      listener.getLogger().println("[poll] Last Build : #" + lastBuild.getNumber());
    }

    final BuildData buildData = getBuildData(lastBuild, false);

    if (buildData != null && buildData.lastBuild != null) {
      listener.getLogger().println("[poll] Last Built Revision: " + buildData.lastBuild.revision);
    }

    final String singleBranch = getSingleBranch(lastBuild);

    boolean pollChangesResult =
        workspace.act(
            new FileCallable<Boolean>() {
              private static final long serialVersionUID = 1L;

              public Boolean invoke(File localWorkspace, VirtualChannel channel)
                  throws IOException {
                EnvVars environment = new EnvVars(System.getenv());

                IGitAPI git =
                    new GitAPI(gitExe, new FilePath(localWorkspace), listener, environment);

                IBuildChooser buildChooser = createBuildChooser(git, listener, buildData);

                if (git.hasGitRepo()) {
                  // Repo is there - do a fetch
                  listener.getLogger().println("Fetching changes from the remote Git repositories");

                  // Fetch updates
                  for (RemoteConfig remoteRepository : getRepositories()) {
                    fetchFrom(git, localWorkspace, listener, remoteRepository);
                  }

                  listener.getLogger().println("Polling for changes in");

                  Collection<Revision> candidates =
                      buildChooser.getCandidateRevisions(true, singleBranch);

                  return (candidates.size() > 0);
                } else {
                  listener
                      .getLogger()
                      .println("No Git repository yet, an initial checkout is required");
                  return true;
                }
              }
            });

    return pollChangesResult;
  }
 private String getUrlForPath(FilePath path) throws IOException, InterruptedException {
   return path.act(new GetUrlForPath(createAuthenticationProvider()));
 }
  @Override
  public boolean perform(
      final AbstractBuild build, final Launcher launcher, final BuildListener listener)
      throws IOException, InterruptedException {

    listener.getLogger().println("Docker Build");

    FilePath fpChild = new FilePath(build.getWorkspace(), dockerFileDirectory);

    final String tagToUse = getTag(build, launcher, listener);
    final String url = getUrl(build);
    // Marshal the builder across the wire.
    DockerClient client = getDockerClient(build);
    final DockerClient.Builder builder = DockerClient.builder().fromClient(client);

    BuildCommandResponse response =
        fpChild.act(
            new FilePath.FileCallable<BuildCommandResponse>() {
              public BuildCommandResponse invoke(File f, VirtualChannel channel)
                  throws IOException, InterruptedException {
                try {
                  listener
                      .getLogger()
                      .println(
                          "Docker Build : build with tag "
                              + tagToUse
                              + " at path "
                              + f.getAbsolutePath());
                  DockerClient client = builder.readTimeout(3600000).build();

                  File dockerFile;

                  // Be lenient and allow the user to just specify the path.
                  if (f.isFile()) dockerFile = f;
                  else dockerFile = new File(f, "Dockerfile");

                  return client.createBuildCommand().dockerFile(dockerFile).tag(tagToUse).execute();

                } catch (DockerException e) {
                  throw Throwables.propagate(e);
                }
              }
            });

    listener.getLogger().println("Docker Build Response : " + response);

    Optional<String> id = response.imageId();
    if (!id.isPresent()) return false;

    build.addAction(
        new DockerBuildImageAction(
            url, id.get(), tagToUse, cleanupWithJenkinsJobDelete, pushOnSuccess));
    build.save();

    if (pushOnSuccess) {

      listener.getLogger().println("Pushing " + tagToUse);
      if (!tagToUse.toLowerCase().equals(tagToUse)) {
        listener
            .getLogger()
            .println(
                "ERROR: Docker will refuse to push tag name "
                    + tagToUse
                    + " because it uses upper case.");
      }

      Identifier identifier = Identifier.fromCompoundString(tagToUse);

      String repositoryName = identifier.repository.name;

      PushCommandResponse pushResponse = client.createPushCommand().name(repositoryName).execute();

      listener.getLogger().println("Docker Push Response : " + pushResponse);
    }

    if (cleanImages) {

      // For some reason, docker delete doesn't delete all tagged
      // versions, despite force = true.
      // So, do it multiple times (protect against infinite looping).
      listener.getLogger().println("Cleaning local images");

      int delete = 100;
      while (delete != 0) {
        int count = client.image(id.get()).removeCommand().force(true).execute().size();
        if (count == 0) delete = 0;
        else delete--;
      }
    }

    listener.getLogger().println("Docker Build Done");

    return true;
  }