* @throws HistoryException
*/
@Override
public void store(History history, Repository repository)
throws HistoryException {
final RuntimeEnvironment env = RuntimeEnvironment.getInstance();
String latestRev = null;
// Return immediately when there is nothing to do.
List<HistoryEntry> entries = history.getHistoryEntries();
if (entries.isEmpty()) {
return;
}
OpenGrokLogger.getLogger().log(Level.FINE,
"Storing history for repo {0}",
new Object[] {repository.getDirectoryName()});
HashMap<String, List<HistoryEntry>> map =
new HashMap<String, List<HistoryEntry>>();
/*
* Go through all history entries for this repository (acquired through
* history/log command executed for top-level directory of the repo
* and parsed into HistoryEntry structures) and create hash map which
* maps file names into list of HistoryEntry structures corresponding
* to changesets in which the file was modified.
*/
for (HistoryEntry e : history.getHistoryEntries()) {
// The history entries are sorted from newest to oldest.
if (latestRev == null) {
latestRev = e.getRevision();
}
for (String s : e.getFiles()) {
/*
* We do not want to generate history cache for files which
* do not currently exist in the repository.
*/
File test = new File(env.getSourceRootPath() + s);
if (!test.exists()) {
continue;
}
List<HistoryEntry> list = map.get(s);
if (list == null) {
list = new ArrayList<HistoryEntry>();
map.put(s, list);
}
/*
* We need to do deep copy in order to have different tags
* per each commit.
*/
if (env.isTagsEnabled() && repository.hasFileBasedTags()) {
list.add(new HistoryEntry(e));
} else {
list.add(e);
}
}
}
/*
* Now traverse the list of files from the hash map built above
* and for each file store its history (saved in the value of the
* hash map entry for the file) in a file. Skip renamed files
* which will be handled separately below.
*/
final File root = RuntimeEnvironment.getInstance().getSourceRootFile();
for (Map.Entry<String, List<HistoryEntry>> map_entry : map.entrySet()) {
try {
if (RuntimeEnvironment.isRenamedFilesEnabled() &&
isRenamedFile(map_entry, env, repository, history)) {
continue;
}
} catch (IOException ex) {
OpenGrokLogger.getLogger().log(Level.WARNING,
"isRenamedFile() got exception: " + ex);
}
doFileHistory(map_entry, env, repository, null, root, false);
}
if (!RuntimeEnvironment.isRenamedFilesEnabled()) {
finishStore(repository, latestRev);
return;
}
/*
* Now handle renamed files (in parallel).
*/
HashMap<String, List<HistoryEntry>> renamed_map =
new HashMap<String, List<HistoryEntry>>();
for (final Map.Entry<String, List<HistoryEntry>> map_entry : map.entrySet()) {
try {
if (isRenamedFile(map_entry, env, repository, history)) {
renamed_map.put(map_entry.getKey(), map_entry.getValue());
}
} catch (IOException ex) {
OpenGrokLogger.getLogger().log(Level.WARNING,
"isRenamedFile() got exception: " + ex);
}
}
// The directories for the renamed files have to be created before
// the actual files otherwise storeFile() might be racing for
// mkdirs() if there are multiple renamed files from single directory
// handled in parallel.
for (final String file : renamed_map.keySet()) {
File cache = getCachedFile(new File(env.getSourceRootPath() + file));
File dir = cache.getParentFile();
if (!dir.isDirectory() && !dir.mkdirs()) {
OpenGrokLogger.getLogger().log(Level.WARNING,
"Unable to create cache directory '" + dir + "'.");
}
}
final Repository repositoryF = repository;
final CountDownLatch latch = new CountDownLatch(renamed_map.size());
for (final Map.Entry<String, List<HistoryEntry>> map_entry : renamed_map.entrySet()) {
RuntimeEnvironment.getHistoryRenamedExecutor().submit(new Runnable() {
@Override
public void run() {
try {
doFileHistory(map_entry, env, repositoryF,
new File(env.getSourceRootPath() + map_entry.getKey()),
root, true);
} catch (Exception ex) {
// We want to catch any exception since we are in thread.
OpenGrokLogger.getLogger().log(Level.WARNING,
"doFileHistory() got exception: " + ex);