// Copyright (C) 2009 The Android Open Source Project // // 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.gerrit.pgm; import com.google.common.base.Joiner; import com.google.common.collect.Sets; import com.google.gerrit.common.IoUtil; import com.google.gerrit.common.PageLinks; import com.google.gerrit.common.PluginData; import com.google.gerrit.pgm.init.BaseInit; import com.google.gerrit.pgm.init.Browser; import com.google.gerrit.pgm.init.InitPlugins; import com.google.gerrit.pgm.init.api.ConsoleUI; import com.google.gerrit.pgm.util.ErrorLogFile; import com.google.gerrit.server.config.GerritServerConfigModule; import com.google.gerrit.server.config.SitePath; import com.google.gerrit.server.securestore.SecureStoreClassName; import com.google.gerrit.server.util.HostPlatform; import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Inject; import com.google.inject.Module; import com.google.inject.util.Providers; import java.io.IOException; import java.nio.file.Path; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Set; import org.kohsuke.args4j.Option; /** Initialize a new Gerrit installation. */ public class Init extends BaseInit { @Option( name = "--batch", aliases = {"-b"}, usage = "Batch mode; skip interactive prompting" ) private boolean batchMode; @Option(name = "--delete-caches", usage = "Delete all persistent caches without asking") private boolean deleteCaches; @Option(name = "--no-auto-start", usage = "Don't automatically start daemon after init") private boolean noAutoStart; @Option(name = "--skip-plugins", usage = "Don't install plugins") private boolean skipPlugins; @Option(name = "--list-plugins", usage = "List available plugins") private boolean listPlugins; @Option(name = "--install-plugin", usage = "Install given plugin without asking") private List<String> installPlugins; @Option(name = "--install-all-plugins", usage = "Install all plugins from war without asking") private boolean installAllPlugins; @Option( name = "--secure-store-lib", usage = "Path to jar providing SecureStore implementation class" ) private String secureStoreLib; @Option(name = "--dev", usage = "Setup site with default options suitable for developers") private boolean dev; @Option(name = "--skip-all-downloads", usage = "Don't download libraries") private boolean skipAllDownloads; @Option(name = "--skip-download", usage = "Don't download given library") private List<String> skippedDownloads; @Inject Browser browser; public Init() { super(new WarDistribution(), null); } public Init(Path sitePath) { super(sitePath, true, true, new WarDistribution(), null); batchMode = true; noAutoStart = true; } @Override protected boolean beforeInit(SiteInit init) throws Exception { ErrorLogFile.errorOnlyConsole(); if (!skipPlugins) { final List<PluginData> plugins = InitPlugins.listPluginsAndRemoveTempFiles(init.site, pluginsDistribution); ConsoleUI ui = ConsoleUI.getInstance(false); if (installAllPlugins && !nullOrEmpty(installPlugins)) { ui.message("Cannot use --install-plugin together with --install-all-plugins.\n"); return true; } verifyInstallPluginList(ui, plugins); if (listPlugins) { if (!plugins.isEmpty()) { ui.message("Available plugins:\n"); for (PluginData plugin : plugins) { ui.message(" * %s version %s\n", plugin.name, plugin.version); } } else { ui.message("No plugins found.\n"); } return true; } } return false; } @Override protected void afterInit(SiteRun run) throws Exception { List<Module> modules = new ArrayList<>(); modules.add( new AbstractModule() { @Override protected void configure() { bind(Path.class).annotatedWith(SitePath.class).toInstance(getSitePath()); bind(Browser.class); bind(String.class) .annotatedWith(SecureStoreClassName.class) .toProvider(Providers.of(getConfiguredSecureStoreClass())); } }); modules.add(new GerritServerConfigModule()); Guice.createInjector(modules).injectMembers(this); start(run); } @Override protected List<String> getInstallPlugins() { return installPlugins; } @Override protected boolean installAllPlugins() { return installAllPlugins; } @Override protected ConsoleUI getConsoleUI() { return ConsoleUI.getInstance(batchMode); } @Override protected boolean getAutoStart() { return !noAutoStart; } @Override protected boolean getDeleteCaches() { return deleteCaches; } @Override protected boolean skipPlugins() { return skipPlugins; } @Override protected boolean isDev() { return dev; } @Override protected boolean skipAllDownloads() { return skipAllDownloads; } @Override protected List<String> getSkippedDownloads() { return skippedDownloads != null ? skippedDownloads : Collections.<String>emptyList(); } @Override protected String getSecureStoreLib() { return secureStoreLib; } void start(SiteRun run) throws Exception { if (run.flags.autoStart) { if (HostPlatform.isWin32()) { System.err.println("Automatic startup not supported on Win32."); } else { startDaemon(run); if (!run.ui.isBatch()) { browser.open(PageLinks.ADMIN_PROJECTS); } } } } void startDaemon(SiteRun run) { String[] argv = {run.site.gerrit_sh.toAbsolutePath().toString(), "start"}; Process proc; try { System.err.println("Executing " + argv[0] + " " + argv[1]); proc = Runtime.getRuntime().exec(argv); } catch (IOException e) { System.err.println("error: cannot start Gerrit: " + e.getMessage()); return; } try { proc.getOutputStream().close(); } catch (IOException e) { // Ignored } IoUtil.copyWithThread(proc.getInputStream(), System.err); IoUtil.copyWithThread(proc.getErrorStream(), System.err); for (; ; ) { try { int rc = proc.waitFor(); if (rc != 0) { System.err.println("error: cannot start Gerrit: exit status " + rc); } break; } catch (InterruptedException e) { // retry } } } private void verifyInstallPluginList(ConsoleUI ui, List<PluginData> plugins) { if (nullOrEmpty(installPlugins) || nullOrEmpty(plugins)) { return; } Set<String> missing = Sets.newHashSet(installPlugins); plugins.stream().forEach(p -> missing.remove(p.name)); if (!missing.isEmpty()) { ui.message("Cannot find plugin(s): %s\n", Joiner.on(", ").join(missing)); listPlugins = true; } } private static boolean nullOrEmpty(List<?> list) { return list == null || list.isEmpty(); } }