package com.heroku.sdk.deploy; import org.apache.commons.io.FileUtils; import java.io.*; import java.util.*; import java.util.concurrent.*; public class Toolbelt { public static String getApiToken() throws IOException, InterruptedException, ExecutionException, TimeoutException { try { return readNetrcFile().get("api.heroku.com").get("password"); } catch (Throwable e) { return runHerokuCommand(new File(System.getProperty("user.home"), "auth:token")); } } public static String getAppName(File projectDir) throws IOException, InterruptedException, ExecutionException, TimeoutException { Map<String,String> remotes = getGitRemotes(projectDir); if (remotes.containsKey("heroku")) { return parseAppFromRemote(remotes.get("heroku")); } else { throw new RuntimeException("No 'heroku' remote found."); } } private static String runHerokuCommand(final File projectDir, final String... command) throws InterruptedException, ExecutionException, TimeoutException { ExecutorService executor = Executors.newSingleThreadExecutor(); FutureTask<String> future = new FutureTask<String>(new Callable<String>() { public String call() throws IOException { String herokuCmd = SystemSettings.isWindows() ? "heroku.bat" : "heroku"; // crazy Java String[] fullCommand = new String[command.length + 1]; fullCommand[0] = herokuCmd; System.arraycopy(command, 0, fullCommand, 1, command.length); ProcessBuilder pb = new ProcessBuilder().command(fullCommand); pb.directory(projectDir); Process p = pb.start(); BufferedReader bri = new BufferedReader(new InputStreamReader(p.getInputStream())); String line; String output = ""; while ((line = bri.readLine()) != null) { output += line; } return output; }}); executor.execute(future); return future.get(10, TimeUnit.SECONDS); } private static Map<String,String> getGitRemotes(File projectDir) throws IOException { File gitConfigFile = new File(new File(projectDir, ".git"), "config"); if (!gitConfigFile.exists()) { File userDir = new File(System.getProperty("user.home")); if (userDir.equals(projectDir) || projectDir.getParent() == null) { throw new RuntimeException("Git repo not found. Did you init one before creating your app?"); } return getGitRemotes(projectDir.getParentFile()); } Map<String,String> remotes = new HashMap<String, String>(); String remote = null; for (String line : FileUtils.readLines(gitConfigFile)) { if (line != null && !line.trim().isEmpty()) { if (line.startsWith("[remote")) { remote = line.replace("[remote \"", "").replace("\"]", ""); } else if (remote != null && line.contains("url =")) { String[] keyValue = line.trim().split("="); remotes.put(remote, keyValue[1].trim()); } } } return remotes; } private static String parseAppFromRemote(String remote) { if (remote.startsWith("https")) { return remote.replace("https://git.heroku.com/", "").replace(".git", ""); } else if (remote.startsWith("git")) { return remote.replace("git@heroku.com:", "").replace(".git", ""); } return null; } private static Map<String,Map<String,String>> readNetrcFile() throws IOException { String homeDir = System.getProperty("user.home"); String netrcFilename = SystemSettings.isWindows() ? "_netrc" : ".netrc"; File netrcFile = new File(new File(homeDir), netrcFilename); if (!netrcFile.exists()) { throw new FileNotFoundException(netrcFile.toString()); } Map<String,Map<String,String>> netrcMap = new HashMap<String, Map<String, String>>(); String machine = null; Map<String,String> entry = new HashMap<String, String>(); for (String line : FileUtils.readLines(netrcFile)) { if (line != null && !line.trim().isEmpty()) { if (line.startsWith("machine")) { if (null != machine) { netrcMap.put(machine, entry); entry = new HashMap<String, String>(); } machine = line.trim().split(" ")[1]; } else { String[] keyValue = line.trim().split(" "); entry.put(keyValue[0], keyValue[1]); } } } if (null != machine) { netrcMap.put(machine, entry); } return netrcMap; } }