protected void makeCombination(Map<IndexEntry, Revision> settings) {
    // Assume we are checked out
    String name = "combine-" + tid + "-" + (idx++);
    git.branch(name);
    git.checkout(name);

    String commit = "Hudson generated combination of:\n";

    for (IndexEntry submodule : settings.keySet()) {
      Revision branch = settings.get(submodule);
      commit += "  " + submodule.getFile() + " " + branch.toString() + "\n";
    }

    listener.getLogger().print(commit);

    for (IndexEntry submodule : settings.keySet()) {
      Revision branch = settings.get(submodule);
      File subdir = new File(workspace, submodule.getFile());
      IGitAPI subGit =
          new GitAPI(git.getGitExe(), new FilePath(subdir), listener, git.getEnvironment());

      subGit.checkout(branch.sha1.name());
      git.add(submodule.file);
    }

    git.commit(commit);
  }
Пример #2
0
  /** Used to add a revision form complete information created elsewhere */
  public void addRevision(int revnumber, String date, String authorinitials, String revremark) {
    Revision r = new Revision();
    r.revnumber = revnumber;
    r.date = date;
    r.authorinitials = authorinitials;
    r.revremark = revremark;

    list.add(r);
  }
 /**
  * Get the content (aka 'body') data.
  *
  * @throws CouchbaseLiteException
  */
 @InterfaceAudience.Public
 public InputStream getContent() throws CouchbaseLiteException {
   if (body != null) {
     return body;
   } else {
     Database db = revision.getDatabase();
     Attachment attachment = db.getAttachmentForSequence(revision.getSequence(), this.name);
     body = attachment.getContent();
     return body;
   }
 }
  private Revision incrementRevision(String clientId) {
    final Revision current = getLastModification().getRevision();

    final long incrementedVersion;
    if (current.getVersion() == null) {
      incrementedVersion = 0;
    } else {
      incrementedVersion = current.getVersion() + 1;
    }
    return new Revision(incrementedVersion, clientId);
  }
  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();
    }
  }
Пример #6
0
  public int difference(Map<IndexEntry, Revision> item, List<IndexEntry> entries) {
    int difference = 0;
    if (entries.size() != item.keySet().size()) return -1;

    for (IndexEntry entry : entries) {
      Revision b = null;
      for (IndexEntry e : item.keySet()) {
        if (e.getFile().equals(entry.getFile())) b = item.get(e);
      }

      if (b == null) return -1;

      if (!entry.object.equals(b.getSha1())) difference++;
    }
    return difference;
  }
Пример #7
0
 /**
  * Scrolls the content so that the given revision is visible.
  *
  * @param revision the revision to scroll the client area to.
  */
 private void scrollToRevision(Revision revision) {
   Rectangle revBounds = revision.getBounds();
   Rectangle clientArea = getClientArea();
   clientArea.x = getOrigin().x;
   clientArea.y = getOrigin().y;
   if (!clientArea.contains(revBounds.x, revBounds.y)
       && !clientArea.contains(revBounds.x + revBounds.width, revBounds.y + revBounds.height)) {
     setOrigin(revBounds.x, revBounds.y);
   }
 }
