| // 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<Artifact> filterZipsBuilder; |
| private final ImmutableSet.Builder<String> filterFileTypesBuilder; |
| private final ImmutableSet.Builder<String> 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<Artifact> 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<Artifact> filterZips = filterZipsBuilder.build(); |
| ImmutableSet<String> filterFileTypes = filterFileTypesBuilder.build(); |
| ImmutableSet<String> 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)); |
| } |
| } |