Skip to content

Instantly share code, notes, and snippets.

@unixunion
Created March 4, 2016 09:02
Show Gist options
  • Save unixunion/0d1599f6eeb83319c44a to your computer and use it in GitHub Desktop.
Save unixunion/0d1599f6eeb83319c44a to your computer and use it in GitHub Desktop.
package com.deblox.greatsnipe.git.impl;
import com.deblox.greatsnipe.git.GitServerProvider;
import io.netty.handler.codec.http.HttpHeaders;
import io.vertx.core.Handler;
import io.vertx.core.Vertx;
import io.vertx.core.http.HttpClient;
import io.vertx.core.http.HttpClientRequest;
import io.vertx.core.json.JsonObject;
import io.vertx.core.logging.Logger;
import io.vertx.core.logging.LoggerFactory;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Base64;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Created by keghol on 02/12/15.
*/
public class BitBucket implements GitServerProvider {
private static final Logger logging = LoggerFactory.getLogger(BitBucket.class);
HttpClient client;
public URL apiUrl; // e.g. https://bitbucket.mydomain.com:80/stash/rest/api/1.0
public String token; // username:password goes here
private String repoUrl; // set this from result of createProjectAndRepo
private Vertx vertx;
@Override
public GitServerProvider setVertx(Vertx vertx) {
this.vertx = vertx;
return this;
}
/**
* Set the url to the BitBucket API, e.g.: https://bitbucket.mydomain.com:80/stash/rest/api/1.0
* <p>
* Important to specify the PORT in the URL!
* @param url
* @return
* @throws MalformedURLException
*/
@Override
public GitServerProvider setApiUrl(String url) throws MalformedURLException {
apiUrl = new URL(url);
client = vertx.createHttpClient();
return this;
}
/**
* sets the token we will use for authentication, for BitBucket, this is "username:password".
*
* @param token
* @return
*/
@Override
public GitServerProvider setToken(String token) {
this.token = token;
return this;
}
/**
* Create a project within BitBucket, create a repo within project, return URL to repo.
*
* Ignores failures to create duplicate projects, returning the URL to the REPO is the only goal.
*
* @param name JsonObject which contains the keys `projectKey` and `projectName` and `repoName`
* @param handler the handler to call with the body
* @throws IOException
*/
@Override
public void createProjectAndRepo(Object name, Handler<Object> handler) throws IOException {
JsonObject document = (JsonObject)name;
// copy relevant keys to the new request on the correct key name per BitBucket API specification
JsonObject request = new JsonObject();
request.put("key", document.getValue("projectKey"));
request.put("name", document.getValue("projectName"));
HttpClientRequest req = client.post(apiUrl.getPort(), apiUrl.getHost(), apiUrl.getPath() + "/projects", res -> {
res.bodyHandler(body -> {
logging.info("Response: " + body.toString());
// created {"key":"MGP","id":62,"name":"My Group","public":false,"type":"NORMAL","link":{"url":"/projects/MGP","rel":"self"},"links":{"self":[{"href":"https://stashpoc.unibet.com/stash/projects/MGP"}]}}
// exists {"errors":[{"context":"key","message":"The project key is already in use","exceptionName":null},{"context":"name","message":"The project name is already in use","exceptionName":null}]}
logging.info("Creating Repo");
HttpClientRequest createRepo = client.post(apiUrl.getPort(), apiUrl.getHost(), apiUrl.getPath() + "/projects/" + document.getValue("projectKey") + "/repos", createResult -> {
createResult.bodyHandler( c -> {
logging.info(c.toString());
logging.info("Getting Project URL URL");
HttpClientRequest req2 = client.get(apiUrl.getPort(), apiUrl.getHost(), apiUrl.getPath() + "/projects/" + document.getValue("projectKey") + "/repos/" + document.getValue("repoName"), res2 -> {
res2.bodyHandler(f -> {
logging.info(f.toString());
try {
handler.handle(new JsonObject(f.toString()).getString("cloneUrl"));
} catch (Exception e) {
handler.handle(new JsonObject().put("error", "unable to get repo url"));
}
});
});
req2 = appendHeaders(req2);
req2.end();
});
});
JsonObject newRepoJson = new JsonObject();
newRepoJson.put("name", document.getValue("repoName"));
newRepoJson.put("scmId", "git");
newRepoJson.put("forkable", true);
createRepo = appendHeaders(createRepo);
createRepo.end();
});
});
req = appendHeaders(req);
logging.info("Created Request: " + request.toString());
try {
req.end(request.toString());
} catch (Exception e) {
logging.error("talking to gitApiUrl error, example: https://stash.mydomain.com:80/stash/rest/api/1.0");
req.end("talking to gitApiUrl error, example: https://stash.mydomain.com:80/stash/rest/api/1.0");
}
}
/**
* Encodes "token" and puts it into a Basic Auth header. Token should be "username:password"
*
* @param req
* @return
*/
public HttpClientRequest appendHeaders(HttpClientRequest req) {
logging.info("Appending credentials");
req.putHeader(HttpHeaders.Names.AUTHORIZATION, "Basic " + Base64.getEncoder().encodeToString(token.getBytes()));
req.putHeader(HttpHeaders.Names.CONTENT_TYPE, "application/json");
return req;
}
@Override
public String getRepoUrl() {
return repoUrl;
}
/**
* Return the url with username:password in it.
* <p>
* depends on that the repoUrl is already set, and will strip away any username and password
* already within the URL.
*
* @return
*/
@Override
public String getAuhRepoUrl(String username, String password) {
logging.info("Getting auth repo url for " +
"username: " + username + " " +
"password: " + password + " " +
"repoUrl: " + repoUrl);
if (!username.equals("")) {
Pattern pattern1 = Pattern.compile("http://.*@");
Pattern pattern2 = Pattern.compile("https://.*@");
Matcher m1 = pattern1.matcher(repoUrl);
String m1S = m1.replaceAll("http://" + username + ":" + password + "@");
Matcher m2 = pattern2.matcher(m1S);
String m2S = m2.replaceAll("https://" + username + ":" + password + "@");
logging.info("Adding credential to url: " + m2S);
return m2S;
} else {
logging.warn("username not set, returning original url");
return repoUrl;
}
}
public void setRepoUrl(String repoUrl) {
logging.info("Setting repoUrl: " + repoUrl);
this.repoUrl = repoUrl;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment