/* * Copyright 2000-2020 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package jetbrains.buildServer.symbols; import jetbrains.buildServer.ExecResult; import jetbrains.buildServer.agent.BuildProgressLogger; import jetbrains.buildServer.symbols.tools.JetSymbolsExe; import jetbrains.buildServer.symbols.tools.PdbType; import jetbrains.buildServer.util.FileUtil; import org.apache.log4j.Logger; import org.jetbrains.annotations.NotNull; import java.io.File; import java.io.IOException; import java.util.Collection; /** * @author Evgeniy.Koshkin */ public class PdbFilePatcher { private static final Logger LOG = Logger.getLogger(PdbFilePatcher.class); private final File myWorkingDir; private final JetSymbolsExe myJetSymbolsExe; private final BuildProgressLogger myProgressLogger; private final PdbFilePatcherAdapterFactory myPatcheAdapterFactory; public PdbFilePatcher(@NotNull final File workingDir, @NotNull final JetSymbolsExe jetSymbolsExe, @NotNull final PdbFilePatcherAdapterFactory patcheAdapterFactory, @NotNull final BuildProgressLogger progressLogger) { myWorkingDir = workingDir; myPatcheAdapterFactory = patcheAdapterFactory; myJetSymbolsExe = jetSymbolsExe; myProgressLogger = progressLogger; } /** * Executes patching process. * * @param symbolsFile is a source PDB file. * @param buildLogger is a build logger. * @return true if file was patched, otherwise false. * @throws Exception is error has happen during patching process. */ public boolean patch(File symbolsFile) throws Exception { final PdbType pdbType = myJetSymbolsExe.getPdbType(symbolsFile, myProgressLogger); final PdbFilePatcherAdapter patherAdapter = myPatcheAdapterFactory.create(pdbType); final Collection<File> sourceFiles = patherAdapter.getReferencedSourceFiles(symbolsFile); final String symbolsFileCanonicalPath = symbolsFile.getCanonicalPath(); if (sourceFiles.isEmpty()) { final String message = "No source information found in pdb file " + symbolsFileCanonicalPath; myProgressLogger.warning(message); LOG.warn(message); return false; } final File tmpFile = FileUtil.createTempFile(myWorkingDir, "pdb-", ".patch", false); try { int processedFilesCount = patherAdapter.serializeSourceLinks(tmpFile, sourceFiles); if (processedFilesCount == 0) { myProgressLogger.message(String.format("No local source files were found for pdb file %s. Looks like it was not produced during the current build.", symbolsFileCanonicalPath)); return false; } else { myProgressLogger.message(String.format("Information about %d source files will be updated.", processedFilesCount)); } final ExecResult result = patherAdapter.updatePdbSourceLinks(symbolsFile, tmpFile); if (result.getExitCode() != 0) { throw new IOException(String.format("Failed to update symbols file %s: %s", symbolsFile, result.getStderr())); } } finally { FileUtil.delete(tmpFile); } return true; } }