Пример #1
0
 @VisibleForTesting
 public static PackageParserOptions parseArgs(String[] args) {
   args = parseParamFileIfUsed(args);
   OptionsParser optionsParser = OptionsParser.newOptionsParser(PackageParserOptions.class);
   optionsParser.parseAndExitUponError(args);
   return optionsParser.getOptions(PackageParserOptions.class);
 }
Пример #2
0
  public static void main(String[] args) throws OptionsParsingException, IOException {

    FileSystem fileSystem = FileSystems.getDefault();
    OptionsParser parser = OptionsParser.newOptionsParser(PlMergeOptions.class);
    parser.parse(args);
    PlMergeOptions options = parser.getOptions(PlMergeOptions.class);

    MergingArguments data = null;

    if (usingControlProtobuf(options)) {
      InputStream in = Files.newInputStream(fileSystem.getPath(options.controlPath));
      Control control = Control.parseFrom(in);
      validateControl(control);
      data = new MergingArguments(control);
    } else if (usingCommandLineArgs(options)) {
      data = new MergingArguments(options);
    } else {
      missingArg("Either --control or --out_file and at least one --source_file");
    }

    PlistMerging merging =
        PlistMerging.from(
            data,
            ImmutableMap.<String, NSObject>of(),
            new KeysToRemoveIfEmptyString("CFBundleIconFile", "NSPrincipalClass"));
    if (data.getPrimaryBundleId() != null || data.getFallbackBundleId() != null) {
      // Only set the bundle identifier if we were passed arguments to do so.
      // This prevents CFBundleIdentifiers being put into strings files.
      merging.setBundleIdentifier(data.getPrimaryBundleId(), data.getFallbackBundleId());
    }
    merging.writePlist(fileSystem.getPath(data.getOutFile()));
  }
Пример #3
0
  public static void main(String[] args) throws OptionsParsingException, IOException {
    FileSystem fileSystem = FileSystems.getDefault();
    OptionsParser parser = OptionsParser.newOptionsParser(PlMergeOptions.class);
    parser.parse(args);
    PlMergeOptions options = parser.getOptions(PlMergeOptions.class);

    if (options.controlPath == null) {
      missingArg("control");
    }

    InputStream in = Files.newInputStream(fileSystem.getPath(options.controlPath));
    Control control = Control.parseFrom(in);
    validateControl(control);

    PlistMerging merging =
        PlistMerging.from(
            control, new KeysToRemoveIfEmptyString("CFBundleIconFile", "NSPrincipalClass"));

    String primaryBundleId = Strings.emptyToNull(control.getPrimaryBundleId());
    String fallbackBundleId = Strings.emptyToNull(control.getFallbackBundleId());

    if (primaryBundleId != null || fallbackBundleId != null) {
      // Only set the bundle identifier if we were passed arguments to do so.
      // This prevents CFBundleIdentifiers being put into strings files.
      merging.setBundleIdentifier(primaryBundleId, fallbackBundleId);
    }
    merging.writePlist(fileSystem.getPath(control.getOutFile()));
  }
