Ejemplo n.º 1
0
  private Collection<Revision> getHeadRevision(
      boolean isPollCall, String singleBranch, GitClient git, TaskListener listener, BuildData data)
      throws InterruptedException {
    try {
      ObjectId sha1 = git.revParse(singleBranch);
      verbose(listener, "rev-parse {0} -> {1}", singleBranch, sha1);

      // if polling for changes don't select something that has
      // already been built as a build candidate
      if (isPollCall && data.hasBeenBuilt(sha1)) {
        verbose(listener, "{0} has already been built", sha1);
        return emptyList();
      }

      verbose(listener, "Found a new commit {0} to be built on {1}", sha1, singleBranch);
      Revision revision = new Revision(sha1);
      revision.getBranches().add(new Branch(singleBranch, sha1));
      return Collections.singletonList(revision);
      /*
      // calculate the revisions that are new compared to the last build
      List<Revision> candidateRevs = new ArrayList<Revision>();
      List<ObjectId> allRevs = git.revListAll(); // index 0 contains the newest revision
      if (data != null && allRevs != null) {
          Revision lastBuiltRev = data.getLastBuiltRevision();
          if (lastBuiltRev == null) {
              return Collections.singletonList(objectId2Revision(singleBranch, sha1));
          }
          int indexOfLastBuildRev = allRevs.indexOf(lastBuiltRev.getSha1());
          if (indexOfLastBuildRev == -1) {
              // mhmmm ... can happen when branches are switched.
              return Collections.singletonList(objectId2Revision(singleBranch, sha1));
          }
          List<ObjectId> newRevisionsSinceLastBuild = allRevs.subList(0, indexOfLastBuildRev);
          // translate list of ObjectIds into list of Revisions
          for (ObjectId objectId : newRevisionsSinceLastBuild) {
              candidateRevs.add(objectId2Revision(singleBranch, objectId));
          }
      }
      if (candidateRevs.isEmpty()) {
          return Collections.singletonList(objectId2Revision(singleBranch, sha1));
      }
      return candidateRevs;
      */
    } catch (GitException e) {
      // branch does not exist, there is nothing to build
      verbose(listener, "Failed to rev-parse: {0}", singleBranch);
      return emptyList();
    }
  }
  private List<String> getFilteredTestCandidates(Integer maxAgeInDays, String ancestorCommitSha1)
      throws Exception {
    GitSCM gitSCM = new GitSCM("foo");
    AncestryBuildChooser chooser = new AncestryBuildChooser(maxAgeInDays, ancestorCommitSha1);
    gitSCM.getExtensions().add(new BuildChooserSetting(chooser));
    assertEquals(maxAgeInDays, chooser.getMaximumAgeInDays());
    assertEquals(ancestorCommitSha1, chooser.getAncestorCommitSha1());

    // mock necessary objects
    GitClient git = Mockito.spy(this.testGitClient);
    Mockito.when(git.getRemoteBranches()).thenReturn(this.testGitClient.getBranches());

    BuildData buildData = Mockito.mock(BuildData.class);
    Mockito.when(buildData.hasBeenBuilt(git.revParse(rootCommit))).thenReturn(false);

    BuildChooserContext context = Mockito.mock(BuildChooserContext.class);
    Mockito.when(context.getEnvironment()).thenReturn(new EnvVars());

    TaskListener listener = TaskListener.NULL;

    // get filtered candidates
    Collection<Revision> candidateRevisions =
        gitSCM
            .getBuildChooser()
            .getCandidateRevisions(true, "**-days-old-branch", git, listener, buildData, context);

    // transform revision candidates to sha1 strings
    List<String> candidateSha1s =
        Lists.newArrayList(
            Iterables.transform(
                candidateRevisions,
                new Function<Revision, String>() {
                  public String apply(Revision rev) {
                    return rev.getSha1String();
                  }
                }));

    return candidateSha1s;
  }
