// Copyright 2017 The Bazel Authors. All rights reserved. // // 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.google.devtools.build.lib.rules.android; import com.google.common.collect.ImmutableSet; import com.google.devtools.build.lib.actions.Artifact; import com.google.devtools.build.lib.analysis.RuleContext; import com.google.devtools.build.lib.analysis.actions.CustomCommandLine; import com.google.devtools.build.lib.analysis.actions.CustomCommandLine.VectorArg; import com.google.devtools.build.lib.analysis.actions.SpawnAction; import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget.Mode; /** Builder for creating a zip filter action. */ public class ZipFilterBuilder { /** Type of compression to apply to output archive. */ public enum Compression { /** Output should be compressed. */ COMPRESSED, /** Output should not be compressed. */ UNCOMPRESSED, /** Compression should not change from input Zip. */ DONT_CHANGE; } /** Modes of performing content hash checking during zip filtering. */ public enum CheckHashMismatchMode { NONE, WARN, ERROR; } private final RuleContext ruleContext; private Artifact inputZip; private Artifact outputZip; private final ImmutableSet.Builder filterZipsBuilder; private final ImmutableSet.Builder filterFileTypesBuilder; private final ImmutableSet.Builder explicitFilterBuilder; private Compression outputMode = Compression.DONT_CHANGE; private CheckHashMismatchMode checkHashMismatch = CheckHashMismatchMode.WARN; /** Creates a builder using the configuration of the rule as the action configuration. */ public ZipFilterBuilder(RuleContext ruleContext) { this.ruleContext = ruleContext; filterZipsBuilder = new ImmutableSet.Builder<>(); filterFileTypesBuilder = new ImmutableSet.Builder<>(); explicitFilterBuilder = new ImmutableSet.Builder<>(); } /** Sets the Zip file to be filtered. */ public ZipFilterBuilder setInputZip(Artifact inputZip) { this.inputZip = inputZip; return this; } /** Sets the artifact to create with the action. */ public ZipFilterBuilder setOutputZip(Artifact outputZip) { this.outputZip = outputZip; return this; } /** * Adds to the Zip files to use as filters. Contents in these files will be omitted from the * output. */ public ZipFilterBuilder addFilterZips(Iterable filterZips) { this.filterZipsBuilder.addAll(filterZips); return this; } /** * Adds to the file types to use as filters. Only contents in the filter Zip files with these * extensions will be filtered out. */ public ZipFilterBuilder addFileTypeToFilter(String filterFileType) { this.filterFileTypesBuilder.add(filterFileType); return this; } /** Adds filterRegex to the set of filters to always check for and remove. */ public ZipFilterBuilder addExplicitFilter(String filterRegex) { this.explicitFilterBuilder.add(filterRegex); return this; } /** Enable checking of hash mismatches for files with the same name. */ public ZipFilterBuilder setCheckHashMismatchMode(CheckHashMismatchMode mode) { this.checkHashMismatch = mode; return this; } /** Builds the action as configured. */ public void build() { ImmutableSet filterZips = filterZipsBuilder.build(); ImmutableSet filterFileTypes = filterFileTypesBuilder.build(); ImmutableSet explicitFilters = explicitFilterBuilder.build(); CustomCommandLine.Builder args = CustomCommandLine.builder(); args.addExecPath("--inputZip", inputZip); args.addExecPath("--outputZip", outputZip); if (!filterZips.isEmpty()) { args.addExecPaths("--filterZips", VectorArg.join(",").each(filterZips)); } if (!filterFileTypes.isEmpty()) { args.addAll("--filterTypes", VectorArg.join(",").each(filterFileTypes)); } if (!explicitFilters.isEmpty()) { args.addAll("--explicitFilters", VectorArg.join(",").each(explicitFilters)); } switch (checkHashMismatch) { case WARN: args.add("--checkHashMismatch").add("WARN"); break; case ERROR: args.add("--checkHashMismatch").add("ERROR"); break; case NONE: args.add("--checkHashMismatch").add("IGNORE"); break; } args.add("--outputMode"); switch (outputMode) { case COMPRESSED: args.add("FORCE_DEFLATE"); break; case UNCOMPRESSED: args.add("FORCE_STORED"); break; case DONT_CHANGE: default: args.add("DONT_CARE"); break; } ruleContext.registerAction( new SpawnAction.Builder() .addInput(inputZip) .addInputs(filterZips) .addOutput(outputZip) .setExecutable(ruleContext.getExecutablePrerequisite("$zip_filter", Mode.HOST)) .addCommandLine(args.build()) .setProgressMessage("Filtering Zip %s", inputZip.prettyPrint()) .setMnemonic("ZipFilter") .build(ruleContext)); } }