Пример #4
0
  public static void main(String[] args) throws Exception {
    OptionsParser parser =
        OptionsParser.newOptionsParser(RemoteOptions.class, RemoteWorkerOptions.class);
    parser.parseAndExitUponError(args);
    RemoteOptions remoteOptions = parser.getOptions(RemoteOptions.class);
    RemoteWorkerOptions remoteWorkerOptions = parser.getOptions(RemoteWorkerOptions.class);

    if (remoteWorkerOptions.workPath == null) {
      printUsage(parser);
      return;
    }

    System.out.println("*** Starting Hazelcast server.");
    ConcurrentMap<String, byte[]> cache = new HazelcastCacheFactory().create(remoteOptions);

    System.out.println(
        "*** Starting grpc server on all locally bound IPs on port "
            + remoteWorkerOptions.listenPort
            + ".");
    Path workPath = getFileSystem().getPath(remoteWorkerOptions.workPath);
    FileSystemUtils.createDirectoryAndParents(workPath);
    RemoteWorker worker = new RemoteWorker(workPath, remoteOptions, remoteWorkerOptions, cache);
    final Server server =
        ServerBuilder.forPort(remoteWorkerOptions.listenPort).addService(worker).build();
    server.start();

    final Path pidFile;
    if (remoteWorkerOptions.pidFile != null) {
      pidFile = getFileSystem().getPath(remoteWorkerOptions.pidFile);
      PrintWriter writer = new PrintWriter(pidFile.getOutputStream());
      writer.append(Integer.toString(ProcessUtils.getpid()));
      writer.append("\n");
      writer.close();
    } else {
      pidFile = null;
    }

    Runtime.getRuntime()
        .addShutdownHook(
            new Thread() {
              @Override
              public void run() {
                System.err.println("*** Shutting down grpc server.");
                server.shutdown();
                if (pidFile != null) {
                  try {
                    pidFile.delete();
                  } catch (IOException e) {
                    System.err.println("Cannot remove pid file: " + pidFile.toString());
                  }
                }
                System.err.println("*** Server shut down.");
              }
            });
    server.awaitTermination();
  }
  @Test
  public void testUseDefaultWithImplicitlyRequiredFlags() throws Exception {
    InvocationPolicy.Builder invocationPolicyBuilder = InvocationPolicy.newBuilder();
    invocationPolicyBuilder
        .addFlagPoliciesBuilder()
        .setFlagName("an_implicit_requirement")
        .getUseDefaultBuilder();

    InvocationPolicyEnforcer enforcer = createOptionsPolicyEnforcer(invocationPolicyBuilder);
    parser.parse(
        "--test_implicit_requirement=user value", "--an_implicit_requirement=implicit user value");

    // test_implicit_requirement sets an_implicit_requirement to "foo", which ignores the user's
    // value because the parser processes implicit values last.
    TestOptions testOptions = getTestOptions();
    assertEquals("user value", testOptions.testImplicitRequirement);
    assertEquals("foo", testOptions.anImplicitRequirement);

    // Then policy puts an_implicit_requirement back to its default.
    enforcer.enforce(parser, "build");

    testOptions = getTestOptions();
    assertEquals("user value", testOptions.testImplicitRequirement);
    assertEquals("implicit default", testOptions.anImplicitRequirement);
  }
  @Test
  public void testNonExistantFlagFromPolicy() throws Exception {
    InvocationPolicy.Builder invocationPolicyBuilder = InvocationPolicy.newBuilder();
    invocationPolicyBuilder
        .addFlagPoliciesBuilder()
        .setFlagName("i_do_not_exist")
        .getSetValueBuilder()
        .addFlagValue("policy value 1");
    invocationPolicyBuilder
        .addFlagPoliciesBuilder()
        .setFlagName("test_string")
        .getSetValueBuilder()
        .addFlagValue("policy value 2");

    InvocationPolicyEnforcer enforcer = createOptionsPolicyEnforcer(invocationPolicyBuilder);
    parser.parse("--test_string=user value");

    TestOptions testOptions = getTestOptions();
    assertEquals("user value", testOptions.testString);

    enforcer.enforce(parser, "test");

    // Still user value.
    testOptions = getTestOptions();
    assertEquals("policy value 2", testOptions.testString);
  }
  /** Tests that SetValue overrides the user's value when the flag allows multiple values. */
  @Test
  public void testSetValueWithMultipleValuesOverridesUser() throws Exception {
    InvocationPolicy.Builder invocationPolicyBuilder = InvocationPolicy.newBuilder();
    invocationPolicyBuilder
        .addFlagPoliciesBuilder()
        .setFlagName("test_multiple_string")
        .getSetValueBuilder()
        .addFlagValue("policy value 1")
        .addFlagValue("policy value 2");

    InvocationPolicyEnforcer enforcer = createOptionsPolicyEnforcer(invocationPolicyBuilder);
    parser.parse("--test_multiple_string=user value 1", "--test_multiple_string=user value 2");

    // Options should not be modified by running the parser through OptionsPolicyEnforcer.create().
    TestOptions testOptions = getTestOptions();
    assertThat(testOptions.testMultipleString)
        .containsExactly("user value 1", "user value 2")
        .inOrder();
    // assertEquals(, testOptions.test_multiple_string);

    enforcer.enforce(parser, "build");

    // Get the options again after policy enforcement.
    testOptions = getTestOptions();
    assertThat(testOptions.testMultipleString)
        .containsExactly("policy value 1", "policy value 2")
        .inOrder();
  }
  @Test
  public void testUseDefaultWithExpansionFlags() throws Exception {
    InvocationPolicy.Builder invocationPolicyBuilder = InvocationPolicy.newBuilder();
    invocationPolicyBuilder
        .addFlagPoliciesBuilder()
        .setFlagName("test_expansion_b")
        .getUseDefaultBuilder();

    InvocationPolicyEnforcer enforcer = createOptionsPolicyEnforcer(invocationPolicyBuilder);
    parser.parse("--test_expansion");

    // --test_expansion should turn on test_expansion a, b, and c
    TestOptions testOptions = getTestOptions();
    assertTrue(testOptions.testExpansionA);
    assertTrue(testOptions.testExpansionB);
    assertTrue(testOptions.testExpansionC);

    enforcer.enforce(parser, "build");

    // After policy enforcement, test_expansion_b should be back to its default (false), but the
    // other two should remain the same.
    testOptions = getTestOptions();
    assertTrue(testOptions.testExpansionA);
    assertFalse(testOptions.testExpansionB);
    assertTrue(testOptions.testExpansionC);
  }
  @Test
  public void testAllowValuesDisallowsValue() throws Exception {
    InvocationPolicy.Builder invocationPolicyBuilder = InvocationPolicy.newBuilder();
    invocationPolicyBuilder
        .addFlagPoliciesBuilder()
        .setFlagName("test_string")
        .getAllowValuesBuilder()
        // no foo!
        .addAllowedValues(STRING_FLAG_DEFAULT)
        .addAllowedValues("bar");

    InvocationPolicyEnforcer enforcer = createOptionsPolicyEnforcer(invocationPolicyBuilder);
    parser.parse("--test_string=foo");

    // Option should be "foo" as specified by the user.
    TestOptions testOptions = getTestOptions();
    assertEquals("foo", testOptions.testString);

    try {
      // Should throw because "foo" is not allowed.
      enforcer.enforce(parser, "build");
      fail();
    } catch (OptionsParsingException e) {
      // expected
    }
  }
Пример #10
0
  public static void main(String[] args) {
    Stopwatch timer = Stopwatch.createStarted();
    OptionsParser optionsParser = OptionsParser.newOptionsParser(Options.class);
    optionsParser.parseAndExitUponError(args);
    Options options = optionsParser.getOptions(Options.class);

    checkFlags(options);

    FileSystem fileSystem = FileSystems.getDefault();
    Path working = fileSystem.getPath("").toAbsolutePath();

    AndroidResourceProcessor resourceProcessor =
        new AndroidResourceProcessor(new StdLogger(com.android.utils.StdLogger.Level.VERBOSE));

    try {
      Path resourcesOut = Files.createTempDirectory("tmp-resources");
      resourcesOut.toFile().deleteOnExit();
      Path assetsOut = Files.createTempDirectory("tmp-assets");
      assetsOut.toFile().deleteOnExit();
      logger.fine(String.format("Setup finished at %dms", timer.elapsed(TimeUnit.MILLISECONDS)));

      ImmutableList<DirectoryModifier> modifiers =
          ImmutableList.of(
              new PackedResourceTarExpander(working.resolve("expanded"), working),
              new FileDeDuplicator(
                  Hashing.murmur3_128(), working.resolve("deduplicated"), working));
      MergedAndroidData mergedData =
          resourceProcessor.mergeData(
              options.mainData,
              options.dependencyData,
              resourcesOut,
              assetsOut,
              modifiers,
              null,
              options.strictMerge);
      logger.info(String.format("Merging finished at %dms", timer.elapsed(TimeUnit.MILLISECONDS)));

      writeAar(options.aarOutput, mergedData, options.manifest, options.rtxt, options.classes);
      logger.info(
          String.format("Packaging finished at %dms", timer.elapsed(TimeUnit.MILLISECONDS)));

    } catch (IOException | MergingException e) {
      logger.log(Level.SEVERE, "Error during merging resources", e);
      System.exit(1);
    }
    System.exit(0);
  }
  private static InvocationPolicyEnforcer createOptionsPolicyEnforcer(
      InvocationPolicy.Builder invocationPolicyBuilder) throws Exception {
    InvocationPolicy policyProto = invocationPolicyBuilder.build();

    // An OptionsPolicyEnforcer could be constructed in the test directly from the InvocationPolicy
    // proto, however Blaze will actually take the policy as another flag with a Base64 encoded
    // binary proto and parse that, so exercise that code path in the test.

    ByteArrayOutputStream out = new ByteArrayOutputStream();
    policyProto.writeTo(out);
    String policyBase64 = BaseEncoding.base64().encode(out.toByteArray());

    OptionsParser startupOptionsParser =
        OptionsParser.newOptionsParser(BlazeServerStartupOptions.class);
    String policyOption = "--invocation_policy=" + policyBase64;
    startupOptionsParser.parse(policyOption);

    return InvocationPolicyEnforcer.create(startupOptionsParser);
  }
