private void addResourceProcessingSteps( Path sourcePath, Path destinationPath, ImmutableList.Builder<Step> stepsBuilder) { String sourcePathExtension = Files.getFileExtension(sourcePath.toString()).toLowerCase(Locale.US); switch (sourcePathExtension) { case "plist": case "stringsdict": LOG.debug("Converting plist %s to binary plist %s", sourcePath, destinationPath); stepsBuilder.add( new PlistProcessStep( sourcePath, destinationPath, ImmutableMap.<String, NSObject>of(), ImmutableMap.<String, NSObject>of(), PlistProcessStep.OutputFormat.BINARY)); break; case "xib": String compiledNibFilename = Files.getNameWithoutExtension(destinationPath.toString()) + ".nib"; Path compiledNibPath = destinationPath.getParent().resolve(compiledNibFilename); LOG.debug("Compiling XIB %s to NIB %s", sourcePath, destinationPath); stepsBuilder.add( new IbtoolStep(ibtool.getCommandPrefix(getResolver()), sourcePath, compiledNibPath)); break; default: stepsBuilder.add(CopyStep.forFile(sourcePath, destinationPath)); break; } }
@SafeVarargs @VisibleForTesting static BuckConfig createFromReaders( Map<Path, Reader> readers, ProjectFilesystem projectFilesystem, Platform platform, ImmutableMap<String, String> environment, ImmutableMap<String, ImmutableMap<String, String>>... configOverrides) throws IOException { ImmutableList.Builder<ImmutableMap<String, ImmutableMap<String, String>>> builder = ImmutableList.builder(); for (Map.Entry<Path, Reader> entry : readers.entrySet()) { Path filePath = entry.getKey(); Reader reader = entry.getValue(); ImmutableMap<String, ImmutableMap<String, String>> parsedConfiguration = Inis.read(reader); LOG.debug("Loaded a configuration file %s: %s", filePath, parsedConfiguration); builder.add(parsedConfiguration); } for (ImmutableMap<String, ImmutableMap<String, String>> configOverride : configOverrides) { LOG.debug("Adding configuration overrides: %s", configOverride); builder.add(configOverride); } Config config = new Config(builder.build()); return new BuckConfig(config, projectFilesystem, platform, environment); }
private static boolean inputFilesUnderSymlink( // We use Collection<Path> instead of Iterable<Path> to prevent // accidentally passing in Path, since Path itself is Iterable<Path>. Collection<Path> inputs, ProjectFilesystem projectFilesystem, Map<Path, Path> symlinkExistenceCache, Map<Path, Path> newSymlinksEncountered) throws IOException { boolean result = false; for (Path input : inputs) { for (int i = 1; i < input.getNameCount(); i++) { Path subpath = input.subpath(0, i); Path resolvedSymlink = symlinkExistenceCache.get(subpath); if (resolvedSymlink != null) { LOG.debug("Detected cached symlink %s -> %s", subpath, resolvedSymlink); newSymlinksEncountered.put(subpath, resolvedSymlink); result = true; } else if (projectFilesystem.isSymLink(subpath)) { Path symlinkTarget = projectFilesystem.resolve(subpath).toRealPath(); Path relativeSymlinkTarget = projectFilesystem.getPathRelativeToProjectRoot(symlinkTarget).or(symlinkTarget); LOG.debug("Detected symbolic link %s -> %s", subpath, relativeSymlinkTarget); newSymlinksEncountered.put(subpath, relativeSymlinkTarget); symlinkExistenceCache.put(subpath, relativeSymlinkTarget); result = true; } } } return result; }
int invalidatePath(Path path) { try (AutoCloseableLock writeLock = rawAndComputedNodesLock.writeLock()) { int invalidatedRawNodes = 0; ImmutableSet<Map<String, Object>> rawNodes = allRawNodes.getIfPresent(path); if (rawNodes != null) { // Increment the counter invalidatedRawNodes = rawNodes.size(); for (Map<String, Object> rawNode : rawNodes) { UnflavoredBuildTarget target = RawNodeParsePipeline.parseBuildTargetFromRawRule(cell.getRoot(), rawNode, path); LOG.debug("Invalidating target for path %s: %s", path, target); for (CacheImpl<?> cache : typedNodeCaches.values()) { cache.allComputedNodes.invalidateAll(targetsCornucopia.get(target)); } targetsCornucopia.removeAll(target); } allRawNodes.invalidate(path); } // We may have been given a file that other build files depend on. Iteratively remove those. Iterable<Path> dependents = buildFileDependents.get(path); LOG.debug("Invalidating dependents for path %s: %s", path, dependents); for (Path dependent : dependents) { if (dependent.equals(path)) { continue; } invalidatedRawNodes += invalidatePath(dependent); } buildFileDependents.removeAll(path); buildFileConfigs.remove(path); return invalidatedRawNodes; } }
private void registerInputsUnderSymlinks(Path buildFile, TargetNode<?> node) throws IOException { Map<Path, Path> newSymlinksEncountered = Maps.newHashMap(); if (inputFilesUnderSymlink( node.getInputs(), node.getRuleFactoryParams().getProjectFilesystem(), symlinkExistenceCache, newSymlinksEncountered)) { ParserConfig.AllowSymlinks allowSymlinks = Preconditions.checkNotNull( cellSymlinkAllowability.get(node.getBuildTarget().getCellPath())); if (allowSymlinks == ParserConfig.AllowSymlinks.FORBID) { throw new HumanReadableException( "Target %s contains input files under a path which contains a symbolic link " + "(%s). To resolve this, use separate rules and declare dependencies instead of " + "using symbolic links.", node.getBuildTarget(), newSymlinksEncountered); } LOG.warn( "Disabling caching for target %s, because one or more input files are under a " + "symbolic link (%s). This will severely impact performance! To resolve this, use " + "separate rules and declare dependencies instead of using symbolic links.", node.getBuildTarget(), newSymlinksEncountered); buildInputPathsUnderSymlink.add(buildFile); } }
@Override public void close() throws InterruptedException, BuildFileParseException { stdout.close(); stderr.close(); BuildFileParseException lastSeen = null; try { closer.close(); } catch (IOException e) { if (e.getCause() instanceof BuildFileParseException) { lastSeen = (BuildFileParseException) e.getCause(); } if (e.getCause() instanceof InterruptedException) { throw (InterruptedException) e.getCause(); } Throwables.propagate(e); } LOG.debug( "Cleaning cache of build files with inputs under symlink %s", buildInputPathsUnderSymlink); Set<Path> buildInputPathsUnderSymlinkCopy = new HashSet<>(buildInputPathsUnderSymlink); buildInputPathsUnderSymlink.clear(); for (Path buildFilePath : buildInputPathsUnderSymlinkCopy) { permState.invalidatePath(buildFilePath); } if (lastSeen != null) { throw lastSeen; } }
/** * @param successMessage single line of text without a trailing newline. If stdErr is attached to * a terminal, then this will append an ANSI reset escape sequence followed by a newline. */ public void printSuccess(String successMessage) { Preconditions.checkArgument( !successMessage.endsWith("\n"), "Trailing newline will be added by this method"); LOG.debug("Build success: %s", successMessage); ansi.printHighlightedSuccessText(stdErr, successMessage); stdErr.print('\n'); }
public CxxInferCapture createInferCaptureBuildRule( BuildTarget target, String name, CxxSource source, CxxInferTools inferTools) { Preconditions.checkArgument(CxxSourceTypes.isPreprocessableType(source.getType())); LOG.verbose("Creating preprocessed InferCapture build rule %s for %s", target, source); CxxInferCapture result = new CxxInferCapture( getParams() .copyWithChanges( target, new DepsBuilder().addPreprocessDeps().add(source), Suppliers.ofInstance(ImmutableSortedSet.<BuildRule>of())), getPathResolver(), CxxToolFlags.copyOf( CxxSourceTypes.getPlatformPreprocessFlags(getCxxPlatform(), source.getType()), preprocessorFlags.getUnchecked(source.getType())), computeCompilerFlags(source.getType(), source.getFlags()), source.getPath(), source.getType(), getCompileOutputPath(target, name), getIncludeRoots(), getSystemIncludeRoots(), getHeaderMaps(), getFrameworks(), CxxDescriptionEnhancer.frameworkPathToSearchPath(getCxxPlatform(), getPathResolver()), getPrefixHeader(), inferTools, getCxxPlatform().getDebugPathSanitizer()); getResolver().addToIndex(result); return result; }
public static ImmutableSet<ProvisioningProfileMetadata> findProfilesInPath(Path searchPath) throws InterruptedException { final ImmutableSet.Builder<ProvisioningProfileMetadata> profilesBuilder = ImmutableSet.builder(); try { Files.walkFileTree( searchPath.toAbsolutePath(), new SimpleFileVisitor<Path>() { @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { if (file.toString().endsWith(".mobileprovision")) { try { ProvisioningProfileMetadata profile = ProvisioningProfileMetadata.fromProvisioningProfilePath(file); profilesBuilder.add(profile); } catch (IOException | IllegalArgumentException e) { LOG.error(e, "Ignoring invalid or malformed .mobileprovision file"); } catch (InterruptedException e) { throw new IOException(e); } } return FileVisitResult.CONTINUE; } }); } catch (IOException e) { if (e.getCause() instanceof InterruptedException) { throw ((InterruptedException) e.getCause()); } LOG.error(e, "Error while searching for mobileprovision files"); } return profilesBuilder.build(); }
/** * A step that invokes Apple's tool to scan the binary and copy any needed Swift standard libraries. */ public class SwiftStdlibStep implements Step { private static final Logger LOG = Logger.get(SwiftStdlibStep.class); private final Path workingDirectory; private final Iterable<String> command; private final Optional<Supplier<CodeSignIdentity>> codeSignIdentitySupplier; public SwiftStdlibStep( Path workingDirectory, Iterable<String> command, Optional<Supplier<CodeSignIdentity>> codeSignIdentitySupplier) { this.workingDirectory = workingDirectory; this.command = command; this.codeSignIdentitySupplier = codeSignIdentitySupplier; } @Override public String getShortName() { return "copy swift standard libs"; } private ProcessExecutorParams makeProcessExecutorParams() { ProcessExecutorParams.Builder builder = ProcessExecutorParams.builder(); builder.setDirectory(workingDirectory.toAbsolutePath().toFile()); builder.setCommand(command); if (codeSignIdentitySupplier.isPresent()) { builder.addCommand( "--sign", CodeSignStep.getIdentityArg(codeSignIdentitySupplier.get().get())); } return builder.build(); } @Override public int execute(ExecutionContext context) throws InterruptedException { ListeningProcessExecutor executor = new ListeningProcessExecutor(); ProcessExecutorParams params = makeProcessExecutorParams(); SimpleProcessListener listener = new SimpleProcessListener(); // TODO(ryu2): parse output as needed try { LOG.debug("%s", command); ListeningProcessExecutor.LaunchedProcess process = executor.launchProcess(params, listener); int result = executor.waitForProcess(process, Long.MAX_VALUE, TimeUnit.SECONDS); if (result != 0) { LOG.error("Error running %s: %s", getDescription(context), listener.getStderr()); } return result; } catch (IOException e) { LOG.error(e, "Could not execute command %s", command); return 1; } } @Override public String getDescription(ExecutionContext context) { return Joiner.on(" ").join(command); } }
private synchronized void invalidateAllCaches() { LOG.debug("Invalidating all caches"); allTargetNodes.invalidateAll(); targetsCornucopia.clear(); allRawNodes.invalidateAll(); buildFileDependents.clear(); knownCells.clear(); }
public static int parseAndWriteBuckCompatibleDepfile( ExecutionContext context, ProjectFilesystem filesystem, HeaderPathNormalizer headerPathNormalizer, HeaderVerification headerVerification, Path sourceDepFile, Path destDepFile, Path inputPath, Path outputPath) throws IOException { // Process the dependency file, fixing up the paths, and write it out to it's final location. // The paths of the headers written out to the depfile are the paths to the symlinks from the // root of the repo if the compilation included them from the header search paths pointing to // the symlink trees, or paths to headers relative to the source file if the compilation // included them using source relative include paths. To handle both cases we check for the // prerequisites both in the values and the keys of the replacement map. Logger.get(Depfiles.class).debug("Processing dependency file %s as Makefile", sourceDepFile); ImmutableMap<String, Object> params = ImmutableMap.<String, Object>of("input", inputPath, "output", outputPath); try (InputStream input = filesystem.newFileInputStream(sourceDepFile); BufferedReader reader = new BufferedReader(new InputStreamReader(input)); OutputStream output = filesystem.newFileOutputStream(destDepFile); BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(output)); SimplePerfEvent.Scope perfEvent = SimplePerfEvent.scope( context.getBuckEventBus(), PerfEventId.of("depfile-parse"), params)) { ImmutableList<String> prereqs = Depfiles.parseDepfile(reader).getPrereqs(); // Skip the first prereq, as it's the input source file. Preconditions.checkState(inputPath.toString().equals(prereqs.get(0))); ImmutableList<String> headers = prereqs.subList(1, prereqs.size()); for (String rawHeader : headers) { Path header = Paths.get(rawHeader).normalize(); Optional<Path> absolutePath = headerPathNormalizer.getAbsolutePathForUnnormalizedPath(header); if (absolutePath.isPresent()) { Preconditions.checkState(absolutePath.get().isAbsolute()); writer.write(absolutePath.get().toString()); writer.newLine(); } else if (headerVerification.getMode() != HeaderVerification.Mode.IGNORE && !headerVerification.isWhitelisted(header.toString())) { context .getBuckEventBus() .post( ConsoleEvent.create( headerVerification.getMode() == HeaderVerification.Mode.ERROR ? Level.SEVERE : Level.WARNING, "%s: included an untracked header \"%s\"", inputPath, header)); if (headerVerification.getMode() == HeaderVerification.Mode.ERROR) { return 1; } } } } return 0; }
public static Optional<AppleSimulatorProfile> parseProfilePlistStream(InputStream inputStream) throws IOException { NSDictionary profile; try (BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream)) { try { profile = (NSDictionary) PropertyListParser.parse(bufferedInputStream); } catch (Exception e) { throw new IOException(e); } } NSObject supportedProductFamilyIDsObject = profile.objectForKey("supportedProductFamilyIDs"); if (!(supportedProductFamilyIDsObject instanceof NSArray)) { LOG.warn( "Invalid simulator profile.plist (supportedProductFamilyIDs missing or not an array)"); return Optional.absent(); } NSArray supportedProductFamilyIDs = (NSArray) supportedProductFamilyIDsObject; AppleSimulatorProfile.Builder profileBuilder = AppleSimulatorProfile.builder(); for (NSObject supportedProductFamilyID : supportedProductFamilyIDs.getArray()) { if (supportedProductFamilyID instanceof NSNumber) { profileBuilder.addSupportedProductFamilyIDs( ((NSNumber) supportedProductFamilyID).intValue()); } else { LOG.warn( "Invalid simulator profile.plist (supportedProductFamilyIDs contains non-number %s)", supportedProductFamilyID); return Optional.absent(); } } NSObject supportedArchsObject = profile.objectForKey("supportedArchs"); if (!(supportedArchsObject instanceof NSArray)) { LOG.warn("Invalid simulator profile.plist (supportedArchs missing or not an array)"); return Optional.absent(); } NSArray supportedArchs = (NSArray) supportedArchsObject; for (NSObject supportedArch : supportedArchs.getArray()) { profileBuilder.addSupportedArchitectures(supportedArch.toString()); } return Optional.of(profileBuilder.build()); }
// If multiple valid ones, find the one which matches the most specifically. I.e., // XXXXXXXXXX.com.example.* will match over XXXXXXXXXX.* for com.example.TestApp // TODO(user): Account for differences between development and distribution certificates. @VisibleForTesting static Optional<ProvisioningProfileMetadata> getBestProvisioningProfile( ImmutableSet<ProvisioningProfileMetadata> profiles, String bundleID, Optional<String> provisioningProfileUUID, Optional<String> prefix) { int bestMatchLength = -1; Optional<ProvisioningProfileMetadata> bestMatch = Optional.<ProvisioningProfileMetadata>absent(); for (ProvisioningProfileMetadata profile : profiles) { if (provisioningProfileUUID.isPresent() && profile.getUUID().equals(provisioningProfileUUID.get())) { return Optional.<ProvisioningProfileMetadata>of(profile); } if (profile.getExpirationDate().after(new Date())) { Pair<String, String> appID = profile.getAppID(); LOG.debug("Looking at provisioning profile " + profile.getUUID() + "," + appID.toString()); if (!prefix.isPresent() || prefix.get().equals(appID.getFirst())) { String profileBundleID = appID.getSecond(); boolean match; if (profileBundleID.endsWith("*")) { // Chop the ending * if wildcard. profileBundleID = profileBundleID.substring(0, profileBundleID.length() - 1); match = bundleID.startsWith(profileBundleID); } else { match = (bundleID.equals(profileBundleID)); } if (match && profileBundleID.length() > bestMatchLength) { bestMatchLength = profileBundleID.length(); bestMatch = Optional.<ProvisioningProfileMetadata>of(profile); } } } } LOG.debug("Found provisioning profile " + bestMatch.toString()); return bestMatch; }
private int doExecute(ExecutionContext context) throws IOException, InterruptedException { List<Predicate<Path>> pathPredicates = Lists.newArrayList(); boolean canDownscale = imageScaler != null && imageScaler.isAvailable(context); LOG.info( "FilterResourcesStep: canDownscale: %s. imageScalar non-null: %s.", canDownscale, imageScaler != null); if (filterDrawables) { Preconditions.checkNotNull(drawableFinder); Set<Path> drawables = drawableFinder.findDrawables(inResDirToOutResDirMap.keySet(), filesystem); pathPredicates.add( ResourceFilters.createImageDensityFilter( drawables, Preconditions.checkNotNull(targetDensities), canDownscale)); } final boolean localeFilterEnabled = !locales.isEmpty(); if (localeFilterEnabled || enableStringWhitelisting) { pathPredicates.add( new Predicate<Path>() { @Override public boolean apply(Path path) { Matcher matcher = NON_ENGLISH_STRINGS_FILE_PATH.matcher(MorePaths.pathWithUnixSeparators(path)); if (!matcher.matches()) { return true; } if (enableStringWhitelisting) { return isPathWhitelisted(path); } else { Preconditions.checkState(localeFilterEnabled); String locale = matcher.group(1); if (matcher.group(2) != null) { locale += "_" + matcher.group(2); } return locales.contains(locale); } } }); } // Create filtered copies of all resource directories. These will be passed to aapt instead. filteredDirectoryCopier.copyDirs( filesystem, inResDirToOutResDirMap, Predicates.and(pathPredicates)); // If an ImageScaler was specified, but only if it is available, try to apply it. if (canDownscale && filterDrawables) { scaleUnmatchedDrawables(context); } return 0; }
public static Config createDefaultConfig( Path root, ImmutableMap<String, ImmutableMap<String, String>> configOverrides) throws IOException { ImmutableList.Builder<Path> configFileBuilder = ImmutableList.builder(); configFileBuilder.addAll(listFiles(GLOBAL_BUCK_CONFIG_DIRECTORY_PATH)); if (Files.isRegularFile(GLOBAL_BUCK_CONFIG_FILE_PATH)) { configFileBuilder.add(GLOBAL_BUCK_CONFIG_FILE_PATH); } Path homeDirectory = Paths.get(System.getProperty("user.home")); Path userConfigDir = homeDirectory.resolve(DEFAULT_BUCK_CONFIG_DIRECTORY_NAME); configFileBuilder.addAll(listFiles(userConfigDir)); Path userConfigFile = homeDirectory.resolve(DEFAULT_BUCK_CONFIG_FILE_NAME); if (Files.isRegularFile(userConfigFile)) { configFileBuilder.add(userConfigFile); } Path configFile = root.resolve(DEFAULT_BUCK_CONFIG_FILE_NAME); if (Files.isRegularFile(configFile)) { configFileBuilder.add(configFile); } Path overrideConfigFile = root.resolve(DEFAULT_BUCK_CONFIG_OVERRIDE_FILE_NAME); if (Files.isRegularFile(overrideConfigFile)) { configFileBuilder.add(overrideConfigFile); } ImmutableList<Path> configFiles = configFileBuilder.build(); ImmutableList.Builder<ImmutableMap<String, ImmutableMap<String, String>>> builder = ImmutableList.builder(); for (Path file : configFiles) { try (Reader reader = Files.newBufferedReader(file, StandardCharsets.UTF_8)) { ImmutableMap<String, ImmutableMap<String, String>> parsedConfiguration = Inis.read(reader); LOG.debug("Loaded a configuration file %s: %s", file, parsedConfiguration); builder.add(parsedConfiguration); } } LOG.debug("Adding configuration overrides: %s", configOverrides); builder.add(configOverrides); return new Config(builder.build()); }
@Override public int execute(ExecutionContext context) throws InterruptedException { ListeningProcessExecutor executor = new ListeningProcessExecutor(); ProcessExecutorParams params = makeProcessExecutorParams(); SimpleProcessListener listener = new SimpleProcessListener(); // TODO(ryu2): parse output as needed try { LOG.debug("%s", command); ListeningProcessExecutor.LaunchedProcess process = executor.launchProcess(params, listener); int result = executor.waitForProcess(process, Long.MAX_VALUE, TimeUnit.SECONDS); if (result != 0) { LOG.error("Error running %s: %s", getDescription(context), listener.getStderr()); } return result; } catch (IOException e) { LOG.error(e, "Could not execute command %s", command); return 1; } }
private void executePostBuildSteps( BuildRule rule, Iterable<Step> postBuildSteps, BuildContext context) throws InterruptedException, StepFailedException { LOG.debug("Running post-build steps for %s", rule); StepRunner stepRunner = context.getStepRunner(); Optional<BuildTarget> optionalTarget = Optional.of(rule.getBuildTarget()); for (Step step : postBuildSteps) { stepRunner.runStepForBuildTarget(step, optionalTarget); // Check for interruptions that may have been ignored by step. if (Thread.interrupted()) { Thread.currentThread().interrupt(); throw new InterruptedException(); } } LOG.debug("Finished running post-build steps for %s", rule); }
@Override public void invalidateBasedOn(WatchEvent<?> event) throws InterruptedException { if (!WatchEvents.isPathChangeEvent(event)) { // Non-path change event, likely an overflow due to many change events: invalidate everything. LOG.debug("Parser invalidating entire cache on overflow."); invalidateAllCaches(); return; } Path path = (Path) event.context(); for (Cell cell : knownCells) { try { if (isPathCreateOrDeleteEvent(event)) { BuildFileTree buildFiles = buildFileTrees.get(cell); if (path.endsWith(cell.getBuildFileName())) { // If a build file has been added or removed, reconstruct the build file tree. buildFileTrees.invalidate(cell); } // Added or removed files can affect globs, so invalidate the package build file // "containing" {@code path} unless its filename matches a temp file pattern. if (!isTempFile(cell, path)) { invalidateContainingBuildFile(cell, buildFiles, path); } LOG.verbose("Invalidating dependents for path %s, cache state %s", path, this); } } catch (ExecutionException | UncheckedExecutionException e) { try { throw propagate(e); } catch (BuildFileParseException bfpe) { LOG.warn("Unable to parse already parsed build file.", bfpe); } } } invalidatePath(path); }
private ImmutableBiMap<Path, Path> getAllPaths(Optional<Path> workingDir) { if (!workingDir.isPresent()) { return other; } try { return pathCache.get(workingDir.get()); } catch (ExecutionException e) { Logger.get(DebugPathSanitizer.class).error("Problem loading paths into cache", e); return getAllPathsWork(workingDir.get()); } }
private int handleGet(Request baseRequest, HttpServletResponse response) throws IOException { if (!artifactCache.isPresent()) { response.getWriter().write("Serving local cache is disabled for this instance."); return HttpServletResponse.SC_INTERNAL_SERVER_ERROR; } String path = baseRequest.getUri().getPath(); String[] pathElements = path.split("/"); if (pathElements.length != 4 || !pathElements[2].equals("key")) { response.getWriter().write("Incorrect url format."); return HttpServletResponse.SC_INTERNAL_SERVER_ERROR; } RuleKey ruleKey = RuleKey.TO_RULE_KEY.apply(pathElements[3]); Path temp = null; try { temp = projectFilesystem.createTempFile(BuckConstant.SCRATCH_PATH, "outgoing_rulekey", ".tmp"); projectFilesystem.createParentDirs(temp); CacheResult fetchResult; try { fetchResult = artifactCache.get().fetch(ruleKey, temp); } catch (InterruptedException e) { LOG.error(e, "Interrupted when fetching from local cache."); e.printStackTrace(response.getWriter()); return HttpServletResponse.SC_INTERNAL_SERVER_ERROR; } if (!fetchResult.getType().isSuccess()) { return HttpServletResponse.SC_NOT_FOUND; } final Path tempFinal = temp; HttpArtifactCacheBinaryProtocol.FetchResponse fetchResponse = new HttpArtifactCacheBinaryProtocol.FetchResponse( ImmutableSet.of(ruleKey), fetchResult.getMetadata(), new ByteSource() { @Override public InputStream openStream() throws IOException { return projectFilesystem.newFileInputStream(tempFinal); } }); fetchResponse.write(response.getOutputStream()); response.setContentLengthLong(fetchResponse.getContentLength()); return HttpServletResponse.SC_OK; } finally { if (temp != null) { projectFilesystem.deleteFileAtPathIfExists(temp); } } }
@Override public int execute(ExecutionContext context) { try (InputStream sourceStream = source.openStream()) { context .getProjectFilesystem() .copyToPath(sourceStream, outputPath, StandardCopyOption.REPLACE_EXISTING); return 0; } catch (IOException e) { LOG.error(e, "Couldn't copy bytes to %s", outputPath); e.printStackTrace(context.getStdErr()); return 1; } }
public static CxxPlatform getConfigDefaultCxxPlatform( CxxBuckConfig cxxBuckConfig, ImmutableMap<Flavor, CxxPlatform> cxxPlatformsMap, CxxPlatform systemDefaultCxxPlatform) { CxxPlatform defaultCxxPlatform; Optional<String> defaultPlatform = cxxBuckConfig.getDefaultPlatform(); if (defaultPlatform.isPresent()) { defaultCxxPlatform = cxxPlatformsMap.get(ImmutableFlavor.of(defaultPlatform.get())); if (defaultCxxPlatform == null) { LOG.warn( "Couldn't find default platform %s, falling back to system default", defaultPlatform.get()); } else { LOG.debug("Using config default C++ platform %s", defaultCxxPlatform); return defaultCxxPlatform; } } else { LOG.debug("Using system default C++ platform %s", systemDefaultCxxPlatform); } return systemDefaultCxxPlatform; }
public class WriteFileStep implements Step { private static final Logger LOG = Logger.get(WriteFileStep.class); private final ByteSource source; private final Path outputPath; public WriteFileStep(ByteSource content, Path outputPath) { this.source = content; this.outputPath = outputPath; } public WriteFileStep(String content, Path outputPath) { this(Suppliers.ofInstance(content), outputPath); } public WriteFileStep(final Supplier<String> content, Path outputPath) { this( new ByteSource() { @Override public InputStream openStream() throws IOException { // echo by default writes a trailing new line and so should we. return new ByteArrayInputStream((content.get() + "\n").getBytes(Charsets.UTF_8)); } }, outputPath); } @Override public int execute(ExecutionContext context) { try (InputStream sourceStream = source.openStream()) { context .getProjectFilesystem() .copyToPath(sourceStream, outputPath, StandardCopyOption.REPLACE_EXISTING); return 0; } catch (IOException e) { LOG.error(e, "Couldn't copy bytes to %s", outputPath); e.printStackTrace(context.getStdErr()); return 1; } } @Override public String getShortName() { return "write_file"; } @Override public String getDescription(ExecutionContext context) { return String.format("echo ... > %s", Escaper.escapeAsBashString(outputPath)); } }
private static void buildAppleCxxPlatforms( Supplier<Optional<Path>> appleDeveloperDirectorySupplier, ImmutableList<Path> extraToolchainPaths, ImmutableList<Path> extraPlatformPaths, BuckConfig buckConfig, AppleConfig appleConfig, ImmutableMap.Builder<Flavor, AppleCxxPlatform> platformFlavorsToAppleSdkPathsBuilder) throws IOException { Optional<Path> appleDeveloperDirectory = appleDeveloperDirectorySupplier.get(); if (appleDeveloperDirectory.isPresent() && !Files.isDirectory(appleDeveloperDirectory.get())) { LOG.error( "Developer directory is set to %s, but is not a directory", appleDeveloperDirectory.get()); return; } ImmutableMap<String, AppleToolchain> toolchains = AppleToolchainDiscovery.discoverAppleToolchains( appleDeveloperDirectory, extraToolchainPaths); ImmutableMap<AppleSdk, AppleSdkPaths> sdkPaths = AppleSdkDiscovery.discoverAppleSdkPaths( appleDeveloperDirectory, extraPlatformPaths, toolchains); for (Map.Entry<AppleSdk, AppleSdkPaths> entry : sdkPaths.entrySet()) { AppleSdk sdk = entry.getKey(); AppleSdkPaths appleSdkPaths = entry.getValue(); String targetSdkVersion = appleConfig.getTargetSdkVersion(sdk.getApplePlatform()).or(sdk.getVersion()); LOG.debug("SDK %s using default version %s", sdk, targetSdkVersion); for (String architecture : sdk.getArchitectures()) { AppleCxxPlatform appleCxxPlatform = AppleCxxPlatforms.build(sdk, targetSdkVersion, architecture, appleSdkPaths, buckConfig); platformFlavorsToAppleSdkPathsBuilder.put( appleCxxPlatform.getCxxPlatform().getFlavor(), appleCxxPlatform); } } }
@Override public boolean fetch(BuckEventBus eventBus, URI uri, Path output) throws IOException { for (Downloader downloader : delegates) { try { if (downloader.fetch(eventBus, uri, output)) { return true; } } catch (IOException e) { LOG.debug(e, "Unable to download %s from %s", uri, downloader); } } return false; }
/** * Execute the commands for this build rule. Requires all dependent rules are already built * successfully. */ private void executeCommandsNowThatDepsAreBuilt( BuildRule rule, BuildContext context, BuildableContext buildableContext, BuildInfoRecorder buildInfoRecorder) throws InterruptedException, StepFailedException { LOG.debug("Building locally: %s", rule); // Attempt to get an approximation of how long it takes to actually run the command. @SuppressWarnings("PMD.PrematureDeclaration") long start = System.nanoTime(); // Get and run all of the commands. List<Step> steps = rule.getBuildSteps(context, buildableContext); AbiRule abiRule = checkIfRuleOrBuildableIsAbiRule(rule); if (abiRule != null) { buildInfoRecorder.addBuildMetadata( ABI_KEY_FOR_DEPS_ON_DISK_METADATA, abiRule.getAbiKeyForDeps().getHash()); } StepRunner stepRunner = context.getStepRunner(); Optional<BuildTarget> optionalTarget = Optional.of(rule.getBuildTarget()); for (Step step : steps) { stepRunner.runStepForBuildTarget(step, optionalTarget); // Check for interruptions that may have been ignored by step. if (Thread.interrupted()) { Thread.currentThread().interrupt(); throw new InterruptedException(); } } long end = System.nanoTime(); LOG.debug( "Build completed: %s %s (%dns)", rule.getType(), rule.getFullyQualifiedName(), end - start); }
@Override public int runWithoutHelp(final CommandRunnerParams params) throws IOException, InterruptedException { // Create a TargetGraph that is composed of the transitive closure of all of the dependent // TargetNodes for the specified BuildTargets. final ImmutableSet<String> fullyQualifiedBuildTargets = ImmutableSet.copyOf(getArgumentsFormattedAsBuildTargets(params.getBuckConfig())); if (fullyQualifiedBuildTargets.isEmpty()) { params.getConsole().printBuildFailure("Please specify at least one build target."); return 1; } ImmutableSet<BuildTarget> targets = FluentIterable.from(getArgumentsFormattedAsBuildTargets(params.getBuckConfig())) .transform( new Function<String, BuildTarget>() { @Override public BuildTarget apply(String input) { return BuildTargetParser.INSTANCE.parse( input, BuildTargetPatternParser.fullyQualified()); } }) .toSet(); LOG.debug("Getting input for targets: %s", targets); TargetGraph graph; try { graph = params .getParser() .buildTargetGraphForBuildTargets( targets, new ParserConfig(params.getBuckConfig()), params.getBuckEventBus(), params.getConsole(), params.getEnvironment(), getEnableProfiling()); } catch (BuildTargetException | BuildFileParseException e) { params.getConsole().printBuildFailureWithoutStacktrace(e); return 1; } if (shouldGenerateJsonOutput()) { return printJsonInputs(params, graph); } return printInputs(params, graph); }
/** * Attempt to complete submitted requests on close so that as much information is recorded as * possible. This aids debugging when close is called during exception processing. */ @Override public void close() { requestService.shutdown(); try { if (!requestService.awaitTermination(timeoutMillis, TimeUnit.MILLISECONDS)) { LOG.warn( Joiner.on(System.lineSeparator()) .join( "A BlockingHttpEndpoint failed to shut down within the standard timeout.", "Your build might have succeeded, but some requests made to ", this.url + " were probably lost.", "Here's some debugging information:", requestService.toString())); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); } }
/** * {@link ExecutorService#awaitTermination(long, java.util.concurrent.TimeUnit)} is called to wait * for events which have been posted, but which have been queued by the {@link EventBus}, to be * delivered. This allows listeners to record or report as much information as possible. This aids * debugging when close is called during exception processing. */ @Override public void close() throws IOException { executorService.shutdown(); try { if (!executorService.awaitTermination(shutdownTimeoutMillis, TimeUnit.MILLISECONDS)) { LOG.warn( Joiner.on(System.lineSeparator()) .join( "The BuckEventBus failed to shut down within the standard timeout.", "Your build might have succeeded, but some messages were probably lost.", "Here's some debugging information:", executorService.toString())); executorService.shutdownNow(); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); } }