public static Version getVersionFromBundleConfig(BundleConfig bundleConfig) { String rawVersion = bundleConfig.getBundletool().getVersion(); // Legacy. Remove soon and fail. if (Strings.isNullOrEmpty(rawVersion)) { return Version.of("0.0.0"); } return Version.of(rawVersion); } }
.orElse(BundleConfig.getDefaultInstance()) .toBuilder() .setBundletool( Bundletool.newBuilder()
private void validateMasterResources(BundleConfig bundleConfig, AppBundle bundle) { ImmutableSet<Integer> resourcesToBePinned = ImmutableSet.copyOf(bundleConfig.getMasterResources().getResourceIdsList()); if (resourcesToBePinned.isEmpty()) { return; } ImmutableSet<Integer> allResourceIds = bundle.getFeatureModules().values().stream() .map(BundleModule::getResourceTable) .filter(Optional::isPresent) .map(Optional::get) .flatMap(resourceTable -> ResourcesUtils.entries(resourceTable)) .map(ResourceTableEntry::getResourceId) .map(ResourceId::getFullResourceId) .collect(toImmutableSet()); SetView<Integer> undefinedResources = Sets.difference(resourcesToBePinned, allResourceIds); if (!undefinedResources.isEmpty()) { throw ValidationException.builder() .withMessage( "Error in BundleConfig. The Master Resources list contains resource IDs not defined " + "in any module. For example: 0x%08x", undefinedResources.iterator().next()) .build(); } } }
command.getSigningConfiguration(), bundleVersion, bundleConfig.getCompression(), tempDir);
Path bundlePath = new ZipBuilder() .addFileWithContent(ZipPath.create("BundleConfig.pb"), BUNDLE_CONFIG.toByteArray()) .addFileWithProtoContent( ZipPath.create("moduleX/manifest/AndroidManifest.xml"),
BundleConfig bundleConfig, ImmutableSet<OptimizationDimension> optimizationsOverride) { String buildVersionString = bundleConfig.getBundletool().getVersion(); Version bundleToolBuildVersion = buildVersionString.isEmpty() Optimizations requestedOptimizations = bundleConfig.getOptimizations();
@Test public void validateBundle_invokesSubValidatorsInSequence() throws Exception { Path bundlePath = new ZipBuilder() .addFileWithContent(ZipPath.create("BundleConfig.pb"), BUNDLE_CONFIG.toByteArray()) .addFileWithProtoContent( ZipPath.create("moduleX/manifest/AndroidManifest.xml"), androidManifest("com.test.app", withSplitId("moduleX"))) .addFileWithContent(ZipPath.create("moduleX/assets/file.txt"), DUMMY_CONTENT) .addFileWithProtoContent( ZipPath.create("moduleY/manifest/AndroidManifest.xml"), androidManifest("com.test.app", withSplitId("moduleY"))) .addFileWithContent(ZipPath.create("moduleY/assets/file.txt"), DUMMY_CONTENT) .writeTo(tempFolder.resolve("bundle.aab")); AppBundle bundle = AppBundle.buildFromZip(new ZipFile(bundlePath.toFile())); ImmutableList<BundleModule> bundleFeatureModules = ImmutableList.copyOf(bundle.getFeatureModules().values()); new ValidatorRunner(ImmutableList.of(validator, validator2)).validateBundle(bundle); InOrder order = Mockito.inOrder(validator, validator2); order.verify(validator).validateBundle(eq(bundle)); order.verify(validator).validateAllModules(eq(bundleFeatureModules)); order.verify(validator).validateModule(anyObject()); order.verify(validator, atLeastOnce()).validateModuleFile(anyObject()); order.verify(validator2).validateBundle(eq(bundle)); order.verify(validator2).validateAllModules(eq(bundleFeatureModules)); order.verify(validator2).validateModule(anyObject()); order.verify(validator2, atLeastOnce()).validateModuleFile(anyObject()); order.verifyNoMoreInteractions(); }
@Test public void buildingViaFlagsAndBuilderHasSameResult_optionalBundleConfig() throws Exception { Path modulePath = createSimpleBaseModule(); Path bundleConfigJsonPath = tmpDir.resolve("BundleConfig.pb.json"); Files.write( bundleConfigJsonPath, ("{ \"compression\": { \"uncompressedGlob\": [\"foo\"] } }").getBytes(UTF_8)); BuildBundleCommand commandViaBuilder = BuildBundleCommand.builder() .setOutputPath(bundlePath) .setModulesPaths(ImmutableList.of(modulePath)) // Optional values. .setBundleConfig( BundleConfig.newBuilder() .setCompression(Compression.newBuilder().addUncompressedGlob("foo")) .build()) .build(); BuildBundleCommand commandViaFlags = BuildBundleCommand.fromFlags( new FlagParser() .parse( "--output=" + bundlePath, "--modules=" + modulePath, // Optional values. "--config=" + bundleConfigJsonPath)); assertThat(commandViaBuilder).isEqualTo(commandViaFlags); }
@Test public void bundleConfig_saved() throws Exception { Path module = createSimpleBaseModule(); // Any version supplied by the user is ignored and overwritten. BundleConfig bundleConfigFromUser = BundleConfigBuilder.create().setVersion("0.0.0").build(); BundleConfig bundleConfigInBundle = new BundleConfigBuilder(bundleConfigFromUser) .setVersion(BundleToolVersion.getCurrentVersion().toString()) .build(); assertThat(bundleConfigFromUser.getBundletool().getVersion()) .isNotEqualTo(bundleConfigInBundle.getBundletool().getVersion()); BuildBundleCommand.builder() .setModulesPaths(ImmutableList.of(module)) .setOutputPath(bundlePath) .setBundleConfig(bundleConfigFromUser) .build() .execute(); AppBundle appBundle = AppBundle.buildFromZip(new ZipFile(bundlePath.toFile())); assertThat(appBundle.getBundleConfig()).isEqualTo(bundleConfigInBundle); }
private static BundleConfig readBundleConfig(ZipFile bundleFile) { ZipEntry bundleConfigEntry = bundleFile.getEntry(BUNDLE_CONFIG_FILE_NAME); checkState(bundleConfigEntry != null, "File '%s' was not found.", BUNDLE_CONFIG_FILE_NAME); try (InputStream is = BufferedIo.inputStream(bundleFile, bundleConfigEntry)) { return BundleConfig.parseFrom(is); } catch (InvalidProtocolBufferException e) { throw ValidationException.builder() .withCause(e) .withMessage("Bundle config '%s' could not be parsed.", BUNDLE_CONFIG_FILE_NAME) .build(); } catch (IOException e) { throw CommandExecutionException.builder() .withCause(e) .withMessage("Error reading file '%s'.", BUNDLE_CONFIG_FILE_NAME) .build(); } }
private static BundleConfig parseBundleConfigJson(Path bundleConfigJsonPath) { BundleConfig.Builder bundleConfig = BundleConfig.newBuilder(); try (Reader bundleConfigReader = BufferedIo.reader(bundleConfigJsonPath)) { JsonFormat.parser().merge(bundleConfigReader, bundleConfig); } catch (InvalidProtocolBufferException e) { throw CommandExecutionException.builder() .withCause(e) .withMessage("The file '%s' is not a valid BundleConfig JSON file.", bundleConfigJsonPath) .build(); } catch (IOException e) { throw CommandExecutionException.builder() .withCause(e) .withMessage( "An error occurred while trying to read the file '%s'.", bundleConfigJsonPath) .build(); } return bundleConfig.build(); }
/** Creates a builder with the initial state identical to the given config. */ public BundleConfigBuilder(BundleConfig bundleConfig) { this.builder = bundleConfig.toBuilder(); }
public static AppBundle buildFromModules( ImmutableList<BundleModule> modules, BundleConfig bundleConfig, BundleMetadata bundleMetadata) { ImmutableSet<ResourceId> pinnedResourceIds = bundleConfig.getMasterResources().getResourceIdsList().stream() .map(ResourceId::create) .collect(toImmutableSet()); return new AppBundle( Maps.uniqueIndex(modules, BundleModule::getName), bundleConfig, bundleMetadata, pinnedResourceIds); }
private static BundleModule.Builder buildBundleModule(String moduleName) { return BundleModule.builder() .setName(BundleModuleName.create(moduleName)) .setBundleConfig(BundleConfig.getDefaultInstance()); } }
@Test public void bundleToolVersionSet() throws Exception { Path module = createSimpleBaseModule(); BuildBundleCommand.builder() .setModulesPaths(ImmutableList.of(module)) .setOutputPath(bundlePath) .build() .execute(); AppBundle appBundle = AppBundle.buildFromZip(new ZipFile(bundlePath.toFile())); assertThat(appBundle.getBundleConfig().getBundletool().getVersion()) .isEqualTo(BundleToolVersion.getCurrentVersion().toString()); }
@Override public void validateBundle(AppBundle bundle) { BundleConfig bundleConfig = bundle.getBundleConfig(); validateVersion(bundleConfig); validateCompression(bundleConfig.getCompression()); validateOptimizations(bundleConfig.getOptimizations()); validateMasterResources(bundleConfig, bundle); }
private static ZipBuilder createBasicZipBuilder(BundleConfig config) { ZipBuilder zipBuilder = new ZipBuilder(); zipBuilder.addFileWithContent(ZipPath.create("BundleConfig.pb"), config.toByteArray()); return zipBuilder; }
/** Creates default builder instance with minimal defaults pre-set. */ public static BundleConfigBuilder create() { return new BundleConfigBuilder(BundleConfig.getDefaultInstance()) // Populate required fields with sensible defaults. .setVersion(BundleToolVersion.getCurrentVersion().toString()); }