Пример #12
0
  protected BuildConfigurationCollection createCollection(String... args) throws Exception {
    OptionsParser parser =
        OptionsParser.newOptionsParser(
            ImmutableList.<Class<? extends OptionsBase>>builder()
                .addAll(buildOptionClasses)
                .add(TestOptions.class)
                .build());
    parser.parse(args);
    ImmutableSortedSet<String> multiCpu =
        ImmutableSortedSet.copyOf(parser.getOptions(TestOptions.class).multiCpus);

    configurationFactory.forbidSanityCheck();
    BuildOptions buildOptions = BuildOptions.of(buildOptionClasses, parser);
    BuildConfigurationCollection collection =
        skyframeExecutor.createConfigurations(
            configurationFactory,
            buildOptions,
            new BlazeDirectories(outputBase, outputBase, workspace),
            multiCpu,
            false);
    return collection;
  }
 @Before
 public final void initializeRuntime() throws Exception {
   BlazeDirectories directories =
       new BlazeDirectories(
           scratch.dir("install_base"), scratch.dir("output_base"), scratch.dir("pkg"));
   this.runtime =
       new BlazeRuntime.Builder()
           .setDirectories(directories)
           .setStartupOptionsProvider(
               OptionsParser.newOptionsParser(BlazeServerStartupOptions.class))
           .setConfigurationFactory(
               new ConfigurationFactory(Mockito.mock(ConfigurationCollectionFactory.class)))
           .build();
 }
Пример #14
0
  @Override
  public void editOptions(CommandEnvironment env, OptionsParser optionsParser)
      throws AbruptExitException {
    ProjectFileSupport.handleProjectFiles(env, optionsParser, commandName());

    TestOutputFormat testOutput = optionsParser.getOptions(ExecutionOptions.class).testOutput;

    try {
      if (testOutput == TestStrategy.TestOutputFormat.STREAMED) {
        env.getReporter()
            .handle(
                Event.warn(
                    "Streamed test output requested so all tests will be run locally, without sharding, "
                        + "one at a time"));
        optionsParser.parse(
            OptionPriority.SOFTWARE_REQUIREMENT,
            "streamed output requires locally run tests, without sharding",
            ImmutableList.of("--test_sharding_strategy=disabled", "--test_strategy=exclusive"));
      }
    } catch (OptionsParsingException e) {
      throw new IllegalStateException("Known options failed to parse", e);
    }
  }
  @Test
  public void testOperationNotSet() throws Exception {
    InvocationPolicy.Builder invocationPolicyBuilder = InvocationPolicy.newBuilder();
    invocationPolicyBuilder.addFlagPoliciesBuilder();
    // No operations added to the flag policy

    InvocationPolicyEnforcer enforcer = createOptionsPolicyEnforcer(invocationPolicyBuilder);
    parser.parse("--test_string=user value");

    TestOptions testOptions = getTestOptions();
    assertEquals("user value", testOptions.testString);

    // Shouldn't throw.
    enforcer.enforce(parser, "test");

    // Still user value.
    testOptions = getTestOptions();
    assertEquals("user value", testOptions.testString);
  }
  /** Tests that policy overrides a value when that value is from the user. */
  @Test
  public void testSetValueOverridesUser() throws Exception {
    InvocationPolicy.Builder invocationPolicyBuilder = InvocationPolicy.newBuilder();
    invocationPolicyBuilder
        .addFlagPoliciesBuilder()
        .setFlagName("test_string")
        .getSetValueBuilder()
        .addFlagValue("policy value");

    InvocationPolicyEnforcer enforcer = createOptionsPolicyEnforcer(invocationPolicyBuilder);
    parser.parse("--test_string=user value");

    TestOptions testOptions = getTestOptions();
    assertEquals("user value", testOptions.testString);

    enforcer.enforce(parser, "build");

    // Get the options again after policy enforcement.
    testOptions = getTestOptions();
    assertEquals("policy value", testOptions.testString);
  }
  /**
   * ***********************************************************************************************
   * Other tests
   * **********************************************************************************************
   */
  @Test
  public void testFlagPolicyDoesNotApply() throws Exception {
    InvocationPolicy.Builder invocationPolicyBuilder = InvocationPolicy.newBuilder();
    invocationPolicyBuilder
        .addFlagPoliciesBuilder()
        .setFlagName("test_string")
        .addCommands("build")
        .getSetValueBuilder()
        .addFlagValue("policy value");

    InvocationPolicyEnforcer enforcer = createOptionsPolicyEnforcer(invocationPolicyBuilder);
    parser.parse("--test_string=user value");

    TestOptions testOptions = getTestOptions();
    assertEquals("user value", testOptions.testString);

    enforcer.enforce(parser, "test");

    // Still user value.
    testOptions = getTestOptions();
    assertEquals("user value", testOptions.testString);
  }
  @Test
  public void testSetValueWithNoValueThrows() throws Exception {
    InvocationPolicy.Builder invocationPolicyBuilder = InvocationPolicy.newBuilder();
    invocationPolicyBuilder
        .addFlagPoliciesBuilder()
        .setFlagName("test_string")
        .getSetValueBuilder(); // No value.

    InvocationPolicyEnforcer enforcer = createOptionsPolicyEnforcer(invocationPolicyBuilder);
    parser.parse("--test_string=user value");

    // Repeatable flags always default to the empty list.
    TestOptions testOptions = getTestOptions();
    assertEquals("user value", testOptions.testString);

    try {
      enforcer.enforce(parser, "build");
      fail();
    } catch (OptionsParsingException e) {
      // expected.
    }
  }
  /**
   * ***********************************************************************************************
   * Tests for UseDefault
   * **********************************************************************************************
   */
  @Test
  public void testUseDefault() throws Exception {
    InvocationPolicy.Builder invocationPolicyBuilder = InvocationPolicy.newBuilder();
    invocationPolicyBuilder
        .addFlagPoliciesBuilder()
        .setFlagName("test_string")
        .getUseDefaultBuilder();

    InvocationPolicyEnforcer enforcer = createOptionsPolicyEnforcer(invocationPolicyBuilder);
    parser.parse("--test_string=user value");

    // Options should be the user specified value before enforcing policy.
    TestOptions testOptions = getTestOptions();
    assertEquals("user value", testOptions.testString);

    enforcer.enforce(parser, "build");

    // Get the options again after policy enforcement: The flag should now be back to its default
    // value
    testOptions = getTestOptions();
    assertEquals(STRING_FLAG_DEFAULT, testOptions.testString);
  }
  /**
   * ***********************************************************************************************
   * Tests for DisallowValues
   * **********************************************************************************************
   */
  @Test
  public void testDisallowValuesAllowsValue() throws Exception {
    InvocationPolicy.Builder invocationPolicyBuilder = InvocationPolicy.newBuilder();
    invocationPolicyBuilder
        .addFlagPoliciesBuilder()
        .setFlagName("test_string")
        .getDisallowValuesBuilder()
        .addDisallowedValues("foo")
        .addDisallowedValues("bar");

    InvocationPolicyEnforcer enforcer = createOptionsPolicyEnforcer(invocationPolicyBuilder);
    parser.parse("--test_string=baz");

    // Option should be "baz" as specified by the user.
    TestOptions testOptions = getTestOptions();
    assertEquals("baz", testOptions.testString);

    enforcer.enforce(parser, "build");

    // Still "baz" since "baz" is allowed by the policy.
    testOptions = getTestOptions();
    assertEquals("baz", testOptions.testString);
  }
  @Test
  public void testSetValueWithImplicitlyRequiredFlags() throws Exception {
    InvocationPolicy.Builder invocationPolicyBuilder = InvocationPolicy.newBuilder();
    invocationPolicyBuilder
        .addFlagPoliciesBuilder()
        .setFlagName("an_implicit_requirement")
        .getSetValueBuilder()
        .addFlagValue("policy value");

    InvocationPolicyEnforcer enforcer = createOptionsPolicyEnforcer(invocationPolicyBuilder);
    parser.parse("--test_implicit_requirement=user value");

    // test_implicit_requirement sets an_implicit_requirement to "foo"
    TestOptions testOptions = getTestOptions();
    assertEquals("user value", testOptions.testImplicitRequirement);
    assertEquals("foo", testOptions.anImplicitRequirement);

    enforcer.enforce(parser, "build");

    testOptions = getTestOptions();
    assertEquals("user value", testOptions.testImplicitRequirement);
    assertEquals("policy value", testOptions.anImplicitRequirement);
  }
  @Test
  public void testDisallowValuesDisallowsMultipleValues() throws Exception {
    InvocationPolicy.Builder invocationPolicyBuilder = InvocationPolicy.newBuilder();
    invocationPolicyBuilder
        .addFlagPoliciesBuilder()
        .setFlagName("test_multiple_string")
        .getDisallowValuesBuilder()
        .addDisallowedValues("foo")
        .addDisallowedValues("bar");

    InvocationPolicyEnforcer enforcer = createOptionsPolicyEnforcer(invocationPolicyBuilder);
    parser.parse("--test_multiple_string=baz", "--test_multiple_string=bar");

    // Option should be "baz" and "bar" as specified by the user.
    TestOptions testOptions = getTestOptions();
    assertThat(testOptions.testMultipleString).containsExactly("baz", "bar").inOrder();

    try {
      enforcer.enforce(parser, "build");
      fail();
    } catch (OptionsParsingException e) {
      // expected, since bar is disallowed.
    }
  }
  @Test
  public void testDisallowValuesDisallowsValue() throws Exception {
    InvocationPolicy.Builder invocationPolicyBuilder = InvocationPolicy.newBuilder();
    invocationPolicyBuilder
        .addFlagPoliciesBuilder()
        .setFlagName("test_string")
        .getDisallowValuesBuilder()
        .addDisallowedValues("foo")
        .addDisallowedValues("bar");

    InvocationPolicyEnforcer enforcer = createOptionsPolicyEnforcer(invocationPolicyBuilder);
    parser.parse("--test_string=foo");

    // Option should be "foo" as specified by the user.
    TestOptions testOptions = getTestOptions();
    assertEquals("foo", testOptions.testString);

    try {
      enforcer.enforce(parser, "build");
      fail();
    } catch (OptionsParsingException e) {
      // expected, since foo is disallowed.
    }
  }
  @Test
  public void testSetValueOverridable() throws Exception {
    InvocationPolicy.Builder invocationPolicyBuilder = InvocationPolicy.newBuilder();
    invocationPolicyBuilder
        .addFlagPoliciesBuilder()
        .setFlagName("test_string")
        .getSetValueBuilder()
        .addFlagValue("policy value")
        .setOverridable(true);

    InvocationPolicyEnforcer enforcer = createOptionsPolicyEnforcer(invocationPolicyBuilder);
    parser.parse("--test_string=user value");

    // Repeatable flags always default to the empty list.
    TestOptions testOptions = getTestOptions();
    assertEquals("user value", testOptions.testString);

    enforcer.enforce(parser, "build");

    // Even though the policy sets the value for test_string, the policy is overridable and the
    // user set the value, so it should be the user's value.
    testOptions = getTestOptions();
    assertEquals("user value", testOptions.testString);
  }
