diff --git a/.idea/libraries/kobalt__Compile_.xml b/.idea/libraries/kobalt__Compile_.xml
index 5fd82a6b..f8a31249 100644
--- a/.idea/libraries/kobalt__Compile_.xml
+++ b/.idea/libraries/kobalt__Compile_.xml
@@ -12,9 +12,9 @@
-
-
+
+
diff --git a/.idea/libraries/kobalt__Test_.xml b/.idea/libraries/kobalt__Test_.xml
index 9623dfb9..f9386500 100644
--- a/.idea/libraries/kobalt__Test_.xml
+++ b/.idea/libraries/kobalt__Test_.xml
@@ -1,14 +1,9 @@
-
-
-
-
-
-
+
diff --git a/.idea/libraries/kobalt_jar.xml b/.idea/libraries/kobalt_jar.xml
index 47bf75af..615f664d 100644
--- a/.idea/libraries/kobalt_jar.xml
+++ b/.idea/libraries/kobalt_jar.xml
@@ -1,7 +1,7 @@
-
+
diff --git a/.idea/libraries/kobalt_plugin_api__Compile_.xml b/.idea/libraries/kobalt_plugin_api__Compile_.xml
index 14febb5c..50404fdc 100644
--- a/.idea/libraries/kobalt_plugin_api__Compile_.xml
+++ b/.idea/libraries/kobalt_plugin_api__Compile_.xml
@@ -3,18 +3,21 @@
-
+
+
-
+
+
-
+
+
diff --git a/.idea/libraries/kobalt_plugin_api__Test_.xml b/.idea/libraries/kobalt_plugin_api__Test_.xml
index 43ee40b8..18b8b5ed 100644
--- a/.idea/libraries/kobalt_plugin_api__Test_.xml
+++ b/.idea/libraries/kobalt_plugin_api__Test_.xml
@@ -1,15 +1,6 @@
-
-
-
-
-
-
-
-
-
-
+
diff --git a/kobalt.iml b/kobalt.iml
index 9c85fa5d..9510060e 100644
--- a/kobalt.iml
+++ b/kobalt.iml
@@ -7,6 +7,7 @@
+
diff --git a/kobalt/src/Build.kt b/kobalt/src/Build.kt
index ee96794f..a7d19ad6 100644
--- a/kobalt/src/Build.kt
+++ b/kobalt/src/Build.kt
@@ -71,7 +71,10 @@ val kobaltPluginApi = project {
"org.apache.maven:maven-model:3.3.3",
"io.reactivex:rxjava:1.0.16",
"com.google.code.gson:gson:2.4",
+ "com.squareup.okhttp3:okhttp:3.2.0",
"com.squareup.retrofit:retrofit:1.9.0",
+ "com.squareup.retrofit2:retrofit:2.0.0-beta4",
+ "com.squareup.retrofit2:converter-gson:2.0.0-beta4",
"com.beust:jcommander:1.48"
)
}
diff --git a/kobalt/wrapper/kobalt-wrapper.properties b/kobalt/wrapper/kobalt-wrapper.properties
index d2b5f6dd..292c9908 100644
--- a/kobalt/wrapper/kobalt-wrapper.properties
+++ b/kobalt/wrapper/kobalt-wrapper.properties
@@ -1 +1 @@
-kobalt.version=0.666
\ No newline at end of file
+kobalt.version=0.667
\ No newline at end of file
diff --git a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/misc/GithubApi2.kt b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/misc/GithubApi2.kt
new file mode 100644
index 00000000..74cfb335
--- /dev/null
+++ b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/misc/GithubApi2.kt
@@ -0,0 +1,146 @@
+package com.beust.kobalt.misc
+
+import com.beust.kobalt.KobaltException
+import com.beust.kobalt.internal.DocUrl
+import com.beust.kobalt.maven.Http
+import com.google.gson.annotations.SerializedName
+import com.google.inject.Inject
+import com.squareup.okhttp.Headers
+import retrofit.RetrofitError
+import retrofit.mime.TypedFile
+import retrofit2.Call
+import retrofit2.Retrofit
+import retrofit2.converter.gson.GsonConverterFactory
+import retrofit2.http.*
+import rx.Observable
+import java.io.File
+import java.util.*
+import java.util.concurrent.Callable
+import java.util.concurrent.Future
+
+class GithubApi2 @Inject constructor(
+ val executors: KobaltExecutors, val localProperties: LocalProperties, val http: Http) {
+
+ companion object {
+ const val PROPERTY_ACCESS_TOKEN = "github.accessToken"
+ const val PROPERTY_USERNAME = "github.username"
+ }
+
+ private val DOC_URL = DocUrl.PUBLISH_PLUGIN_URL
+
+ //
+ // JSON mapped classes that get sent up and down
+ //
+ class CreateRelease(@SerializedName("tag_name") var tagName: String? = null,
+ var name: String? = tagName)
+ class CreateReleaseResponse(var id: String? = null, @SerializedName("upload_url") var uploadUrl: String?)
+ class UploadAssetResponse(var id: String? = null, val name: String? = null)
+ class ReleasesResponse(@SerializedName("tag_name") var tagName: String? = null,
+ var name: String? = tagName)
+
+ interface Api {
+ @POST("/repos/{owner}/{repo}/releases")
+ fun createRelease(@Path("owner") owner: String,
+ @Path("repo") repo: String,
+ @Query("access_token") accessToken: String,
+ @Body createRelease: CreateRelease): Call
+
+ @GET("/repos/{owner}/{repo}/releases")
+ fun getReleases(@Path("owner") owner: String,
+ @Path("repo") repo: String,
+ @Query("access_token") accessToken: String): Call>
+
+ @GET("/repos/{owner}/{repo}/releases")
+ fun getReleasesNoAuth(@Path("owner") owner: String,
+ @Path("repo") repo: String): Call>
+ }
+
+ //
+ // Read only Api
+ //
+ private val service = Retrofit.Builder()
+ .baseUrl("https://api.github.com")
+ .addConverterFactory(GsonConverterFactory.create())
+ .build()
+ .create(Api::class.java)
+
+ fun uploadRelease(packageName: String, tagName: String, zipFile: File) {
+ log(1, "Uploading release ${zipFile.name}")
+
+ val username = localProperties.get(PROPERTY_USERNAME, DOC_URL)
+ val accessToken = localProperties.get(PROPERTY_ACCESS_TOKEN, DOC_URL)
+ try {
+ val response = service.createRelease(username, packageName, accessToken, CreateRelease(tagName))
+ .execute()
+ .body()
+
+ uploadAsset(accessToken, response.uploadUrl!!, TypedFile("application/zip", zipFile),
+ tagName)
+ .toBlocking()
+ .forEach { action ->
+ log(1, "\n${zipFile.name} successfully uploaded")
+ }
+ } catch(e: RetrofitError) {
+ throw KobaltException("Couldn't upload release: " + e.message, e)
+// val error = parseRetrofitError(e)
+// throw KobaltException("Couldn't upload release, ${error.message}: "
+// + error.errors[0].code + " field: " + error.errors[0].field)
+ }
+ }
+
+ private fun uploadAsset(token: String, uploadUrl: String, typedFile: TypedFile, tagName: String)
+ : Observable {
+ val strippedUrl = uploadUrl.substring(0, uploadUrl.indexOf("{"))
+ val fileName = typedFile.file().name
+ val url = "$strippedUrl?name=$fileName&label=$fileName"
+ val headers = Headers.of("Authorization", "token $token")
+ val totalSize = typedFile.file().length()
+ http.uploadFile(url = url, file = typedFile, headers = headers, post = true, // Github requires POST
+ progressCallback = http.percentProgressCallback(totalSize))
+
+ return Observable.just(UploadAssetResponse(tagName, tagName))
+ }
+
+ val latestKobaltVersion: Future
+ get() {
+ val callable = Callable {
+ var result = "0"
+
+ val username = localProperties.getNoThrows(GithubApiOld.PROPERTY_USERNAME, DOC_URL)
+ val accessToken = localProperties.getNoThrows(GithubApiOld.PROPERTY_ACCESS_TOKEN, DOC_URL)
+ try {
+ val req =
+ if (username != null && accessToken != null) {
+ service.getReleases(username, "kobalt", accessToken)
+ } else {
+ service.getReleasesNoAuth("cbeust", "kobalt")
+ }
+ val releases = req.execute()
+ .body()
+ releases.firstOrNull()?.let {
+ try {
+ result = listOf(it.name, it.tagName).filterNotNull().first { !it.isBlank() }
+ } catch(ex: NoSuchElementException) {
+ throw KobaltException("Couldn't find the latest release")
+ }
+ }
+ } catch(e: RetrofitError) {
+ log(1, "Couldn't retrieve releases from github: " + e.message)
+ e.printStackTrace()
+// val error = parseRetrofitError(e)
+// val details = if (error.errors != null) {
+// error.errors[0]
+// } else {
+// null
+// }
+// // TODO: If the credentials didn't work ("bad credentials"), should start again
+// // using cbeust/kobalt, like above. Right now, just bailing.
+// log(2, "Couldn't retrieve releases from github, ${error.message ?: e}: "
+// + details?.code + " field: " + details?.field)
+ }
+ result
+ }
+
+ return executors.miscExecutor.submit(callable)
+ }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/com/beust/kobalt/Main.kt b/src/main/kotlin/com/beust/kobalt/Main.kt
index 1fc07b6e..ed8d793d 100644
--- a/src/main/kotlin/com/beust/kobalt/Main.kt
+++ b/src/main/kotlin/com/beust/kobalt/Main.kt
@@ -58,7 +58,7 @@ private class Main @Inject constructor(
val files: KFiles,
val executors: KobaltExecutors,
val checkVersions: CheckVersions,
- val github: GithubApi,
+ val github: GithubApi2,
val updateKobalt: UpdateKobalt,
val client: KobaltClient,
val server: KobaltServer,
diff --git a/src/main/kotlin/com/beust/kobalt/app/UpdateKobalt.kt b/src/main/kotlin/com/beust/kobalt/app/UpdateKobalt.kt
index cd66c7ff..0c989662 100644
--- a/src/main/kotlin/com/beust/kobalt/app/UpdateKobalt.kt
+++ b/src/main/kotlin/com/beust/kobalt/app/UpdateKobalt.kt
@@ -14,7 +14,7 @@ import javax.inject.Inject
/**
* Update Kobalt to the latest version.
*/
-class UpdateKobalt @Inject constructor(val github: GithubApi, val wrapperProperties: KobaltWrapperProperties) {
+class UpdateKobalt @Inject constructor(val github: GithubApi2, val wrapperProperties: KobaltWrapperProperties) {
fun updateKobalt() {
val newVersion = github.latestKobaltVersion
wrapperProperties.create(newVersion.get())
diff --git a/src/main/kotlin/com/beust/kobalt/plugin/publish/PublishPlugin.kt b/src/main/kotlin/com/beust/kobalt/plugin/publish/PublishPlugin.kt
index bd892d88..db7c9e45 100644
--- a/src/main/kotlin/com/beust/kobalt/plugin/publish/PublishPlugin.kt
+++ b/src/main/kotlin/com/beust/kobalt/plugin/publish/PublishPlugin.kt
@@ -16,7 +16,7 @@ import javax.inject.Singleton
@Suppress("VARIABLE_WITH_REDUNDANT_INITIALIZER")
@Singleton
public class PublishPlugin @Inject constructor(val files: KFiles, val factory: PomGenerator.IFactory,
- val bintrayFactory: BintrayApi.IFactory, val github: GithubApi, val localProperties: LocalProperties)
+ val bintrayFactory: BintrayApi.IFactory, val github: GithubApi2, val localProperties: LocalProperties)
: BasePlugin() {
override val name = PLUGIN_NAME
diff --git a/src/main/resources/kobalt.properties b/src/main/resources/kobalt.properties
index 9db44ee2..529cf587 100644
--- a/src/main/resources/kobalt.properties
+++ b/src/main/resources/kobalt.properties
@@ -1 +1 @@
-kobalt.version=0.666
+kobalt.version=0.667