Moving dependencies to child module.

Instead of getting all dependencies at parent Maven module
they are now defined at child level.
This allows to only include the ones effectively needed
and avoid duplications when using shaded jars.

Adding as well a copy of the Gerrit InitStep interface
as it is missing in the Gerrit API package.

Change-Id: I8c8edbc05599d1e507d269baf5d95f32b99870e7
diff --git a/github-oauth/pom.xml b/github-oauth/pom.xml
index b92be3e..5d9f0c1 100644
--- a/github-oauth/pom.xml
+++ b/github-oauth/pom.xml
@@ -14,8 +14,9 @@
 See the License for the specific language governing permissions and
 limitations under the License.
 -->
-<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
-    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+<project
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
+  xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <modelVersion>4.0.0</modelVersion>
   <parent>
     <groupId>com.googlesource.gerrit.plugins.github</groupId>
@@ -29,8 +30,8 @@
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
   </properties>
   <build>
-  <plugins>
-        <plugin>
+    <plugins>
+      <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-shade-plugin</artifactId>
         <version>1.6</version>
@@ -45,7 +46,6 @@
               <exclude>log4j:log4j:*</exclude>
               <exclude>commons-lang:*:*</exclude>
               <exclude>commons-codec:*:*</exclude>
-              <exclude>commons-io:*:*</exclude>
               <exclude>com.google.guava:*</exclude>
             </excludes>
           </artifactSet>
@@ -61,4 +61,58 @@
       </plugin>
     </plugins>
   </build>
+  <dependencies>
+    <dependency>
+      <groupId>com.google.gerrit</groupId>
+      <artifactId>gerrit-plugin-api</artifactId>
+      <version>${project.version}</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>javax.servlet</groupId>
+      <artifactId>javax.servlet-api</artifactId>
+      <version>3.0.1</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>com.google.inject</groupId>
+      <artifactId>guice</artifactId>
+      <version>3.0</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>com.google.guava</groupId>
+      <artifactId>guava</artifactId>
+      <version>14.0</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+      <version>1.7.5</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-log4j12</artifactId>
+      <version>1.7.5</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>log4j</groupId>
+      <artifactId>log4j</artifactId>
+      <version>1.2.17</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.jenkins-ci.plugins</groupId>
+      <artifactId>github-api</artifactId>
+      <version>1.40</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.httpcomponents</groupId>
+      <artifactId>httpclient</artifactId>
+      <version>4.2.5</version>
+    </dependency>
+  </dependencies>
 </project>
diff --git a/github-plugin/pom.xml b/github-plugin/pom.xml
index b1bf14b..83e7e83 100644
--- a/github-plugin/pom.xml
+++ b/github-plugin/pom.xml
@@ -36,27 +36,54 @@
     <plugins>

       <plugin>

         <groupId>org.apache.maven.plugins</groupId>

-        <artifactId>maven-jar-plugin</artifactId>

-        <version>2.4</version>

+        <artifactId>maven-shade-plugin</artifactId>

+        <version>1.6</version>

         <configuration>

-          <archive>

-            <manifestEntries>

-              <Gerrit-Module>com.googlesource.gerrit.plugins.github.Module</Gerrit-Module>

-              <Gerrit-HttpModule>com.googlesource.gerrit.plugins.github.HttpModule</Gerrit-HttpModule>

-              <Gerrit-InitStep>com.googlesource.gerrit.plugins.github.InitGitHub</Gerrit-InitStep>

+          <promoteTransitiveDependencies>true</promoteTransitiveDependencies>

+          <artifactSet>

+            <excludes>

+              <exclude>com.google.*:*</exclude>

+              <exclude>javax.inject:*:*</exclude>

+              <exclude>aopalliance:aopalliance:*</exclude>

+              <exclude>org.slf4j:*</exclude>

+              <exclude>log4j:log4j:*</exclude>

+              <exclude>commons-lang:*:*</exclude>

+              <exclude>commons-codec:*:*</exclude>

+              <exclude>commons-io:*:*</exclude>

+              <exclude>com.google.guava:*</exclude>

 

-              <Implementation-Vendor>GerritForge</Implementation-Vendor>

-              <Implementation-URL>http://www.gerritforge.com</Implementation-URL>

+            </excludes>

+          </artifactSet>

+          <transformers>

+            <transformer

+              implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">

+              <manifestEntries>

+                <Gerrit-Module>com.googlesource.gerrit.plugins.github.Module</Gerrit-Module>

+                <Gerrit-HttpModule>com.googlesource.gerrit.plugins.github.HttpModule</Gerrit-HttpModule>

+                <Gerrit-InitStep>com.googlesource.gerrit.plugins.github.InitGitHub</Gerrit-InitStep>

 

-              <Implementation-Title>${Gerrit-ApiType}

-                ${project.artifactId}</Implementation-Title>

-              <Implementation-Version>${project.version}</Implementation-Version>

+                <Implementation-Vendor>GerritForge</Implementation-Vendor>

+                <Implementation-URL>http://www.gerritforge.com</Implementation-URL>

 

-              <Gerrit-ApiType>${Gerrit-ApiType}</Gerrit-ApiType>

-              <Gerrit-ApiVersion>${Gerrit-ApiVersion}</Gerrit-ApiVersion>

-            </manifestEntries>

-          </archive>

+                <Implementation-Title>${Gerrit-ApiType}

+                  ${project.artifactId}</Implementation-Title>

+                <Implementation-Version>${project.version}</Implementation-Version>

+

+                <Gerrit-ApiType>${Gerrit-ApiType}</Gerrit-ApiType>

+                <Gerrit-ApiVersion>${Gerrit-ApiVersion}</Gerrit-ApiVersion>

+              </manifestEntries>

+            </transformer>

+          </transformers>

+

         </configuration>

+        <executions>

+          <execution>

+            <phase>package</phase>

+            <goals>

+              <goal>shade</goal>

+            </goals>

+          </execution>

+        </executions>

       </plugin>

 

       <plugin>

@@ -79,20 +106,23 @@
       <version>${Gerrit-ApiVersion}</version>

       <scope>provided</scope>

     </dependency>

-

     <dependency>

       <groupId>junit</groupId>

       <artifactId>junit</artifactId>

       <version>4.8.1</version>

       <scope>test</scope>

     </dependency>

-

     <dependency>

       <groupId>${project.groupId}</groupId>

       <artifactId>github-oauth</artifactId>

       <version>${project.version}</version>

     </dependency>

-

+    <dependency>

+      <groupId>javax.servlet</groupId>

+      <artifactId>javax.servlet-api</artifactId>

+      <version>3.0.1</version>

+      <scope>provided</scope>

+    </dependency>

   </dependencies>

 

   <repositories>

diff --git a/github-plugin/src/main/java/com/google/gerrit/pgm/init/InitFlags.java b/github-plugin/src/main/java/com/google/gerrit/pgm/init/InitFlags.java
new file mode 100644
index 0000000..adbb03a
--- /dev/null
+++ b/github-plugin/src/main/java/com/google/gerrit/pgm/init/InitFlags.java
@@ -0,0 +1,52 @@
+// 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.init;
+
+import com.google.gerrit.server.config.SitePaths;
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+
+import org.eclipse.jgit.errors.ConfigInvalidException;
+import org.eclipse.jgit.storage.file.FileBasedConfig;
+import org.eclipse.jgit.util.FS;
+
+import java.io.IOException;
+import java.util.List;
+
+/** Global variables used by the 'init' command. */
+@Singleton
+public class InitFlags {
+  /** Recursively delete the site path if initialization fails. */
+  public boolean deleteOnFailure;
+
+  /** Run the daemon (and open the web UI in a browser) after initialization. */
+  public boolean autoStart;
+
+  public final FileBasedConfig cfg;
+  public final FileBasedConfig sec;
+  public final List<String> installPlugins;
+
+  @Inject
+  InitFlags(final SitePaths site,
+      final @InstallPlugins List<String> installPlugins) throws IOException,
+      ConfigInvalidException {
+    this.installPlugins = installPlugins;
+    cfg = new FileBasedConfig(site.gerrit_config, FS.DETECTED);
+    sec = new FileBasedConfig(site.secure_config, FS.DETECTED);
+
+    cfg.load();
+    sec.load();
+  }
+}
diff --git a/github-plugin/src/main/java/com/google/gerrit/pgm/init/InitStep.java b/github-plugin/src/main/java/com/google/gerrit/pgm/init/InitStep.java
new file mode 100644
index 0000000..4fa3f90
--- /dev/null
+++ b/github-plugin/src/main/java/com/google/gerrit/pgm/init/InitStep.java
@@ -0,0 +1,20 @@
+// 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.init;
+
+/** A single step in the site initialization process. */
+public interface InitStep {
+  public void run() throws Exception;
+}
diff --git a/github-plugin/src/main/java/com/google/gerrit/pgm/init/InstallPlugins.java b/github-plugin/src/main/java/com/google/gerrit/pgm/init/InstallPlugins.java
new file mode 100644
index 0000000..73db6f5
--- /dev/null
+++ b/github-plugin/src/main/java/com/google/gerrit/pgm/init/InstallPlugins.java
@@ -0,0 +1,25 @@
+// Copyright (C) 2013 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.init;
+
+import com.google.inject.BindingAnnotation;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@BindingAnnotation
+@Retention(RetentionPolicy.RUNTIME)
+public @interface InstallPlugins {
+}
diff --git a/github-plugin/src/main/java/com/google/gerrit/pgm/init/Section.java b/github-plugin/src/main/java/com/google/gerrit/pgm/init/Section.java
new file mode 100644
index 0000000..387b93a
--- /dev/null
+++ b/github-plugin/src/main/java/com/google/gerrit/pgm/init/Section.java
@@ -0,0 +1,196 @@
+// 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.init;
+
+import com.google.gerrit.pgm.util.ConsoleUI;
+import com.google.gerrit.server.config.ConfigUtil;
+import com.google.gerrit.server.config.SitePaths;
+import com.google.inject.Inject;
+import com.google.inject.assistedinject.Assisted;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Set;
+
+import javax.annotation.Nullable;
+
+/** Helper to edit a section of the configuration files. */
+public class Section {
+  public interface Factory {
+    Section get(@Assisted("section") String section,
+        @Assisted("subsection") String subsection);
+  }
+
+  private final InitFlags flags;
+  private final SitePaths site;
+  private final ConsoleUI ui;
+  private final String section;
+  private final String subsection;
+
+  @Inject
+  public Section(final InitFlags flags, final SitePaths site,
+      final ConsoleUI ui, @Assisted("section") final String section,
+      @Assisted("subsection") @Nullable final String subsection) {
+    this.flags = flags;
+    this.site = site;
+    this.ui = ui;
+    this.section = section;
+    this.subsection = subsection;
+  }
+
+  String get(String name) {
+    return flags.cfg.getString(section, null, name);
+  }
+
+  public void set(final String name, final String value) {
+    final ArrayList<String> all = new ArrayList<String>();
+    all.addAll(Arrays.asList(flags.cfg.getStringList(section, subsection, name)));
+
+    if (value != null) {
+      if (all.size() == 0 || all.size() == 1) {
+        flags.cfg.setString(section, subsection, name, value);
+      } else {
+        all.set(0, value);
+        flags.cfg.setStringList(section, subsection, name, all);
+      }
+
+    } else if (all.size() == 0) {
+    } else if (all.size() == 1) {
+      flags.cfg.unset(section, subsection, name);
+    } else {
+      all.remove(0);
+      flags.cfg.setStringList(section, subsection, name, all);
+    }
+  }
+
+  public <T extends Enum<?>> void set(final String name, final T value) {
+    if (value != null) {
+      set(name, value.name());
+    } else {
+      unset(name);
+    }
+  }
+
+  public void unset(String name) {
+    set(name, (String) null);
+  }
+
+  public String string(final String title, final String name, final String dv) {
+    return string(title, name, dv, false);
+  }
+
+  public String string(final String title, final String name, final String dv,
+      final boolean nullIfDefault) {
+    final String ov = get(name);
+    String nv = ui.readString(ov != null ? ov : dv, "%s", title);
+    if (nullIfDefault && nv == dv) {
+      nv = null;
+    }
+    if (!eq(ov, nv)) {
+      set(name, nv);
+    }
+    return nv;
+  }
+
+  public File path(final String title, final String name, final String defValue) {
+    return site.resolve(string(title, name, defValue));
+  }
+
+  public <T extends Enum<?>> T select(final String title, final String name,
+      final T defValue) {
+    return select(title, name, defValue, false);
+  }
+
+  public <T extends Enum<?>> T select(final String title, final String name,
+      final T defValue, final boolean nullIfDefault) {
+    final boolean set = get(name) != null;
+    T oldValue = ConfigUtil.getEnum(flags.cfg, section, subsection, name, defValue);
+    T newValue = ui.readEnum(oldValue, "%s", title);
+    if (nullIfDefault && newValue == defValue) {
+      newValue = null;
+    }
+    if (!set || oldValue != newValue) {
+      if (newValue != null) {
+        set(name, newValue);
+      } else {
+        unset(name);
+      }
+    }
+    return newValue;
+  }
+
+  public String select(final String title, final String name, final String dv,
+      Set<String> allowedValues) {
+    final String ov = get(name);
+    String nv = ui.readString(ov != null ? ov : dv, allowedValues, "%s", title);
+    if (!eq(ov, nv)) {
+      set(name, nv);
+    }
+    return nv;
+  }
+
+  public String password(final String username, final String password) {
+    final String ov = getSecure(password);
+
+    String user = flags.sec.getString(section, subsection, username);
+    if (user == null) {
+      user = get(username);
+    }
+
+    if (user == null) {
+      flags.sec.unset(section, subsection, password);
+      return null;
+    }
+
+    if (ov != null) {
+      // If the user already has a password stored, try to reuse it
+      // rather than prompting for a whole new one.
+      //
+      if (ui.isBatch() || !ui.yesno(false, "Change %s's password", user)) {
+        return ov;
+      }
+    }
+
+    final String nv = ui.password("%s's password", user);
+    if (!eq(ov, nv)) {
+      setSecure(password, nv);
+    }
+    return nv;
+  }
+
+  public String getSecure(String name) {
+    return flags.sec.getString(section, subsection, name);
+  }
+
+  public void setSecure(String name, String value) {
+    if (value != null) {
+      flags.sec.setString(section, subsection, name, value);
+    } else {
+      flags.sec.unset(section, subsection, name);
+    }
+  }
+
+  String getName() {
+    return section;
+  }
+
+  private static boolean eq(final String a, final String b) {
+    if (a == null && b == null) {
+      return true;
+    }
+    return a != null ? a.equals(b) : false;
+  }
+}
diff --git a/github-plugin/src/main/java/com/google/gerrit/pgm/util/ConsoleUI.java b/github-plugin/src/main/java/com/google/gerrit/pgm/util/ConsoleUI.java
new file mode 100644
index 0000000..e8cf0ab
--- /dev/null
+++ b/github-plugin/src/main/java/com/google/gerrit/pgm/util/ConsoleUI.java
@@ -0,0 +1,295 @@
+// 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.util;
+
+import static org.eclipse.jgit.util.StringUtils.equalsIgnoreCase;
+
+import java.io.Console;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Set;
+
+/** Console based interaction with the invoking user. */
+public abstract class ConsoleUI {
+  /** Get a UI instance, assuming interactive mode. */
+  public static ConsoleUI getInstance() {
+    return getInstance(false);
+  }
+
+  /** Get a UI instance, possibly forcing batch mode. */
+  public static ConsoleUI getInstance(final boolean batchMode) {
+    Console console = batchMode ? null : System.console();
+    return console != null ? new Interactive(console) : new Batch();
+  }
+
+  /** Constructs an exception indicating the user aborted the operation. */
+  protected static Die abort() {
+    return new Die("aborted by user");
+  }
+
+  /** Obtain all values from an enumeration. */
+  @SuppressWarnings("unchecked")
+  protected static <T extends Enum<?>> T[] all(final T value) {
+    try {
+      return (T[]) value.getClass().getMethod("values").invoke(null);
+    } catch (IllegalArgumentException e) {
+      throw new IllegalArgumentException("Cannot obtain enumeration values", e);
+    } catch (SecurityException e) {
+      throw new IllegalArgumentException("Cannot obtain enumeration values", e);
+    } catch (IllegalAccessException e) {
+      throw new IllegalArgumentException("Cannot obtain enumeration values", e);
+    } catch (InvocationTargetException e) {
+      throw new IllegalArgumentException("Cannot obtain enumeration values", e);
+    } catch (NoSuchMethodException e) {
+      throw new IllegalArgumentException("Cannot obtain enumeration values", e);
+    }
+  }
+
+  /** @return true if this is a batch UI that has no user interaction. */
+  public abstract boolean isBatch();
+
+  /** Display a header message before a series of prompts. */
+  public abstract void header(String fmt, Object... args);
+
+  /** Display a message. */
+  public abstract void message(String fmt, Object... args);
+
+  /** Request the user to answer a yes/no question. */
+  public abstract boolean yesno(Boolean def, String fmt, Object... args);
+
+  /** Prints a message asking the user to let us know when its safe to continue. */
+  public abstract void waitForUser();
+
+  /** Prompt the user for a string, suggesting a default, and returning choice. */
+  public abstract String readString(String def, String fmt, Object... args);
+
+  /** Prompt the user to make a choice from an allowed list of values. */
+  public abstract String readString(String def, Set<String> allowedValues,
+      String fmt, Object... args);
+
+  /** Prompt the user for an integer value, suggesting a default. */
+  public int readInt(int def, String fmt, Object... args) {
+    for (;;) {
+      String p = readString(String.valueOf(def), fmt, args);
+      try {
+        return Integer.parseInt(p.trim(), 10);
+      } catch (NumberFormatException e) {
+        System.err.println("error: Invalid integer format: " + p.trim());
+      }
+    }
+  }
+
+  /** Prompt the user for a password, returning the string; null if blank. */
+  public abstract String password(String fmt, Object... args);
+
+  /** Prompt the user to make a choice from an enumeration's values. */
+  public abstract <T extends Enum<?>> T readEnum(T def, String fmt,
+      Object... args);
+
+  private static class Interactive extends ConsoleUI {
+    private final Console console;
+
+    Interactive(final Console console) {
+      this.console = console;
+    }
+
+    @Override
+    public boolean isBatch() {
+      return false;
+    }
+
+    @Override
+    public boolean yesno(Boolean def, String fmt, Object... args) {
+      final String prompt = String.format(fmt, args);
+      for (;;) {
+        String y = "y";
+        String n = "n";
+        if (def != null) {
+          if (def) {
+            y = "Y";
+          } else {
+            n = "N";
+          }
+        }
+
+        String yn = console.readLine("%-30s [%s/%s]? ", prompt, y, n);
+        if (yn == null) {
+          throw abort();
+        }
+        yn = yn.trim();
+        if (def != null && yn.isEmpty()) {
+          return def;
+        }
+        if (yn.equalsIgnoreCase("y") || yn.equalsIgnoreCase("yes")) {
+          return true;
+        }
+        if (yn.equalsIgnoreCase("n") || yn.equalsIgnoreCase("no")) {
+          return false;
+        }
+      }
+    }
+
+    @Override
+    public void waitForUser() {
+      if (console.readLine("Press enter to continue ") == null) {
+        throw abort();
+      }
+    }
+
+    @Override
+    public String readString(String def, String fmt, Object... args) {
+      final String prompt = String.format(fmt, args);
+      String r;
+      if (def != null) {
+        r = console.readLine("%-30s [%s]: ", prompt, def);
+      } else {
+        r = console.readLine("%-30s : ", prompt);
+      }
+      if (r == null) {
+        throw abort();
+      }
+      r = r.trim();
+      if (r.isEmpty()) {
+        return def;
+      }
+      return r;
+    }
+
+    @Override
+    public String readString(String def, Set<String> allowedValues, String fmt,
+        Object... args) {
+      for (;;) {
+        String r = readString(def, fmt, args);
+        if (allowedValues.contains(r.toLowerCase())) {
+          return r.toLowerCase();
+        }
+        if (!"?".equals(r)) {
+          console.printf("error: '%s' is not a valid choice\n", r);
+        }
+        console.printf("       Supported options are:\n");
+        for (final String v : allowedValues) {
+          console.printf("         %s\n", v.toString().toLowerCase());
+        }
+      }
+    }
+
+    @Override
+    public String password(String fmt, Object... args) {
+      final String prompt = String.format(fmt, args);
+      for (;;) {
+        final char[] a1 = console.readPassword("%-30s : ", prompt);
+        if (a1 == null) {
+          throw abort();
+        }
+
+        final char[] a2 = console.readPassword("%30s : ", "confirm password");
+        if (a2 == null) {
+          throw abort();
+        }
+
+        final String s1 = new String(a1);
+        final String s2 = new String(a2);
+        if (!s1.equals(s2)) {
+          console.printf("error: Passwords did not match; try again\n");
+          continue;
+        }
+        return !s1.isEmpty() ? s1 : null;
+      }
+    }
+
+    @Override
+    public <T extends Enum<?>> T readEnum(T def, String fmt, Object... args) {
+      final String prompt = String.format(fmt, args);
+      final T[] options = all(def);
+      for (;;) {
+        String r = console.readLine("%-30s [%s/?]: ", prompt, def.toString());
+        if (r == null) {
+          throw abort();
+        }
+        r = r.trim();
+        if (r.isEmpty()) {
+          return def;
+        }
+        for (final T e : options) {
+          if (equalsIgnoreCase(e.toString(), r)) {
+            return e;
+          }
+        }
+        if (!"?".equals(r)) {
+          console.printf("error: '%s' is not a valid choice\n", r);
+        }
+        console.printf("       Supported options are:\n");
+        for (final T e : options) {
+          console.printf("         %s\n", e.toString().toLowerCase());
+        }
+      }
+    }
+
+    @Override
+    public void header(String fmt, Object... args) {
+      fmt = fmt.replaceAll("\n", "\n*** ");
+      console.printf("\n*** " + fmt + "\n*** \n\n", args);
+    }
+
+    @Override
+    public void message(String fmt, Object... args) {
+      console.printf(fmt, args);
+    }
+  }
+
+  private static class Batch extends ConsoleUI {
+    @Override
+    public boolean isBatch() {
+      return true;
+    }
+
+    @Override
+    public boolean yesno(Boolean def, String fmt, Object... args) {
+      return def != null ? def : true;
+    }
+
+    @Override
+    public String readString(String def, String fmt, Object... args) {
+      return def;
+    }
+
+    @Override
+    public String readString(String def, Set<String> allowedValues, String fmt,
+        Object... args) {
+      return def;
+    }
+
+    @Override
+    public void waitForUser() {
+    }
+
+    @Override
+    public String password(String fmt, Object... args) {
+      return null;
+    }
+
+    @Override
+    public <T extends Enum<?>> T readEnum(T def, String fmt, Object... args) {
+      return def;
+    }
+
+    @Override
+    public void header(String fmt, Object... args) {
+    }
+
+    @Override
+    public void message(String fmt, Object... args) {
+    }
+  }
+}
diff --git a/github-plugin/src/main/java/com/google/gerrit/pgm/util/Die.java b/github-plugin/src/main/java/com/google/gerrit/pgm/util/Die.java
new file mode 100644
index 0000000..96e2ec8
--- /dev/null
+++ b/github-plugin/src/main/java/com/google/gerrit/pgm/util/Die.java
@@ -0,0 +1,27 @@
+// 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.util;
+
+public class Die extends RuntimeException {
+  private static final long serialVersionUID = 1L;
+
+  public Die(final String why) {
+    super(why);
+  }
+
+  public Die(final String why, final Throwable cause) {
+    super(why, cause);
+  }
+}
diff --git a/pom.xml b/pom.xml
index 2741a35..a83d34d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -234,49 +234,6 @@
     <module>github-oauth</module>
     <module>github-plugin</module>
   </modules>