Пример #25
0
 public static void printUsage(OptionsParser parser) {
   System.out.println("Usage: remote_worker \n\n" + "Starts a worker that runs a RPC service.");
   System.out.println(
       parser.describeOptions(
           Collections.<String, String>emptyMap(), OptionsParser.HelpVerbosity.LONG));
 }
 @Before
 public final void setParser() throws Exception {
   parser = OptionsParser.newOptionsParser(TestOptions.class);
 }
 private TestOptions getTestOptions() {
   return parser.getOptions(TestOptions.class);
 }
  public static void main(String[] args) throws Exception {
    final Stopwatch timer = Stopwatch.createStarted();
    OptionsParser optionsParser =
        OptionsParser.newOptionsParser(Options.class, AaptConfigOptions.class);
    optionsParser.parseAndExitUponError(args);
    aaptConfigOptions = optionsParser.getOptions(AaptConfigOptions.class);
    options = optionsParser.getOptions(Options.class);

    FileSystem fileSystem = FileSystems.getDefault();
    Path working = fileSystem.getPath("").toAbsolutePath();
    final AndroidResourceProcessor resourceProcessor = new AndroidResourceProcessor(STD_LOGGER);

    try {
      final Path tmp = Files.createTempDirectory("android_resources_tmp");
      // Clean up the tmp file on exit to keep diskspace low.
      tmp.toFile().deleteOnExit();

      final Path expandedOut = tmp.resolve("tmp-expanded");
      final Path deduplicatedOut = tmp.resolve("tmp-deduplicated");
      final Path mergedAssets = tmp.resolve("merged_assets");
      final Path mergedResources = tmp.resolve("merged_resources");
      final Path filteredResources = tmp.resolve("resources-filtered");
      final Path densityManifest = tmp.resolve("manifest-filtered/AndroidManifest.xml");
      final Path processedManifest = tmp.resolve("manifest-processed/AndroidManifest.xml");

      Path generatedSources = null;
      if (options.srcJarOutput != null
          || options.rOutput != null
          || options.symbolsTxtOut != null) {
        generatedSources = tmp.resolve("generated_resources");
      }

      LOGGER.fine(String.format("Setup finished at %sms", timer.elapsed(TimeUnit.MILLISECONDS)));

      final ImmutableList<DirectoryModifier> modifiers =
          ImmutableList.of(
              new PackedResourceTarExpander(expandedOut, working),
              new FileDeDuplicator(Hashing.murmur3_128(), deduplicatedOut, working));

      // Resources can appear in both the direct dependencies and transitive -- use a set to
      // ensure depeduplication.
      List<DependencyAndroidData> data =
          ImmutableSet.<DependencyAndroidData>builder()
              .addAll(options.directData)
              .addAll(options.transitiveData)
              .build()
              .asList();

      final MergedAndroidData mergedData =
          resourceProcessor.mergeData(
              options.primaryData,
              data,
              mergedResources,
              mergedAssets,
              modifiers,
              selectPngCruncher(),
              true);

      LOGGER.fine(String.format("Merging finished at %sms", timer.elapsed(TimeUnit.MILLISECONDS)));

      final DensityFilteredAndroidData filteredData =
          mergedData.filter(
              new DensitySpecificResourceFilter(
                  options.densities, filteredResources, mergedResources),
              new DensitySpecificManifestProcessor(options.densities, densityManifest));

      LOGGER.fine(
          String.format(
              "Density filtering finished at %sms", timer.elapsed(TimeUnit.MILLISECONDS)));

      final MergedAndroidData processedManifestData =
          resourceProcessor.processManifest(
              options.packageType,
              options.packageForR,
              options.applicationId,
              options.versionCode,
              options.versionName,
              filteredData,
              processedManifest);

      resourceProcessor.processResources(
          aaptConfigOptions.aapt,
          aaptConfigOptions.androidJar,
          aaptConfigOptions.buildToolsVersion,
          options.packageType,
          aaptConfigOptions.debug,
          options.packageForR,
          new FlagAaptOptions(aaptConfigOptions),
          aaptConfigOptions.resourceConfigs,
          aaptConfigOptions.splits,
          processedManifestData,
          data,
          generatedSources,
          options.packagePath,
          options.proguardOutput,
          options.mainDexProguardOutput,
          options.resourcesOutput != null
              ? processedManifestData.getResourceDir().resolve("values").resolve("public.xml")
              : null);
      LOGGER.fine(String.format("aapt finished at %sms", timer.elapsed(TimeUnit.MILLISECONDS)));

      if (options.manifestOutput != null) {
        resourceProcessor.copyManifestToOutput(processedManifestData, options.manifestOutput);
      }
      if (options.srcJarOutput != null) {
        resourceProcessor.createSrcJar(
            generatedSources,
            options.srcJarOutput,
            VariantConfiguration.Type.LIBRARY == options.packageType);
      }
      if (options.rOutput != null) {
        resourceProcessor.copyRToOutput(
            generatedSources,
            options.rOutput,
            VariantConfiguration.Type.LIBRARY == options.packageType);
      }
      if (options.symbolsTxtOut != null) {
        resourceProcessor.copyRToOutput(
            generatedSources,
            options.symbolsTxtOut,
            VariantConfiguration.Type.LIBRARY == options.packageType);
      }
      if (options.resourcesOutput != null) {
        resourceProcessor.createResourcesZip(
            processedManifestData.getResourceDir(),
            processedManifestData.getAssetDir(),
            options.resourcesOutput);
      }
      LOGGER.fine(
          String.format("Packaging finished at %sms", timer.elapsed(TimeUnit.MILLISECONDS)));
    } catch (MergingException e) {
      LOGGER.log(java.util.logging.Level.SEVERE, "Error during merging resources", e);
      throw e;
    } catch (IOException | InterruptedException | LoggedErrorException e) {
      LOGGER.log(java.util.logging.Level.SEVERE, "Error during processing resources", e);
      throw e;
    } catch (Exception e) {
      LOGGER.log(java.util.logging.Level.SEVERE, "Unexpected", e);
      throw e;
    } finally {
      resourceProcessor.shutdown();
    }
    LOGGER.fine(String.format("Resources processed in %sms", timer.elapsed(TimeUnit.MILLISECONDS)));
  }