193 "message.test-for-tool"), toolName, e.getMessage())); |
128 "message.test-for-tool"), toolName, e.getMessage())); |
194 return false; |
129 return false; |
195 } |
130 } |
196 } |
131 } |
197 |
132 |
198 @Override |
133 public LinuxRpmBundler() { |
199 public boolean validate(Map<String, ? super Object> params) |
134 super(PACKAGE_NAME); |
|
135 } |
|
136 |
|
137 @Override |
|
138 public void doValidate(Map<String, ? super Object> params) |
200 throws ConfigException { |
139 throws ConfigException { |
201 try { |
140 if (params == null) throw new ConfigException( |
202 if (params == null) throw new ConfigException( |
141 I18N.getString("error.parameters-null"), |
203 I18N.getString("error.parameters-null"), |
142 I18N.getString("error.parameters-null.advice")); |
204 I18N.getString("error.parameters-null.advice")); |
143 |
205 |
144 // validate presense of required tools |
206 // run basic validation to ensure requirements are met |
145 if (!testTool(TOOL_RPMBUILD, TOOL_RPMBUILD_MIN_VERSION)){ |
207 // we are not interested in return code, only possible exception |
146 throw new ConfigException( |
208 APP_BUNDLER.fetchFrom(params).validate(params); |
147 MessageFormat.format( |
209 |
148 I18N.getString("error.cannot-find-rpmbuild"), |
210 // validate presense of required tools |
149 TOOL_RPMBUILD_MIN_VERSION), |
211 if (!testTool(TOOL_RPMBUILD, TOOL_RPMBUILD_MIN_VERSION)){ |
150 MessageFormat.format( |
212 throw new ConfigException( |
151 I18N.getString("error.cannot-find-rpmbuild.advice"), |
213 MessageFormat.format( |
152 TOOL_RPMBUILD_MIN_VERSION)); |
214 I18N.getString("error.cannot-find-rpmbuild"), |
153 } |
215 TOOL_RPMBUILD_MIN_VERSION), |
154 } |
216 MessageFormat.format( |
155 |
217 I18N.getString("error.cannot-find-rpmbuild.advice"), |
156 @Override |
218 TOOL_RPMBUILD_MIN_VERSION)); |
157 protected File buildPackageBundle( |
219 } |
158 Map<String, String> replacementData, |
220 |
159 Map<String, ? super Object> params, File outputParentDir) throws |
221 // only one mime type per association, at least one file extension |
160 PackagerException, IOException { |
222 List<Map<String, ? super Object>> associations = |
161 |
223 FILE_ASSOCIATIONS.fetchFrom(params); |
162 Path specFile = specFile(params); |
224 if (associations != null) { |
|
225 for (int i = 0; i < associations.size(); i++) { |
|
226 Map<String, ? super Object> assoc = associations.get(i); |
|
227 List<String> mimes = FA_CONTENT_TYPE.fetchFrom(assoc); |
|
228 if (mimes == null || mimes.isEmpty()) { |
|
229 String msgKey = |
|
230 "error.no-content-types-for-file-association"; |
|
231 throw new ConfigException( |
|
232 MessageFormat.format(I18N.getString(msgKey), i), |
|
233 I18N.getString(msgKey + ".advice")); |
|
234 } else if (mimes.size() > 1) { |
|
235 String msgKey = |
|
236 "error.no-content-types-for-file-association"; |
|
237 throw new ConfigException( |
|
238 MessageFormat.format(I18N.getString(msgKey), i), |
|
239 I18N.getString(msgKey + ".advice")); |
|
240 } |
|
241 } |
|
242 } |
|
243 |
|
244 // bundle name has some restrictions |
|
245 // the string converter will throw an exception if invalid |
|
246 BUNDLE_NAME.getStringConverter().apply( |
|
247 BUNDLE_NAME.fetchFrom(params), params); |
|
248 |
|
249 return true; |
|
250 } catch (RuntimeException re) { |
|
251 if (re.getCause() instanceof ConfigException) { |
|
252 throw (ConfigException) re.getCause(); |
|
253 } else { |
|
254 throw new ConfigException(re); |
|
255 } |
|
256 } |
|
257 } |
|
258 |
|
259 private boolean prepareProto(Map<String, ? super Object> params) |
|
260 throws PackagerException, IOException { |
|
261 File appImage = StandardBundlerParam.getPredefinedAppImage(params); |
|
262 File appDir = null; |
|
263 |
|
264 // we either have an application image or need to build one |
|
265 if (appImage != null) { |
|
266 appDir = new File(RPM_IMAGE_DIR.fetchFrom(params), |
|
267 APP_NAME.fetchFrom(params)); |
|
268 // copy everything from appImage dir into appDir/name |
|
269 IOUtils.copyRecursive(appImage.toPath(), appDir.toPath()); |
|
270 } else { |
|
271 appDir = APP_BUNDLER.fetchFrom(params).doBundle(params, |
|
272 RPM_IMAGE_DIR.fetchFrom(params), true); |
|
273 } |
|
274 return appDir != null; |
|
275 } |
|
276 |
|
277 public File bundle(Map<String, ? super Object> params, |
|
278 File outdir) throws PackagerException { |
|
279 |
|
280 IOUtils.writableOutputDir(outdir.toPath()); |
|
281 |
|
282 File imageDir = RPM_IMAGE_DIR.fetchFrom(params); |
|
283 try { |
|
284 |
|
285 imageDir.mkdirs(); |
|
286 |
|
287 if (prepareProto(params) && prepareProjectConfig(params)) { |
|
288 return buildRPM(params, outdir); |
|
289 } |
|
290 return null; |
|
291 } catch (IOException ex) { |
|
292 Log.verbose(ex); |
|
293 throw new PackagerException(ex); |
|
294 } |
|
295 } |
|
296 |
|
297 private boolean prepareProjectConfig(Map<String, ? super Object> params) |
|
298 throws IOException { |
|
299 Map<String, String> data = createReplacementData(params); |
|
300 File rootDir = |
|
301 LinuxAppBundler.getRootDir(RPM_IMAGE_DIR.fetchFrom(params), params); |
|
302 File binDir = new File(rootDir, "bin"); |
|
303 |
|
304 // prepare installer icon |
|
305 File iconTarget = getConfig_IconFile(binDir, params); |
|
306 File icon = LinuxAppBundler.ICON_PNG.fetchFrom(params); |
|
307 if (!StandardBundlerParam.isRuntimeInstaller(params)) { |
|
308 if (icon == null || !icon.exists()) { |
|
309 fetchResource(iconTarget.getName(), |
|
310 I18N.getString("resource.menu-icon"), |
|
311 DEFAULT_ICON, |
|
312 iconTarget, |
|
313 VERBOSE.fetchFrom(params), |
|
314 RESOURCE_DIR.fetchFrom(params)); |
|
315 } else { |
|
316 fetchResource(iconTarget.getName(), |
|
317 I18N.getString("resource.menu-icon"), |
|
318 icon, |
|
319 iconTarget, |
|
320 VERBOSE.fetchFrom(params), |
|
321 RESOURCE_DIR.fetchFrom(params)); |
|
322 } |
|
323 } |
|
324 |
|
325 StringBuilder installScripts = new StringBuilder(); |
|
326 StringBuilder removeScripts = new StringBuilder(); |
|
327 for (Map<String, ? super Object> addLauncher : |
|
328 ADD_LAUNCHERS.fetchFrom(params)) { |
|
329 Map<String, String> addLauncherData = |
|
330 createReplacementData(addLauncher); |
|
331 addLauncherData.put("APPLICATION_FS_NAME", |
|
332 data.get("APPLICATION_FS_NAME")); |
|
333 addLauncherData.put("DESKTOP_MIMES", ""); |
|
334 |
|
335 // prepare desktop shortcut |
|
336 if (SHORTCUT_HINT.fetchFrom(params)) { |
|
337 try (Writer w = Files.newBufferedWriter( |
|
338 getConfig_DesktopShortcutFile(binDir, |
|
339 addLauncher).toPath())) { |
|
340 String content = preprocessTextResource( |
|
341 getConfig_DesktopShortcutFile(binDir, |
|
342 addLauncher).getName(), |
|
343 I18N.getString("resource.menu-shortcut-descriptor"), |
|
344 DEFAULT_DESKTOP_FILE_TEMPLATE, addLauncherData, |
|
345 VERBOSE.fetchFrom(params), |
|
346 RESOURCE_DIR.fetchFrom(params)); |
|
347 w.write(content); |
|
348 } |
|
349 } |
|
350 |
|
351 // prepare installer icon |
|
352 iconTarget = getConfig_IconFile(binDir, addLauncher); |
|
353 icon = LinuxAppBundler.ICON_PNG.fetchFrom(addLauncher); |
|
354 if (icon == null || !icon.exists()) { |
|
355 fetchResource(iconTarget.getName(), |
|
356 I18N.getString("resource.menu-icon"), |
|
357 DEFAULT_ICON, |
|
358 iconTarget, |
|
359 VERBOSE.fetchFrom(params), |
|
360 RESOURCE_DIR.fetchFrom(params)); |
|
361 } else { |
|
362 fetchResource(iconTarget.getName(), |
|
363 I18N.getString("resource.menu-icon"), |
|
364 icon, |
|
365 iconTarget, |
|
366 VERBOSE.fetchFrom(params), |
|
367 RESOURCE_DIR.fetchFrom(params)); |
|
368 } |
|
369 |
|
370 // post copying of desktop icon |
|
371 installScripts.append("xdg-desktop-menu install --novendor "); |
|
372 installScripts.append(LINUX_INSTALL_DIR.fetchFrom(params)); |
|
373 installScripts.append("/"); |
|
374 installScripts.append(data.get("APPLICATION_FS_NAME")); |
|
375 installScripts.append("/bin/"); |
|
376 installScripts.append(addLauncherData.get( |
|
377 "APPLICATION_LAUNCHER_FILENAME")); |
|
378 installScripts.append(".desktop\n"); |
|
379 |
|
380 // preun cleanup of desktop icon |
|
381 removeScripts.append("xdg-desktop-menu uninstall --novendor "); |
|
382 removeScripts.append(LINUX_INSTALL_DIR.fetchFrom(params)); |
|
383 removeScripts.append("/"); |
|
384 removeScripts.append(data.get("APPLICATION_FS_NAME")); |
|
385 removeScripts.append("/bin/"); |
|
386 removeScripts.append(addLauncherData.get( |
|
387 "APPLICATION_LAUNCHER_FILENAME")); |
|
388 removeScripts.append(".desktop\n"); |
|
389 |
|
390 } |
|
391 data.put("ADD_LAUNCHERS_INSTALL", installScripts.toString()); |
|
392 data.put("ADD_LAUNCHERS_REMOVE", removeScripts.toString()); |
|
393 |
|
394 StringBuilder cdsScript = new StringBuilder(); |
|
395 |
|
396 data.put("APP_CDS_CACHE", cdsScript.toString()); |
|
397 |
|
398 List<Map<String, ? super Object>> associations = |
|
399 FILE_ASSOCIATIONS.fetchFrom(params); |
|
400 data.put("FILE_ASSOCIATION_INSTALL", ""); |
|
401 data.put("FILE_ASSOCIATION_REMOVE", ""); |
|
402 data.put("DESKTOP_MIMES", ""); |
|
403 if (associations != null) { |
|
404 String mimeInfoFile = XDG_FILE_PREFIX.fetchFrom(params) |
|
405 + "-MimeInfo.xml"; |
|
406 StringBuilder mimeInfo = new StringBuilder( |
|
407 "<?xml version=\"1.0\"?>\n<mime-info xmlns=" |
|
408 +"'http://www.freedesktop.org/standards/shared-mime-info'>\n"); |
|
409 StringBuilder registrations = new StringBuilder(); |
|
410 StringBuilder deregistrations = new StringBuilder(); |
|
411 StringBuilder desktopMimes = new StringBuilder("MimeType="); |
|
412 boolean addedEntry = false; |
|
413 |
|
414 for (Map<String, ? super Object> assoc : associations) { |
|
415 // <mime-type type="application/x-vnd.awesome"> |
|
416 // <comment>Awesome document</comment> |
|
417 // <glob pattern="*.awesome"/> |
|
418 // <glob pattern="*.awe"/> |
|
419 // </mime-type> |
|
420 |
|
421 if (assoc == null) { |
|
422 continue; |
|
423 } |
|
424 |
|
425 String description = FA_DESCRIPTION.fetchFrom(assoc); |
|
426 File faIcon = FA_ICON.fetchFrom(assoc); |
|
427 List<String> extensions = FA_EXTENSIONS.fetchFrom(assoc); |
|
428 if (extensions == null) { |
|
429 Log.verbose(I18N.getString( |
|
430 "message.creating-association-with-null-extension")); |
|
431 } |
|
432 |
|
433 List<String> mimes = FA_CONTENT_TYPE.fetchFrom(assoc); |
|
434 if (mimes == null || mimes.isEmpty()) { |
|
435 continue; |
|
436 } |
|
437 String thisMime = mimes.get(0); |
|
438 String dashMime = thisMime.replace('/', '-'); |
|
439 |
|
440 mimeInfo.append(" <mime-type type='") |
|
441 .append(thisMime) |
|
442 .append("'>\n"); |
|
443 if (description != null && !description.isEmpty()) { |
|
444 mimeInfo.append(" <comment>") |
|
445 .append(description) |
|
446 .append("</comment>\n"); |
|
447 } |
|
448 |
|
449 if (extensions != null) { |
|
450 for (String ext : extensions) { |
|
451 mimeInfo.append(" <glob pattern='*.") |
|
452 .append(ext) |
|
453 .append("'/>\n"); |
|
454 } |
|
455 } |
|
456 |
|
457 mimeInfo.append(" </mime-type>\n"); |
|
458 if (!addedEntry) { |
|
459 registrations.append("xdg-mime install ") |
|
460 .append(LINUX_INSTALL_DIR.fetchFrom(params)) |
|
461 .append("/") |
|
462 .append(data.get("APPLICATION_FS_NAME")) |
|
463 .append("/bin/") |
|
464 .append(mimeInfoFile) |
|
465 .append("\n"); |
|
466 |
|
467 deregistrations.append("xdg-mime uninstall ") |
|
468 .append(LINUX_INSTALL_DIR.fetchFrom(params)) |
|
469 .append("/") |
|
470 .append(data.get("APPLICATION_FS_NAME")) |
|
471 .append("/bin/") |
|
472 .append(mimeInfoFile) |
|
473 .append("\n"); |
|
474 addedEntry = true; |
|
475 } else { |
|
476 desktopMimes.append(";"); |
|
477 } |
|
478 desktopMimes.append(thisMime); |
|
479 |
|
480 if (faIcon != null && faIcon.exists()) { |
|
481 int size = getSquareSizeOfImage(faIcon); |
|
482 |
|
483 if (size > 0) { |
|
484 File target = new File(binDir, |
|
485 APP_NAME.fetchFrom(params) |
|
486 + "_fa_" + faIcon.getName()); |
|
487 IOUtils.copyFile(faIcon, target); |
|
488 |
|
489 // xdg-icon-resource install --context mimetypes |
|
490 // --size 64 awesomeapp_fa_1.png |
|
491 // application-x.vnd-awesome |
|
492 registrations.append( |
|
493 "xdg-icon-resource install " |
|
494 + "--context mimetypes --size ") |
|
495 .append(size) |
|
496 .append(" ") |
|
497 .append(LINUX_INSTALL_DIR.fetchFrom(params)) |
|
498 .append("/") |
|
499 .append(data.get("APPLICATION_FS_NAME")) |
|
500 .append("/") |
|
501 .append(target.getName()) |
|
502 .append(" ") |
|
503 .append(dashMime) |
|
504 .append("\n"); |
|
505 |
|
506 // xdg-icon-resource uninstall --context mimetypes |
|
507 // --size 64 awesomeapp_fa_1.png |
|
508 // application-x.vnd-awesome |
|
509 deregistrations.append( |
|
510 "xdg-icon-resource uninstall " |
|
511 + "--context mimetypes --size ") |
|
512 .append(size) |
|
513 .append(" ") |
|
514 .append(LINUX_INSTALL_DIR.fetchFrom(params)) |
|
515 .append("/") |
|
516 .append(data.get("APPLICATION_FS_NAME")) |
|
517 .append("/") |
|
518 .append(target.getName()) |
|
519 .append(" ") |
|
520 .append(dashMime) |
|
521 .append("\n"); |
|
522 } |
|
523 } |
|
524 } |
|
525 mimeInfo.append("</mime-info>"); |
|
526 |
|
527 if (addedEntry) { |
|
528 try (Writer w = Files.newBufferedWriter( |
|
529 new File(binDir, mimeInfoFile).toPath())) { |
|
530 w.write(mimeInfo.toString()); |
|
531 } |
|
532 data.put("FILE_ASSOCIATION_INSTALL", registrations.toString()); |
|
533 data.put("FILE_ASSOCIATION_REMOVE", deregistrations.toString()); |
|
534 data.put("DESKTOP_MIMES", desktopMimes.toString()); |
|
535 } |
|
536 } |
|
537 |
|
538 if (!StandardBundlerParam.isRuntimeInstaller(params)) { |
|
539 // prepare desktop shortcut |
|
540 if (SHORTCUT_HINT.fetchFrom(params)) { |
|
541 try (Writer w = Files.newBufferedWriter( |
|
542 getConfig_DesktopShortcutFile(binDir, params).toPath())) { |
|
543 String content = preprocessTextResource( |
|
544 getConfig_DesktopShortcutFile(binDir, |
|
545 params).getName(), |
|
546 I18N.getString("resource.menu-shortcut-descriptor"), |
|
547 DEFAULT_DESKTOP_FILE_TEMPLATE, data, |
|
548 VERBOSE.fetchFrom(params), |
|
549 RESOURCE_DIR.fetchFrom(params)); |
|
550 w.write(content); |
|
551 } |
|
552 } |
|
553 } |
|
554 |
163 |
555 // prepare spec file |
164 // prepare spec file |
556 try (Writer w = Files.newBufferedWriter( |
165 Files.createDirectories(specFile.getParent()); |
557 getConfig_SpecFile(params).toPath())) { |
166 try (Writer w = Files.newBufferedWriter(specFile)) { |
558 String content = preprocessTextResource( |
167 String content = preprocessTextResource( |
559 getConfig_SpecFile(params).getName(), |
168 specFile.getFileName().toString(), |
560 I18N.getString("resource.rpm-spec-file"), |
169 I18N.getString("resource.rpm-spec-file"), |
561 DEFAULT_SPEC_TEMPLATE, data, |
170 DEFAULT_SPEC_TEMPLATE, replacementData, |
562 VERBOSE.fetchFrom(params), |
171 VERBOSE.fetchFrom(params), |
563 RESOURCE_DIR.fetchFrom(params)); |
172 RESOURCE_DIR.fetchFrom(params)); |
564 w.write(content); |
173 w.write(content); |
565 } |
174 } |
566 |
175 |
567 return true; |
176 return buildRPM(params, outputParentDir); |
568 } |
177 } |
569 |
178 |
570 private Map<String, String> createReplacementData( |
179 @Override |
|
180 protected Map<String, String> createReplacementData( |
571 Map<String, ? super Object> params) throws IOException { |
181 Map<String, ? super Object> params) throws IOException { |
572 Map<String, String> data = new HashMap<>(); |
182 Map<String, String> data = new HashMap<>(); |
573 String launcher = LinuxAppImageBuilder.getLauncherRelativePath(params); |
183 |
574 |
184 data.put("APPLICATION_DIRECTORY", Path.of(LINUX_INSTALL_DIR.fetchFrom( |
575 data.put("APPLICATION_NAME", APP_NAME.fetchFrom(params)); |
185 params), PACKAGE_NAME.fetchFrom(params)).toString()); |
576 data.put("APPLICATION_FS_NAME", APP_NAME.fetchFrom(params)); |
|
577 data.put("APPLICATION_PACKAGE", BUNDLE_NAME.fetchFrom(params)); |
|
578 data.put("APPLICATION_VENDOR", VENDOR.fetchFrom(params)); |
|
579 data.put("APPLICATION_VERSION", VERSION.fetchFrom(params)); |
|
580 data.put("APPLICATION_RELEASE", RELEASE.fetchFrom(params)); |
|
581 data.put("APPLICATION_LAUNCHER_FILENAME", launcher); |
|
582 data.put("INSTALLATION_DIRECTORY", LINUX_INSTALL_DIR.fetchFrom(params)); |
|
583 data.put("XDG_PREFIX", XDG_FILE_PREFIX.fetchFrom(params)); |
|
584 data.put("DEPLOY_BUNDLE_CATEGORY", MENU_GROUP.fetchFrom(params)); |
|
585 data.put("APPLICATION_DESCRIPTION", DESCRIPTION.fetchFrom(params)); |
|
586 data.put("APPLICATION_SUMMARY", APP_NAME.fetchFrom(params)); |
186 data.put("APPLICATION_SUMMARY", APP_NAME.fetchFrom(params)); |
587 data.put("APPLICATION_LICENSE_TYPE", LICENSE_TYPE.fetchFrom(params)); |
187 data.put("APPLICATION_LICENSE_TYPE", LICENSE_TYPE.fetchFrom(params)); |
588 |
188 data.put("APPLICATION_LICENSE_FILE", Optional.ofNullable( |
589 String licenseFile = LICENSE_FILE.fetchFrom(params); |
189 LICENSE_FILE.fetchFrom(params)).orElse("")); |
590 if (licenseFile == null) { |
190 data.put("APPLICATION_GROUP", Optional.ofNullable( |
591 licenseFile = ""; |
191 GROUP.fetchFrom(params)).orElse("")); |
592 } |
192 |
593 data.put("APPLICATION_LICENSE_FILE", licenseFile); |
|
594 |
|
595 String group = GROUP.fetchFrom(params); |
|
596 if (group == null) { |
|
597 group = ""; |
|
598 } |
|
599 data.put("APPLICATION_GROUP", group); |
|
600 |
|
601 String deps = LINUX_PACKAGE_DEPENDENCIES.fetchFrom(params); |
|
602 data.put("PACKAGE_DEPENDENCIES", |
|
603 deps.isEmpty() ? "" : "Requires: " + deps); |
|
604 data.put("RUNTIME_INSTALLER", "" + |
|
605 StandardBundlerParam.isRuntimeInstaller(params)); |
|
606 return data; |
193 return data; |
607 } |
194 } |
608 |
195 |
609 private File getConfig_DesktopShortcutFile(File rootDir, |
196 private Path specFile(Map<String, ? super Object> params) { |
610 Map<String, ? super Object> params) { |
197 return TEMP_ROOT.fetchFrom(params).toPath().resolve(Path.of("SPECS", |
611 return new File(rootDir, APP_NAME.fetchFrom(params) + ".desktop"); |
198 PACKAGE_NAME.fetchFrom(params) + ".spec")); |
612 } |
|
613 |
|
614 private File getConfig_IconFile(File rootDir, |
|
615 Map<String, ? super Object> params) { |
|
616 return new File(rootDir, APP_NAME.fetchFrom(params) + ".png"); |
|
617 } |
|
618 |
|
619 private File getConfig_SpecFile(Map<String, ? super Object> params) { |
|
620 return new File(RPM_IMAGE_DIR.fetchFrom(params), |
|
621 APP_NAME.fetchFrom(params) + ".spec"); |
|
622 } |
199 } |
623 |
200 |
624 private File buildRPM(Map<String, ? super Object> params, |
201 private File buildRPM(Map<String, ? super Object> params, |
625 File outdir) throws IOException { |
202 File outdir) throws IOException { |
626 Log.verbose(MessageFormat.format(I18N.getString( |
203 Log.verbose(MessageFormat.format(I18N.getString( |
627 "message.outputting-bundle-location"), |
204 "message.outputting-bundle-location"), |
628 outdir.getAbsolutePath())); |
205 outdir.getAbsolutePath())); |
629 |
206 |
630 File broot = new File(TEMP_ROOT.fetchFrom(params), "rmpbuildroot"); |
207 PlatformPackage thePackage = createMetaPackage(params); |
631 |
|
632 outdir.mkdirs(); |
|
633 |
208 |
634 //run rpmbuild |
209 //run rpmbuild |
635 ProcessBuilder pb = new ProcessBuilder( |
210 ProcessBuilder pb = new ProcessBuilder( |
636 TOOL_RPMBUILD, |
211 TOOL_RPMBUILD, |
637 "-bb", getConfig_SpecFile(params).getAbsolutePath(), |
212 "-bb", specFile(params).toAbsolutePath().toString(), |
638 "--define", "%_sourcedir " |
213 "--define", String.format("%%_sourcedir %s", thePackage.sourceRoot()), |
639 + RPM_IMAGE_DIR.fetchFrom(params).getAbsolutePath(), |
|
640 // save result to output dir |
214 // save result to output dir |
641 "--define", "%_rpmdir " + outdir.getAbsolutePath(), |
215 "--define", String.format("%%_rpmdir %s", outdir.getAbsolutePath()), |
642 // do not use other system directories to build as current user |
216 // do not use other system directories to build as current user |
643 "--define", "%_topdir " + broot.getAbsolutePath() |
217 "--define", String.format("%%_topdir %s", |
|
218 TEMP_ROOT.fetchFrom(params).toPath().toAbsolutePath()) |
644 ); |
219 ); |
645 pb = pb.directory(RPM_IMAGE_DIR.fetchFrom(params)); |
|
646 IOUtils.exec(pb); |
220 IOUtils.exec(pb); |
647 |
221 |
648 Log.verbose(MessageFormat.format( |
222 Log.verbose(MessageFormat.format( |
649 I18N.getString("message.output-bundle-location"), |
223 I18N.getString("message.output-bundle-location"), |
650 outdir.getAbsolutePath())); |
224 outdir.getAbsolutePath())); |