-  <dependencies>
-    <dependency>
-      <groupId>com.google.gerrit</groupId>
-      <artifactId>gerrit-plugin-api</artifactId>
-      <version>${project.version}</version>
-    </dependency>
-    <dependency>
-      <groupId>javax.servlet</groupId>
-      <artifactId>javax.servlet-api</artifactId>
-      <version>3.0.1</version>
-      <scope>provided</scope>
-    </dependency>
-    <dependency>
-      <groupId>com.google.inject</groupId>
-      <artifactId>guice</artifactId>
-      <version>3.0</version>
-    </dependency>
-    <dependency>
-      <groupId>com.google.guava</groupId>
-      <artifactId>guava</artifactId>
-      <version>14.0</version>
-    </dependency>
-    <dependency>
-      <groupId>org.slf4j</groupId>
-      <artifactId>slf4j-api</artifactId>
-      <version>1.7.5</version>
-    </dependency>
-    <dependency>
-      <groupId>org.slf4j</groupId>
-      <artifactId>slf4j-log4j12</artifactId>
-      <version>1.7.5</version>
-    </dependency>
-    <dependency>
-      <groupId>log4j</groupId>
-      <artifactId>log4j</artifactId>
-      <version>1.2.17</version>
-    </dependency>
-    <dependency>
-      <groupId>org.jenkins-ci.plugins</groupId>
-      <artifactId>github-api</artifactId>
-      <version>1.40</version>
-    </dependency>
-  </dependencies>
   <build>
     <plugins>
       <plugin>