Пример #8
0
  protected void makeCombination(Map<IndexEntry, Revision> settings) {
    // Assume we are checked out
    String name = "combine-" + tid + "-" + (idx++);
    git.branch(name);
    git.checkout(name);

    String commit = "Hudson generated combination of:\n";

    for (IndexEntry submodule : settings.keySet()) {
      Revision branch = settings.get(submodule);
      commit += "  " + submodule.getFile() + " " + branch.toString() + "\n";
    }

    listener.getLogger().print(commit);

    for (IndexEntry submodule : settings.keySet()) {
      Revision branch = settings.get(submodule);
      File subdir = new File(workspace, submodule.getFile());
      IGitAPI subGit =
          new GitAPI(git.getGitExe(), new FilePath(subdir), listener, git.getEnvironment());

      subGit.checkout(branch.sha1.name());
      git.add(submodule.file);
    }

    try {
      File f = File.createTempFile("gitcommit", ".txt");
      FileOutputStream fos = null;
      try {
        fos = new FileOutputStream(f);
        fos.write(commit.getBytes());
      } finally {
        fos.close();
      }
      git.commit(f);
      f.delete();
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
Пример #9
0
 private boolean normalize(GitilesView.Builder view, HttpServletResponse res) throws IOException {
   if (view.getOldRevision() != Revision.NULL) {
     return false;
   }
   Revision r = view.getRevision();
   Revision nr = Revision.normalizeParentExpressions(r);
   if (r != nr) {
     res.sendRedirect(view.setRevision(nr).toUrl());
     return true;
   }
   return false;
 }
  @Override
  public <T> ConfigurationSnapshot<T> configureFlow(
      Revision revision, ConfigurationRequest<T> configurationRequest) {
    lock();
    try {
      // check the revision
      checkRevision(revision);

      // execute the configuration request
      final ConfigurationResult<T> result = configurationRequest.execute();

      // update the revision
      final Revision newRevision = updateRevision(incrementRevision(revision.getClientId()));

      // build the result
      return new ConfigurationSnapshot(
          newRevision.getVersion(), result.getConfiguration(), result.isNew());
    } finally {
      unlock();
    }
  }
Пример #11
0
  public static List<Vehicule> getAvailableVehiculesByAgence(
      Date startDate, Date endDate, Agence agence) {
    List<Vehicule> listVehiculesByAgence = Vehicule.getVehiculesByAgence(agence);
    List<Vehicule> listAvailableVehicules = new ArrayList<Vehicule>();
    List<Session> listSessionsByAgence = Session.getSessionsByAgence(agence);
    List<Revision> listRevisionsByVehicule;
    Calendar calendar = new GregorianCalendar();
    Date startRevision;
    Date endRevision;

    for (Vehicule vehicule : listVehiculesByAgence) {
      boolean isAvailable = true;
      listRevisionsByVehicule = Revision.getRevisionsByVehicule(vehicule);
      for (Revision revision : listRevisionsByVehicule) {
        startRevision = revision.date;
        calendar.setTime(revision.date);
        calendar.add(Calendar.DATE, 7);
        endRevision = calendar.getTime();

        if (startDate.equals(startRevision)
            || endDate.equals(startRevision)
            || startDate.equals(endRevision)
            || endDate.equals(endRevision)
            || (startDate.after(startRevision) && startDate.before(endRevision))
            || (endDate.after(startRevision) && endDate.before(endRevision))) {

          isAvailable = false;
        }
      }

      if (isAvailable) {
        for (Session session : listSessionsByAgence) {
          if (startDate.equals(session.dateDepart)
              || endDate.equals(session.dateDepart)
              || startDate.equals(session.dateFin)
              || endDate.equals(session.dateFin)
              || (startDate.after(session.dateDepart) && startDate.before(session.dateFin))
              || (endDate.after(session.dateDepart) && endDate.before(session.dateFin))) {
            if (session.vehicule.id == vehicule.id) {
              isAvailable = false;
            }
          }
        }
      }

      if (isAvailable) {
        listAvailableVehicules.add(vehicule);
      }
    }

    return listAvailableVehicules;
  }
Пример #12
0
 /**
  * Implementation of callback from layout algorithm. This method is called once for each revision
  * or branch marker to be added to the view.
  *
  * @see net.sf.versiontree.layout.drawer.IDrawMethod#draw(net.sf.versiontree.data.ITreeElement,
  *     int, int)
  */
 public void draw(ITreeElement element, int x, int y) {
   if (element instanceof IRevision) {
     Revision revision = new Revision(connectors, 0);
     revision.setRevisionData((IRevision) element);
     revision.addMouseListener(this);
     revision.setMenu(this.getMenu());
     revision.setLocation(BORDER + x * (width + hspacing), BORDER + y * (height + vspacing));
     revision.setSize(revision.computeSize(SWT.DEFAULT, SWT.DEFAULT));
     // check if this is the current revision
     if ((revision.getRevisionData().getState() & ITreeElement.STATE_CURRENT) != 0) {
       currentRevision = revision;
       selectionManager.revisionSelected(currentRevision.getRevisionData(), 1);
       logSelectionListener.logEntrySelected(currentRevision.getRevisionData().getLogEntry());
     }
   } else {
     Branch branch = new Branch(connectors, 0);
     branch.setBranchData(((IBranch) element));
     branch.addMouseListener(this);
     branch.setLocation(BORDER + x * (width + hspacing), BORDER + y * (height + vspacing));
     branch.setSize(branch.computeSize(SWT.DEFAULT, SWT.DEFAULT));
   }
 }
Пример #13
0
  /**
   * Set up submodule URLs so that they correspond to the remote pertaining to the revision that has
   * been checked out.
   */
  public void setupSubmoduleUrls(Revision rev, TaskListener listener) throws GitException {
    String remote = null;

    // try to locate the remote repository from where this commit came from
    // (by using the heuristics that the branch name, if available, contains the remote name)
    // if we can figure out the remote, the other setupSubmoduleUrls method
    // look at its URL, and if it's a non-bare repository, we attempt to retrieve modules
    // from this checked out copy.
    //
    // the idea is that you have something like tree-structured repositories: at the root you have
    // corporate central repositories that you
    // ultimately push to, which all .gitmodules point to, then you have intermediate team local
    // repository,
    // which is assumed to be a non-bare repository (say, a checked out copy on a shared server
    // accessed via SSH)
    //
    // the abovementioned behaviour of the Git plugin makes it pick up submodules from this team
    // local repository,
    // not the corporate central.
    //
    // (Kohsuke: I have a bit of hesitation/doubt about such a behaviour change triggered by
    // seemingly indirect
    // evidence of whether the upstream is bare or not (not to mention the fact that you can't
    // reliably
    // figure out if the repository is bare or not just from the URL), but that's what apparently
    // has been implemented
    // and we care about the backward compatibility.)
    //
    // note that "figuring out which remote repository the commit came from" isn't a well-defined
    // question, and this is really a heuristics. The user might be telling us to build a specific
    // SHA1.
    // or maybe someone pushed directly to the workspace and so it may not correspond to any remote
    // branch.
    // so if we fail to figure this out, we back out and avoid being too clever. See JENKINS-10060
    // as an example
    // of where our trying to be too clever here is breaking stuff for people.
    for (Branch br : rev.getBranches()) {
      String b = br.getName();
      if (b != null) {
        int slash = b.indexOf('/');

        if (slash != -1) remote = getDefaultRemote(b.substring(0, slash));
      }

      if (remote != null) break;
    }

    if (remote == null) remote = getDefaultRemote();

    if (remote != null) setupSubmoduleUrls(remote, listener);
  }
Пример #14
0
 /**
  * Listener for all components on the view. Checks for left clicks on Revisions, changes the
  * selection and notifies the LogEntrySelectionListener.
  */
 public void mouseDown(MouseEvent e) {
   if (e.getSource() instanceof Revision) {
     Revision selected = (Revision) e.getSource();
     // exit if user wants to open contex menu on
     // a already selected revision
     if (e.button == 3 && selected.isSelected()) {
       return;
     }
     selectionManager.revisionSelected(selected.getRevisionData(), e.stateMask);
     redrawAll();
     // notify listener
     if (selected.isSelected()) {
       logSelectionListener.logEntrySelected(selected.getRevisionData().getLogEntry());
     }
   } else if (e.getSource() instanceof Branch) {
     Branch selected = (Branch) e.getSource();
     List<IRevision> revisions = selected.getBranchData().getRevisions();
     if (revisions.size() > 0) {
       selectionManager.branchSelected(revisions, e.stateMask);
       redrawAll();
     }
   }
 }
Пример #15
0
    /**
     * Compares this revision with the specified object for order. Returns a negative integer, zero,
     * or a positive integer as this object is less than, equal to, or greater than the specified
     * object.
     *
     * <p>
     *
     * @param rev revision to be compared for order with this revision.
     * @return a negative integer, zero, or a positive integer as this object is less than, equal
     *     to, or greater than the specified object.
     */
    @Override
    public int compareTo(Revision rev) {
      checkNotNull(rev);

      return ComparisonChain.start()
          .compare(this.time, rev.time)
          .compare(this.filename, rev.filename)
          .compare(this.user, rev.user)
          .compare(this.logmsg, rev.logmsg)
          .compare(this.transaction, rev.transaction)
          .compare(this.relName, rev.relName)
          .compare(this.hashCode(), rev.hashCode())
          .result();
    }
Пример #16
0
  /**
   * Given a Revision, show it as if it were an entry from git whatchanged, so that it can be parsed
   * by GitChangeLogParser.
   *
   * @param r The Revision object
   * @return The git show output, in List form.
   * @throws GitException if errors were encountered running git show.
   */
  public List<String> showRevision(Revision r) throws GitException {
    String revName = r.getSha1String();
    String result = "";

    if (revName != null) {
      result = launchCommand("show", "--no-abbrev", "--format=raw", "-M", "--raw", revName);
    }

    List<String> revShow = new ArrayList<String>();

    if (result != null) {
      revShow = new ArrayList<String>(Arrays.asList(result.split("\\n")));
    }

    return revShow;
  }
 /** Get the owning document. */
 @InterfaceAudience.Public
 public Document getDocument() {
   return revision.getDocument();
 }
Пример #18
0
  /**
   * Recovers the change transactions for the co-change graph from the revision information, i.e.,
   * it assigns the transaction ids for the revisions.
   *
   * @param revisionList is a list of revisions.
   * @return Sorted map that maps timestamps to collections of transactions, where transactions are
   *     sets of revisions.
   */
  private SortedMap<Long, Collection<SortedSet<Revision>>> recoverTransactions(
      List<Revision> revisionList) {

    // Step 1: Transform the list of revisions to a sorted data structure.

    // A map user -> msg-entry.
    Map<String, Map<String, SortedMap<Long, SortedSet<String>>>> userMap =
        new HashMap<String, Map<String, SortedMap<Long, SortedSet<String>>>>();

    // A map logmsg -> time-entry.
    Map<String, SortedMap<Long, SortedSet<String>>> msgMap;

    // A map time -> file.
    SortedMap<Long, SortedSet<String>> timeMap;

    // A set of files.
    SortedSet<String> fileSet;

    for (Revision revision : revisionList) {
      // A map logmsg -> time-entry.
      msgMap = userMap.get(revision.user);
      if (msgMap == null) {
        msgMap = new HashMap<String, SortedMap<Long, SortedSet<String>>>();
        userMap.put(revision.user, msgMap);
      }

      // A map time -> file.
      timeMap = msgMap.get(revision.logmsg);
      if (timeMap == null) {
        timeMap = new TreeMap<Long, SortedSet<String>>();
        msgMap.put(revision.logmsg, timeMap);
      }

      // A set of files.
      fileSet = timeMap.get(revision.time);
      if (fileSet == null) {
        fileSet = new TreeSet<String>();
        timeMap.put(revision.time, fileSet);
      }

      // Add file to set.
      fileSet.add(revision.filename);
    }

    // Step 2: Create the result, which is
    // a map timestamp -> set of transactions (Long -> SortedSet),
    // where one transaction is a set of revisions.
    SortedMap<Long, Collection<SortedSet<Revision>>> result =
        new TreeMap<Long, Collection<SortedSet<Revision>>>();

    int transaction = 0;
    Set<String> userSet = userMap.keySet();
    for (String user : userSet) {
      msgMap = userMap.get(user);

      Set<String> msgSet = msgMap.keySet();
      for (String logmsg : msgSet) {
        timeMap = msgMap.get(logmsg);

        Set<Long> timeSet = timeMap.keySet();

        long firstTime = 0;
        Set<String> tmpFilesSeen = new TreeSet<String>(); // Detect a time window that is too long.
        Collection<SortedSet<Revision>> transColl; // Collection of transactions.
        SortedSet<Revision> revSet = null; // Transaction, i.e., set of revisions.
        for (Long time : timeSet) {
          if (time.longValue() - firstTime > timeWindow) {
            // Start new transaction.
            transaction++;
            firstTime = time.longValue();
            tmpFilesSeen.clear();

            // Retrieve (or create new) set of transactions for the timestamp.
            transColl = result.get(time);
            if (transColl == null) {
              transColl = new ArrayList<SortedSet<Revision>>();
              result.put(time, transColl);
            }

            // New transaction (set of revisions).
            revSet = new TreeSet<Revision>();
            transColl.add(revSet);

          } else if (sliding) {
            // The time window 'slides' with the files.
            firstTime = time.longValue();
          }

          fileSet = timeMap.get(time);
          for (String filename : fileSet) {
            // Detect a time window that is too long.
            if (verbosity.isAtLeast(Verbosity.WARNING) && tmpFilesSeen.contains(filename)) {
              System.err.println(
                  "Transaction-recovery warning: " + "Time window might be to wide ");
              System.err.println("(currently '" + timeWindow + "' milli-seconds). ");
              System.err.println(
                  "File '" + filename + "' already contained in current transaction.");
            }
            tmpFilesSeen.add(filename);

            // Create revision and add revision to resulting list.
            Revision revision = new Revision();
            revision.relName = "CO-CHANGE";
            revision.filename = filename;
            revision.time = time;
            revision.user = user;
            revision.logmsg = logmsg;
            revision.transaction = transaction;
            revSet.add(revision);
          }
        }
      }
    }
    return result;
  }
Пример #19
0
  public void createSubmoduleCombinations() throws GitException, IOException {
    Map<IndexEntry, Collection<Revision>> moduleBranches =
        new HashMap<IndexEntry, Collection<Revision>>();

    for (IndexEntry submodule : git.getSubmodules("HEAD")) {
      File subdir = new File(workspace, submodule.getFile());
      IGitAPI subGit =
          new GitAPI(git.getGitExe(), new FilePath(subdir), listener, git.getEnvironment());

      GitUtils gu = new GitUtils(listener, subGit);
      Collection<Revision> items = gu.filterTipBranches(gu.getAllBranchRevisions());

      filterRevisions(submodule.getFile(), items);

      moduleBranches.put(submodule, items);
    }

    // Remove any uninteresting branches

    for (IndexEntry entry : moduleBranches.keySet()) {
      listener.getLogger().print("Submodule " + entry.getFile() + " branches");
      for (Revision br : moduleBranches.get(entry)) {
        listener.getLogger().print(" " + br.toString());
      }
      listener.getLogger().print("\n");
    }

    // Make all the possible combinations
    List<Map<IndexEntry, Revision>> combinations = createCombinations(moduleBranches);

    listener
        .getLogger()
        .println("There are " + combinations.size() + " submodule/revision combinations possible");

    // Create a map which is SHA1 -> Submodule IDs that were present
    Map<ObjectId, List<IndexEntry>> entriesMap = new HashMap<ObjectId, List<IndexEntry>>();
    // Knock out already-defined configurations
    for (ObjectId sha1 : git.revListAll()) {
      // What's the submodule configuration
      List<IndexEntry> entries = git.getSubmodules(sha1.name());
      entriesMap.put(sha1, entries);
    }

    for (List<IndexEntry> entries : entriesMap.values()) {
      for (Iterator<Map<IndexEntry, Revision>> it = combinations.iterator(); it.hasNext(); ) {
        Map<IndexEntry, Revision> item = it.next();
        if (matches(item, entries)) {
          it.remove();
          break;
        }
      }
    }

    listener
        .getLogger()
        .println("There are " + combinations.size() + " configurations that could be generated.");

    ObjectId headSha1 = git.revParse("HEAD");

    // Make up the combinations

    for (Map<IndexEntry, Revision> combination : combinations) {
      // By default, use the head sha1
      ObjectId sha1 = headSha1;
      int min = Integer.MAX_VALUE;

      // But let's see if we can find the most appropriate place to create the branch
      for (ObjectId sha : entriesMap.keySet()) {
        List<IndexEntry> entries = entriesMap.get(sha);
        int value = difference(combination, entries);
        if (value > 0 && value < min) {
          min = value;
          sha1 = sha;
        }

        if (min == 1) {
          break; // look no further
        }
      }

      git.checkout(sha1.name());
      makeCombination(combination);
    }
  }
Пример #20
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);
  }