Ejemplo n.º 3
0
  /**
   * In order to determine which Revisions to build.
   *
   * <p>Does the following : 1. Find all the branch revisions 2. Filter out branches that we don't
   * care about from the revisions. Any Revisions with no interesting branches are dropped. 3. Get
   * rid of any revisions that are wholly subsumed by another revision we're considering. 4. Get rid
   * of any revisions that we've already built. 5. Sort revisions from old to new.
   *
   * <p>NB: Alternate BuildChooser implementations are possible - this may be beneficial if "only 1"
   * branch is to be built, as much of this work is irrelevant in that usecase.
   *
   * @throws IOException
   * @throws GitException
   */
  private List<Revision> getAdvancedCandidateRevisions(
      boolean isPollCall,
      TaskListener listener,
      GitUtils utils,
      BuildData data,
      BuildChooserContext context)
      throws GitException, IOException, InterruptedException {
    EnvVars env = context.getBuild().getEnvironment();

    // 1. Get all the (branch) revisions that exist
    List<Revision> revs = new ArrayList<Revision>(utils.getAllBranchRevisions());
    verbose(listener, "Starting with all the branches: {0}", revs);

    // 2. Filter out any revisions that don't contain any branches that we
    // actually care about (spec)
    for (Iterator<Revision> i = revs.iterator(); i.hasNext(); ) {
      Revision r = i.next();

      // filter out uninteresting branches
      for (Iterator<Branch> j = r.getBranches().iterator(); j.hasNext(); ) {
        Branch b = j.next();
        boolean keep = false;
        for (BranchSpec bspec : gitSCM.getBranches()) {
          if (bspec.matches(b.getName(), env)) {
            keep = true;
            break;
          }
        }

        if (!keep) {
          verbose(listener, "Ignoring {0} because it doesn''t match branch specifier", b);
          j.remove();
        }
      }

      // filter out HEAD ref if it's not the only ref
      if (r.getBranches().size() > 1) {
        for (Iterator<Branch> j = r.getBranches().iterator(); j.hasNext(); ) {
          Branch b = j.next();
          if (HEAD.matches(b.getName(), env)) {
            verbose(
                listener,
                "Ignoring {0} because there''s named branch for this revision",
                b.getName());
            j.remove();
          }
        }
      }

      if (r.getBranches().size() == 0) {
        verbose(
            listener,
            "Ignoring {0} because we don''t care about any of the branches that point to it",
            r);
        i.remove();
      }
    }

    verbose(listener, "After branch filtering: {0}", revs);

    // 3. We only want 'tip' revisions
    revs = utils.filterTipBranches(revs);
    verbose(listener, "After non-tip filtering: {0}", revs);

    // 4. Finally, remove any revisions that have already been built.
    verbose(listener, "Removing what''s already been built: {0}", data.getBuildsByBranchName());
    Revision lastBuiltRevision = data.getLastBuiltRevision();
    for (Iterator<Revision> i = revs.iterator(); i.hasNext(); ) {
      Revision r = i.next();

      if (data.hasBeenBuilt(r.getSha1())) {
        i.remove();

        // keep track of new branches pointing to the last built revision
        if (lastBuiltRevision != null && lastBuiltRevision.getSha1().equals(r.getSha1())) {
          lastBuiltRevision = r;
        }
      }
    }
    verbose(listener, "After filtering out what''s already been built: {0}", revs);

    // if we're trying to run a build (not an SCM poll) and nothing new
    // was found then just run the last build again but ensure that the branch list
    // is ordered according to the configuration. Sorting the branch list ensures
    // a deterministic value for GIT_BRANCH and allows a git-flow style workflow
    // with fast-forward merges between branches
    if (!isPollCall && revs.isEmpty() && lastBuiltRevision != null) {
      verbose(
          listener,
          "Nothing seems worth building, so falling back to the previously built revision: {0}",
          data.getLastBuiltRevision());
      return Collections.singletonList(
          utils.sortBranchesForRevision(lastBuiltRevision, gitSCM.getBranches(), env));
    }

    // 5. sort them by the date of commit, old to new
    // this ensures the fairness in scheduling.
    final List<Revision> in = revs;
    return utils.git.withRepository(
        new RepositoryCallback<List<Revision>>() {
          public List<Revision> invoke(Repository repo, VirtualChannel channel)
              throws IOException, InterruptedException {
            Collections.sort(in, new CommitTimeComparator(repo));
            return in;
          }
        });
  }