Exemple #1
0
  /**
   * Get the history after a specified revision.
   *
   * <p>The default implementation first fetches the full history and then throws away the oldest
   * revisions. This is not efficient, so subclasses should override it in order to get good
   * performance. Once every subclass has implemented a more efficient method, the default
   * implementation should be removed and made abstract.
   *
   * @param file the file to get the history for
   * @param sinceRevision the revision right before the first one to return, or {@code null} to
   *     return the full history
   * @return partial history for file
   * @throws HistoryException on error accessing the history
   */
  History getHistory(File file, String sinceRevision) throws HistoryException {

    // If we want an incremental history update and get here, warn that
    // it may be slow.
    if (sinceRevision != null) {
      Logger logger = OpenGrokLogger.getLogger();
      logger.log(
          Level.WARNING,
          "Incremental history retrieval is not implemented for {0}.",
          getClass().getSimpleName());
      logger.log(Level.WARNING, "Falling back to slower full history retrieval.");
    }

    History history = getHistory(file);

    if (sinceRevision == null) {
      return history;
    }

    List<HistoryEntry> partial = new ArrayList<>();
    for (HistoryEntry entry : history.getHistoryEntries()) {
      partial.add(entry);
      if (sinceRevision.equals(entry.getRevision())) {
        // Found revision right before the first one to return.
        break;
      }
    }

    removeAndVerifyOldestChangeset(partial, sinceRevision);
    history.setHistoryEntries(partial);
    return history;
  }
  /** Helper for {@link #get(File, Repository)}. */
  private History getHistory(File file, Repository repository, boolean withFiles)
      throws HistoryException, SQLException {
    final String filePath = getSourceRootRelativePath(file);
    final String reposPath = toUnixPath(repository.getDirectoryName());
    final ArrayList<HistoryEntry> entries = new ArrayList<HistoryEntry>();
    final ConnectionResource conn = connectionManager.getConnectionResource();
    try {
      final PreparedStatement ps;
      if (file.isDirectory()) {
        // Fetch history for all files under this directory.
        ps = conn.getStatement(GET_DIR_HISTORY);
        ps.setString(2, filePath);
      } else {
        // Fetch history for a single file only.
        ps = conn.getStatement(GET_FILE_HISTORY);
        ps.setString(2, getParentPath(filePath));
        ps.setString(3, getBaseName(filePath));
      }
      ps.setString(1, reposPath);

      final PreparedStatement filePS = withFiles ? conn.getStatement(GET_CS_FILES) : null;

      try (ResultSet rs = ps.executeQuery()) {
        while (rs.next()) {
          // Get the information about a changeset
          String revision = rs.getString(1);
          String author = rs.getString(2);
          Timestamp time = rs.getTimestamp(3);
          String message = rs.getString(4);
          HistoryEntry entry = new HistoryEntry(revision, time, author, null, message, true);
          entries.add(entry);

          // Fill the list of files touched by the changeset, if
          // requested.
          if (withFiles) {
            int changeset = rs.getInt(5);
            filePS.setInt(1, changeset);
            try (ResultSet fileRS = filePS.executeQuery()) {
              while (fileRS.next()) {
                entry.addFile(fileRS.getString(1));
              }
            }
          }
        }
      }
    } finally {
      connectionManager.releaseConnection(conn);
    }

    History history = new History();
    history.setHistoryEntries(entries);

    RuntimeEnvironment env = RuntimeEnvironment.getInstance();
    if (env.isTagsEnabled() && repository.hasFileBasedTags()) {
      repository.assignTagsInHistory(history);
    }

    return history;
  }