Пример #21
0
  /**
   * Determines which Revisions to build.
   *
   * <p>If only one branch is chosen and only one repository is listed, then just attempt to find
   * the latest revision number for the chosen branch.
   *
   * <p>If multiple branches are selected or the branches include wildcards, then use the advanced
   * usecase as defined in the getAdvancedCandidateRevisons method.
   *
   * @throws IOException
   * @throws GitException
   */
  @Override
  public Collection<Revision> getCandidateRevisions(
      boolean isPollCall,
      String singleBranch,
      GitClient git,
      TaskListener listener,
      BuildData data,
      BuildChooserContext context)
      throws GitException, IOException, InterruptedException {

    verbose(
        listener,
        "getCandidateRevisions({0},{1},,,{2}) considering branches to build",
        isPollCall,
        singleBranch,
        data);

    // if the branch name contains more wildcards then the simple usecase
    // does not apply and we need to skip to the advanced usecase
    if (singleBranch == null || singleBranch.contains("*"))
      return getAdvancedCandidateRevisions(
          isPollCall, listener, new GitUtils(listener, git), data, context);

    // check if we're trying to build a specific commit
    // this only makes sense for a build, there is no
    // reason to poll for a commit
    if (!isPollCall && singleBranch.matches("[0-9a-f]{6,40}")) {
      try {
        ObjectId sha1 = git.revParse(singleBranch);
        Revision revision = new Revision(sha1);
        revision.getBranches().add(new Branch("detached", sha1));
        verbose(listener, "Will build the detached SHA1 {0}", sha1);
        return Collections.singletonList(revision);
      } catch (GitException e) {
        // revision does not exist, may still be a branch
        // for example a branch called "badface" would show up here
        verbose(listener, "Not a valid SHA1 {0}", singleBranch);
      }
    }

    Collection<Revision> revisions = new ArrayList<Revision>();

    // if it doesn't contain '/' then it could be either a tag or an unqualified branch
    if (!singleBranch.contains("/")) {
      // the 'branch' could actually be a tag:
      Set<String> tags = git.getTagNames(singleBranch);
      if (tags.size() != 0) {
        verbose(listener, "{0} is a tag");
        return getHeadRevision(isPollCall, singleBranch, git, listener, data);
      }

      // <tt>BRANCH</tt> is recognized as a shorthand of <tt>*/BRANCH</tt>
      // so check all remotes to fully qualify this branch spec
      for (RemoteConfig config : gitSCM.getRepositories()) {
        String repository = config.getName();
        String fqbn = repository + "/" + singleBranch;
        verbose(
            listener,
            "Qualifying {0} as a branch in repository {1} -> {2}",
            singleBranch,
            repository,
            fqbn);
        revisions.addAll(getHeadRevision(isPollCall, fqbn, git, listener, data));
      }
    } else {
      // either the branch is qualified (first part should match a valid remote)
      // or it is still unqualified, but the branch name contains a '/'
      List<String> possibleQualifiedBranches = new ArrayList<String>();
      boolean singleBranchIsQualified = false;
      for (RemoteConfig config : gitSCM.getRepositories()) {
        String repository = config.getName();
        if (singleBranch.startsWith(repository + "/")) {
          singleBranchIsQualified = true;
          break;
        }
        String fqbn = repository + "/" + singleBranch;
        verbose(
            listener,
            "Qualifying {0} as a branch in repository {1} -> {2}",
            singleBranch,
            repository,
            fqbn);
        possibleQualifiedBranches.add(fqbn);
      }
      if (singleBranchIsQualified) {
        revisions.addAll(getHeadRevision(isPollCall, singleBranch, git, listener, data));
      } else {
        for (String fqbn : possibleQualifiedBranches) {
          revisions.addAll(getHeadRevision(isPollCall, fqbn, git, listener, data));
        }
      }
    }

    return revisions;
  }
