Browse files

Added github integration. Fixes #29

  • Loading branch information...
1 parent 49c1609 commit df61ba011c967be6504d2861e9876c0911e38798 @lucmazon lucmazon committed Feb 27, 2013
View
8 androidkickstartr-core/pom.xml
@@ -50,6 +50,14 @@
<groupId>org.apache.maven.shared</groupId>
<artifactId>maven-invoker</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.eclipse.jgit</groupId>
+ <artifactId>org.eclipse.jgit</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.mylyn.github</groupId>
+ <artifactId>org.eclipse.egit.github.core</artifactId>
+ </dependency>
</dependencies>
</project>
View
11 androidkickstartr-core/src/main/java/com/athomas/androidkickstartr/AppDetails.java
@@ -33,6 +33,7 @@
private boolean acra;
private boolean eclipse;
private boolean proguard;
+ private boolean git;
public String getPackageName() {
return packageName;
@@ -170,6 +171,10 @@ public boolean isProguard() {
return proguard;
}
+ public boolean isGit() {
+ return git;
+ }
+
@Override
public String toString() {
return "State [actionBarSherlock=" + actionBarSherlock + //
@@ -186,6 +191,7 @@ public String toString() {
", acra=" + acra + //
", eclipse=" + eclipse + //
", proguard=" + proguard + //
+ ", git=" + git + //
"]";
}
@@ -319,6 +325,11 @@ public Builder proguard(boolean proguard) {
return this;
}
+ public Builder git(boolean git) {
+ state.git = git;
+ return this;
+ }
+
public AppDetails build() {
if (state.listNavigation && state.tabNavigation) {
View
49 androidkickstartr-core/src/main/java/com/athomas/androidkickstartr/Kickstartr.java
@@ -6,6 +6,8 @@
import java.util.List;
import org.apache.commons.io.FileUtils;
+import org.eclipse.egit.github.core.Repository;
+import org.eclipse.jgit.api.errors.GitAPIException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -16,6 +18,7 @@
import com.athomas.androidkickstartr.generator.SampleFragmentGenerator;
import com.athomas.androidkickstartr.generator.ViewPagerAdapterGenerator;
import com.athomas.androidkickstartr.util.FileHelper;
+import com.athomas.androidkickstartr.util.GitHubber;
import com.athomas.androidkickstartr.util.LibraryHelper;
import com.athomas.androidkickstartr.util.RefHelper;
import com.athomas.androidkickstartr.util.ResourcesUtils;
@@ -53,7 +56,7 @@ private void extractResources(AppDetails appDetails) {
}
}
- public File start() {
+ private void createDirectory() {
LOGGER.info("generation of " + appDetails + " : " + appDetails);
if (appDetails.isRestTemplate() || appDetails.isAcra()) {
@@ -66,7 +69,6 @@ public File start() {
LOGGER.debug("source code generated from templates.");
} catch (IOException e) {
LOGGER.error("generated code file not generated", e);
- return null;
}
try {
@@ -76,7 +78,6 @@ public File start() {
LOGGER.debug("res dir copied.");
} catch (IOException e) {
LOGGER.error("problem occurs during the resources copying", e);
- return null;
}
if (appDetails.isMaven()) {
@@ -96,10 +97,8 @@ public File start() {
LOGGER.debug("files generated from templates.");
} catch (IOException e) {
LOGGER.error("problem during ftl files loading", e);
- return null;
} catch (TemplateException e) {
LOGGER.error("problem during template processing", e);
- return null;
}
try {
@@ -117,27 +116,37 @@ public File start() {
}
} catch (IOException e) {
LOGGER.error("a problem occured during the org.eclipse.jdt.apt.core.prefs copying", e);
- return null;
}
LibraryHelper libraryManager = new LibraryHelper(appDetails, fileHelper);
libraryManager.go();
LOGGER.debug("libraries copied");
-
- File zipFile = null;
- try {
- File targetDir = fileHelper.getTargetDir();
- zipFile = new File(targetDir, appDetails.getName() + "-AndroidKickstartr.zip");
- Zipper.zip(fileHelper.getFinalDir(), zipFile);
- LOGGER.debug("application sources zipped");
- } catch (IOException e) {
- LOGGER.error("a problem occured during the compression", e);
- return null;
- }
-
- LOGGER.debug("AndroidKickstartR generation done");
- return zipFile;
}
+
+ public File startZip() {
+ createDirectory();
+ File zipFile = null;
+ try {
+ File targetDir = fileHelper.getTargetDir();
+ zipFile = new File(targetDir, appDetails.getName() + "-AndroidKickstartr.zip");
+ Zipper.zip(fileHelper.getFinalDir(), zipFile);
+ LOGGER.debug("application sources zipped");
+ } catch (IOException e) {
+ LOGGER.error("a problem occured during the compression", e);
+ return null;
+ }
+
+ LOGGER.debug("AndroidKickstartR generation done");
+ return zipFile;
+ }
+
+ public Repository startGithub(String accessToken) throws IOException, GitAPIException {
+ LOGGER.debug("Github creation started");
+ createDirectory();
+ GitHubber gitHubber = new GitHubber(accessToken);
+ Repository repository = gitHubber.createCommit(fileHelper.getFinalDir(), fileHelper.getProjectDir().getName());
+ return repository;
+ }
private void generateSourceCode() throws IOException {
List<Generator> generators = new ArrayList<Generator>();
View
8 androidkickstartr-core/src/main/java/com/athomas/androidkickstartr/util/FileHelper.java
@@ -73,6 +73,10 @@ public File getTargetAndroidResDir() throws IOException {
public File getTargetProjectDir() {
return getDir(getProjectPath());
}
+
+ public File getProjectDir() {
+ return getDir(getProjectPath());
+ }
public File getFinalDir() {
return getDir(getFinalPath());
@@ -151,6 +155,10 @@ public File getTargetEclipseJdtCorePrefsFile() throws IOException {
public File getTargetProjectPropertiesFile() throws IOException {
return createFile(getProjectPath() + "/project.properties");
}
+
+ public File getTargetReadmeFile() throws IOException {
+ return createFile(getFinalPath() + "/README.md");
+ }
public File getTargetRoboSherlockActivityFile() throws IOException {
return createFile(getTargetSourcePath() + "/" + packageName.replace(".", "/") + "/robosherlock/RoboSherlockActivity.java");
View
52 androidkickstartr-core/src/main/java/com/athomas/androidkickstartr/util/GitHubber.java
@@ -0,0 +1,52 @@
+package com.athomas.androidkickstartr.util;
+
+import org.eclipse.egit.github.core.Repository;
+import org.eclipse.egit.github.core.client.GitHubClient;
+import org.eclipse.egit.github.core.service.RepositoryService;
+import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.api.InitCommand;
+import org.eclipse.jgit.api.errors.GitAPIException;
+import org.eclipse.jgit.lib.StoredConfig;
+import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
+
+import java.io.File;
+import java.io.IOException;
+
+public class GitHubber {
+
+ private static final String COMMIT_MESSAGE = "AndroidKickstartR generation";
+
+ private String accessToken;
+ private GitHubClient gitHubClient;
+ private RepositoryService repositoryService;
+
+ public GitHubber(String accessToken) {
+ this.accessToken = accessToken;
+ gitHubClient = new GitHubClient();
+ gitHubClient.setOAuth2Token(accessToken);
+
+ repositoryService = new RepositoryService(gitHubClient);
+ }
+
+ public Repository createCommit(File srcFolder, String applicationName) throws IOException, GitAPIException {
+ Repository repository = repositoryService.createRepository(new Repository().setName(applicationName));
+
+ String cloneUrl = repository.getCloneUrl();
+
+ InitCommand init = new InitCommand();
+ init.setDirectory(srcFolder);
+ init.setBare(false);
+ Git git = init.call();
+
+ StoredConfig config = git.getRepository().getConfig();
+ config.setString("remote", "origin", "url", cloneUrl);
+ config.save();
+
+ UsernamePasswordCredentialsProvider user = new UsernamePasswordCredentialsProvider(accessToken, "");
+ git.add().addFilepattern(".").call();
+ git.commit().setMessage(COMMIT_MESSAGE).call();
+ git.push().setCredentialsProvider(user).call();
+
+ return repository;
+ }
+}
View
5 ...kickstartr-core/src/main/java/com/athomas/androidkickstartr/util/TemplatesFileHelper.java
@@ -92,6 +92,11 @@ public void generate() throws IOException, TemplateException {
LOGGER.debug("RoboSherlockFragmentActivity.java created");
}
}
+
+ if (appDetails.isGit()) {
+ processTemplate(cfg, params, "Readme.ftl", fileHelper.getTargetReadmeFile());
+ LOGGER.debug("README.md created");
+ }
}
private void processTemplate(Configuration cfg, HashMap<String, Object> params, String templateFile, File targetFile) throws IOException, TemplateException {
View
4 androidkickstartr-core/src/main/resources/templates/Readme.ftl
@@ -0,0 +1,4 @@
+# ${application.name} #
+
+----------
+Generated by [Android KickstartR](http://www.androidkickstartr.com)
View
2 androidkickstartr-core/src/test/java/com/athomas/androidkickstartr/KickstartrMavenTest.java
@@ -440,7 +440,7 @@ public void generateProject_maven_abs_list_rest_acra_nine_viewpager_roboguice_pr
private File launchKickstartr() {
kickstartr = new Kickstartr(appDetails);
- return kickstartr.start();
+ return kickstartr.startZip();
}
}
View
2 ...idkickstartr-core/src/test/java/com/athomas/androidkickstartr/KickstartrNonMavenTest.java
@@ -369,7 +369,7 @@ public void generateProject_abs_list_rest_acra_nine_viewpager_roboguice_proguard
private File launchKickstartr() {
kickstartr = new Kickstartr(appDetails);
- return kickstartr.start();
+ return kickstartr.startZip();
}
}
View
4 androidkickstartr-ws/pom.xml
@@ -28,6 +28,10 @@
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-server</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpclient</artifactId>
+ </dependency>
</dependencies>
<pluginRepositories>
View
169 androidkickstartr-ws/src/main/java/com/athomas/androidkickstartr/Main.java
@@ -1,25 +1,63 @@
package com.athomas.androidkickstartr;
+import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
+import java.io.InputStreamReader;
import java.io.OutputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import javax.ws.rs.FormParam;
+import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.StreamingOutput;
import org.apache.commons.io.FileUtils;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.NameValuePair;
+import org.apache.http.client.ClientProtocolException;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.message.BasicNameValuePair;
+import org.eclipse.egit.github.core.Repository;
+import org.eclipse.jgit.api.errors.GitAPIException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import com.athomas.androidkickstartr.util.StringUtils;
@Path("/")
public class Main {
+ private static final Logger LOGGER = LoggerFactory.getLogger(Main.class);
+
+ private static final String PROTOCOL = "http";
+ private static final String HOSTNAME = "localhost";
+ private static final int HOSTPORT = 8000;
+
+ // Remember to add these properties to your JVM on deploy (-Did="XXXXXXX"
+ // -Dsecret="XXXXXXX")
+ private static final String CLIENT_ID = System.getProperty("id");
+ private static final String CLIENT_SECRET = System.getProperty("secret");
+
+ private static final String ACCESS_TOKEN = "accessToken";
+ private static final String ERROR = "error";
+ private static final String SUCCESS = "success";
+
@POST
@Produces("application/zip")
public Response go(//
@@ -43,11 +81,15 @@ public Response go(//
@FormParam("packageName") String packageName,//
@FormParam("name") String name,//
@FormParam("activity") String activity,//
- @FormParam("activityLayout") String activityLayout//
+ @FormParam("activityLayout") String activityLayout,//
+
+ // Github access token
+ @FormParam("accessToken") String accessToken//
) {
boolean listNavigation = false;
boolean tabNavigation = false;
+ boolean git = false;
if (navigationType != null) {
tabNavigation = navigationType.equals("tabNavigation");
@@ -67,6 +109,10 @@ public Response go(//
activityLayout = "activity_main";
}
+ if (!StringUtils.isEmpty(accessToken)) {
+ git = true;
+ }
+
if (viewPager && !actionBarSherlock && !viewPagerIndicator && !supportV4) {
supportV4 = true;
}
@@ -97,31 +143,120 @@ public Response go(//
acra(acra). //
eclipse(eclipse). //
proguard(proguard). //
+ git(git). //
build();
final Kickstartr kickstarter = new Kickstartr(appDetails);
- final File file = kickstarter.start();
- if (file == null) {
- return Response.serverError().build();
+ if (!git) {
+ LOGGER.debug("No github asked");
+ final File file = kickstarter.startZip();
+
+ if (file == null) {
+ return Response.serverError().build();
+ }
+
+ StreamingOutput output = new StreamingOutput() {
+ public void write(OutputStream output) throws IOException, WebApplicationException {
+ try {
+ FileUtils.copyFile(file, output);
+ kickstarter.clean();
+ } catch (Exception e) {
+ throw new WebApplicationException(e);
+ }
+ }
+ };
+
+ return Response //
+ .ok(output) //
+ .header("Content-Length", file.length()) //
+ .header("Content-Disposition", "attachment; filename=" + file.getName()) //
+ .build();
+ } else {
+ LOGGER.debug("Github output asked");
+ Repository repository = null;
+ try {
+ repository = kickstarter.startGithub(accessToken);
+ } catch (IOException e) {
+ e.printStackTrace();
+ return Response.seeOther(
+ createAndroidKickstartRUriWithAccessToken(accessToken, ERROR, "Unable to create or access repository : " + e.getMessage())).build();
+ } catch (GitAPIException e) {
+ e.printStackTrace();
+ return Response.seeOther(
+ createAndroidKickstartRUriWithAccessToken(accessToken, ERROR, "Unable to create or access repository : " + e.getMessage())).build();
+ } finally {
+ kickstarter.clean();
+ }
+ if (repository != null)
+ return Response.seeOther(
+ createAndroidKickstartRUriWithAccessToken(accessToken, SUCCESS,
+ "Repository successfully created! You can access it now at the following address : &repositoryUrl=" + repository.getHtmlUrl()))
+ .build();
+ else
+ return Response.serverError().build();
}
+ }
- StreamingOutput output = new StreamingOutput() {
- public void write(OutputStream output) throws IOException, WebApplicationException {
- try {
- FileUtils.copyFile(file, output);
- kickstarter.clean();
- } catch (Exception e) {
- throw new WebApplicationException(e);
+ @GET
+ @Path("getAccessToken")
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response getAccessToken(@QueryParam("code") String code) throws ClientProtocolException, IOException, URISyntaxException {
+ HttpClient httpclient = new DefaultHttpClient();
+ HttpPost postRequest = new HttpPost("https://github.com/login/oauth/access_token");
+
+ List<NameValuePair> nameValuePair = new ArrayList<NameValuePair>(3);
+ nameValuePair.add(new BasicNameValuePair("client_id", CLIENT_ID));
+ nameValuePair.add(new BasicNameValuePair("client_secret", CLIENT_SECRET));
+ nameValuePair.add(new BasicNameValuePair("code", code));
+
+ postRequest.setEntity(new UrlEncodedFormEntity(nameValuePair));
+
+ HttpResponse response = httpclient.execute(postRequest);
+ if (response.getStatusLine().getStatusCode() != 200) {
+ return Response.temporaryRedirect(
+ createAndroidKickstartRUri(ERROR, "Unexpected status code : " + response.getStatusLine().getStatusCode() + " "
+ + response.getStatusLine().getReasonPhrase())).build();
+ } else {
+ HttpEntity entity = response.getEntity();
+ BufferedReader br = new BufferedReader(new InputStreamReader(entity.getContent()));
+ String buf;
+
+ Pattern pattern = Pattern.compile("(\\w{40})");
+ while ((buf = br.readLine()) != null) {
+ Matcher matcher = pattern.matcher(buf);
+ if (matcher.find()) {
+ return Response.temporaryRedirect(createAndroidKickstartRUri(ACCESS_TOKEN, matcher.group())).build();
}
}
- };
+ }
+ return Response.temporaryRedirect(createAndroidKickstartRUri(ERROR, "Couldn't retrieve access token")).build();
+ }
+
+ // HELPERS
- return Response //
- .ok(output) //
- .header("Content-Length", file.length()) //
- .header("Content-Disposition", "attachment; filename=" + file.getName()) //
- .build();
+ private static URI createAndroidKickstartRUriWithAccessToken(String accessToken, String parameterName, String parameterValue) {
+ return createAndroidKickstartRUri(new String[] { ACCESS_TOKEN, parameterName }, new String[] { accessToken, parameterValue });
}
+ private static URI createAndroidKickstartRUri(String parameterName, String parameterValue) {
+ return createAndroidKickstartRUri(new String[] { parameterName }, new String[] { parameterValue });
+ }
+
+ private static URI createAndroidKickstartRUri(String[] parameterNames, String[] parameterValues) {
+ try {
+ return new URI(PROTOCOL, null, HOSTNAME, HOSTPORT, null, createParametersString(parameterNames, parameterValues), null);
+ } catch (URISyntaxException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ private static String createParametersString(String[] parameterNames, String[] parameterValues) {
+ StringBuilder builder = new StringBuilder();
+ for (int i = 0; i < parameterNames.length; i++) {
+ builder.append(parameterNames[i]).append("=").append(parameterValues[i]).append("&");
+ }
+ return builder.deleteCharAt(builder.length() - 1).toString();
+ }
}
View
18 pom.xml
@@ -31,6 +31,9 @@
<logback.version>1.0.0</logback.version>
<junit.version>4.10</junit.version>
<maven-invoker.version>2.0.11</maven-invoker.version>
+ <httpcomponents.version>4.2.2</httpcomponents.version>
+ <jgit.version>2.2.0.201212191850-r</jgit.version>
+ <egit.version>2.1.3</egit.version>
</properties>
<dependencyManagement>
@@ -90,6 +93,21 @@
<artifactId>maven-invoker</artifactId>
<version>${maven-invoker.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpclient</artifactId>
+ <version>${httpcomponents.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jgit</groupId>
+ <artifactId>org.eclipse.jgit</artifactId>
+ <version>${jgit.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.mylyn.github</groupId>
+ <artifactId>org.eclipse.egit.github.core</artifactId>
+ <version>${egit.version}</version>
+ </dependency>
</dependencies>
</dependencyManagement>

0 comments on commit df61ba0

Please sign in to comment.