com.facebook.buck.rules.macros.OutputToFileExpander.java Source code

Java tutorial

Introduction

Here is the source code for com.facebook.buck.rules.macros.OutputToFileExpander.java

Source

/*
 * Copyright 2015-present Facebook, Inc.
 *
 * 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 com.facebook.buck.rules.macros;

import static java.nio.charset.StandardCharsets.UTF_8;

import com.facebook.buck.io.ProjectFilesystem;
import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.model.BuildTargets;
import com.facebook.buck.model.MacroException;
import com.facebook.buck.rules.BuildRule;
import com.facebook.buck.rules.BuildRuleResolver;
import com.facebook.buck.rules.CellPathResolver;
import com.google.common.collect.ImmutableList;
import com.google.common.hash.Hashing;

import java.io.IOException;
import java.nio.file.Path;
import java.util.Optional;

public class OutputToFileExpander implements MacroExpander {
    private final MacroExpander delegate;

    public OutputToFileExpander(MacroExpander delegate) {
        this.delegate = delegate;
    }

    @Override
    public String expand(BuildTarget target, CellPathResolver cellNames, BuildRuleResolver resolver,
            ImmutableList<String> input) throws MacroException {

        try {
            String expanded;
            if (delegate instanceof MacroExpanderWithCustomFileOutput) {
                expanded = ((MacroExpanderWithCustomFileOutput) delegate).expandForFile(target, cellNames, resolver,
                        input);
            } else {
                expanded = delegate.expand(target, cellNames, resolver, input);
            }

            Optional<BuildRule> rule = resolver.getRuleOptional(target);
            if (!rule.isPresent()) {
                throw new MacroException(String.format("no rule %s", target));
            }
            ProjectFilesystem filesystem = rule.get().getProjectFilesystem();
            Path tempFile = createTempFile(filesystem, target, input.get(0));
            filesystem.writeContentsToPath(expanded, tempFile);
            return "@" + filesystem.resolve(tempFile);
        } catch (IOException e) {
            throw new MacroException("Unable to create file to hold expanded results", e);
        }
    }

    @Override
    public ImmutableList<BuildRule> extractBuildTimeDeps(BuildTarget target, CellPathResolver cellNames,
            BuildRuleResolver resolver, ImmutableList<String> input) throws MacroException {
        return delegate.extractBuildTimeDeps(target, cellNames, resolver, input);
    }

    @Override
    public ImmutableList<BuildTarget> extractParseTimeDeps(BuildTarget target, CellPathResolver cellNames,
            ImmutableList<String> input) throws MacroException {
        return delegate.extractParseTimeDeps(target, cellNames, input);
    }

    @Override
    public Object extractRuleKeyAppendables(BuildTarget target, CellPathResolver cellNames,
            BuildRuleResolver resolver, ImmutableList<String> input) throws MacroException {
        return delegate.extractRuleKeyAppendables(target, cellNames, resolver, input);
    }

    /**
     * @return The absolute path to the temp file.
     */
    private Path createTempFile(ProjectFilesystem filesystem, BuildTarget target, String input) throws IOException {
        Path directory = BuildTargets.getScratchPath(filesystem, target, "%s/tmp");
        filesystem.mkdirs(directory);

        // "prefix" should give a stable name, so that the same delegate with the same input can output
        // the same file. We won't optimise for this case, since it's actually unlikely to happen within
        // a single run, but using a random name would cause 'buck-out' to expand in an uncontrolled
        // manner.
        String prefix = Hashing.sha1().newHasher().putString(delegate.getClass().getName(), UTF_8)
                .putString(input, UTF_8).hash().toString();

        return filesystem.createTempFile(directory, prefix, ".macro");
    }
}