Пример #22
0
  public Revision addRevision(Revision revision) {
    getRevisions().add(revision);
    revision.setPeriodo(this);

    return revision;
  }
Пример #23
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;
          }
        });
  }
Пример #24
0
 private Revision objectId2Revision(String singleBranch, ObjectId sha1) {
   Revision revision = new Revision(sha1);
   revision.getBranches().add(new Branch(singleBranch, sha1));
   return revision;
 }
Пример #25
0
  public Revision removeRevision(Revision revision) {
    getRevisions().remove(revision);
    revision.setPeriodo(null);

    return revision;
  }
Пример #26
0
  /**
   * Compute the difference between original and revised sequences.
   *
   * @param orig The original sequence.
   * @param rev The revised sequence to be compared with the original.
   * @return A Revision object describing the differences.
   * @throws DifferenciationFailedException if the diff could not be computed.
   */
  public Revision diff(Object[] orig, Object[] rev) throws DifferentiationFailedException {
    // create map eqs, such that for each item in both orig and rev
    // eqs(item) = firstOccurrence(item, orig);
    Map eqs = buildEqSet(orig, rev);

    // create an array such that
    //   indx[i] = NOT_FOUND_i if orig[i] is not in rev
    //   indx[i] = firstOccurrence(orig[i], orig)
    int[] indx = buildIndex(eqs, orig, NOT_FOUND_i);

    // create an array such that
    //   jndx[j] = NOT_FOUND_j if orig[j] is not in rev
    //   jndx[j] = firstOccurrence(rev[j], orig)
    int[] jndx = buildIndex(eqs, rev, NOT_FOUND_j);

    // what in effect has been done is to build a unique hash
    // for each item that is in both orig and rev
    // and to label each item in orig and new with that hash value
    // or a marker that the item is not common to both.

    eqs = null; // let gc know we're done with this

    Revision deltas = new Revision(); // !!! new Revision()
    int i = 0;
    int j = 0;

    // skip matching
    // skip leading items that are equal
    // could be written
    // for (i=0; indx[i] != EOS && indx[i] == jndx[i]; i++);
    // j = i;
    for (; indx[i] != EOS && indx[i] == jndx[j]; i++, j++) {
      /* void */
    }

    while (indx[i] != jndx[j]) { // only equal if both == EOS
      // they are different
      int ia = i;
      int ja = j;

      // size of this delta
      do {
        // look down rev for a match
        // stop at a match
        // or if the FO(rev[j]) > FO(orig[i])
        // or at the end
        while (jndx[j] < 0 || jndx[j] < indx[i]) {
          j++;
        }
        // look down orig for a match
        // stop at a match
        // or if the FO(orig[i]) > FO(rev[j])
        // or at the end
        while (indx[i] < 0 || indx[i] < jndx[j]) {
          i++;
        }

        // this doesn't do a compare each line with each other line
        // so it won't find all matching lines
      } while (indx[i] != jndx[j]);

      // on exit we have a match

      // they are equal, reverse any exedent matches
      // it is possible to overshoot, so count back matching items
      while (i > ia && j > ja && indx[i - 1] == jndx[j - 1]) {
        --i;
        --j;
      }

      deltas.addDelta(Delta.newDelta(new Chunk(orig, ia, i - ia), new Chunk(rev, ja, j - ja)));
      // skip matching
      for (; indx[i] != EOS && indx[i] == jndx[j]; i++, j++) {
        /* void */
      }
    }
    return deltas;
  }
Пример #27
0
  /**
   * Parses the CVS log data and extracts revisions.
   *
   * @return List of revisions.
   */
  private List<Revision> readRevisionList() {
    List<Revision> result = new ArrayList<Revision>();

    String line = "";
    // String relName = "CO-CHANGE";
    String filename = null;
    Long time;
    String user;
    String logmsg;

    int lineno = 1;
    try {
      while ((line = reader.readLine()) != null) {
        // New working file.
        if (line.startsWith("Working file: ")) {
          // Set name of the current working file,
          //   for which we pasre the revisions.
          filename = line.substring(14);
        }

        // New revision.
        if (line.startsWith("date: ")) {
          // Set date, author, and logmsg of the current revision.

          // Parse date. Start right after "date: ".
          time = parseDate(line.substring(6, line.indexOf("author: ")));
          if (time == null) {
            System.err.print("Error while reading the CVS date info for file: ");
            System.err.println(filename + ".");
          }

          // Parse author. Start right after "author: ".
          int posBegin = line.indexOf("author: ") + 8;
          int posEnd = line.indexOf(';', posBegin);
          user = line.substring(posBegin, posEnd);

          // Parse logmsg. Start on next line the date/author line.
          logmsg = "";
          ++lineno;
          while (((line = reader.readLine()) != null)
              && !line.startsWith("----")
              && !line.startsWith("====")) {
            if (!line.startsWith("branches: ")) {
              logmsg += line + ReaderDataGraph.endl;
            }
            ++lineno;
          }

          // Create revision and add revision to resulting list.
          Revision revision = new Revision();
          // revision.relName = relName.replace(' ', '_');  // Replace blanks by underline.
          revision.filename = filename.replace(' ', '_'); // Replace blanks by underline.
          revision.time = time;
          revision.user = user;
          revision.logmsg = logmsg;
          result.add(revision);

          // System.out.print("Relation: "+ relName +
          //                 " File: " + filename +
          //                 " Time: " + time.toString() +
          //                 " User: "******" LogMsg: " + logmsg);

        }
        ++lineno;
      } // while
    } catch (Exception e) {
      System.err.println("Exception while reading the CVS log at line " + lineno + ":");
      System.err.println(e);
      System.err.print("Read line: ");
      System.err.println(line);
    }
    return result;
  }