Skip to content

Commit 65ae533

Browse files
abstraktorslisson
authored andcommitted
feat(model-server): /repositories/{repository}/branches outputs json if accepted
1 parent 43eb52d commit 65ae533

File tree

4 files changed

+124
-13
lines changed

4 files changed

+124
-13
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package org.modelix.model.server.api
2+
3+
import kotlinx.serialization.Serializable
4+
import kotlin.js.JsExport
5+
6+
@JsExport
7+
@Serializable
8+
data class BranchInfo(val id: String, val versionHash: String)

model-server-openapi/specifications/model-server-v2.yaml

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,14 @@ paths:
249249
type: string
250250
responses:
251251
"200":
252-
$ref: '#/components/responses/200'
252+
description: OK
253+
content:
254+
text/plain:
255+
schema:
256+
type: string
257+
application/json:
258+
schema:
259+
$ref: "#/components/schemas/BranchesWithHashes"
253260
default:
254261
$ref: '#/components/responses/GeneralError'
255262
/repositories/{repository}/branches/{branch}:
@@ -764,3 +771,15 @@ components:
764771
type: string
765772
description: Unix timestamp
766773
author: { type: string }
774+
BranchesWithHashes:
775+
type: array
776+
items:
777+
type: object
778+
properties:
779+
id:
780+
type: string
781+
versionHash:
782+
type: string
783+
required:
784+
- id
785+
- versionHash

model-server/src/main/kotlin/org/modelix/model/server/handlers/ModelReplicationServer.kt

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ import org.modelix.model.lazy.RepositoryId
5454
import org.modelix.model.operations.OTBranch
5555
import org.modelix.model.persistent.HashUtil
5656
import org.modelix.model.server.ModelServerPermissionSchema
57+
import org.modelix.model.server.api.BranchInfo
5758
import org.modelix.model.server.api.RepositoryConfig
5859
import org.modelix.model.server.api.v2.ImmutableObjectsStream
5960
import org.modelix.model.server.api.v2.VersionDelta
@@ -114,14 +115,30 @@ class ModelReplicationServer(
114115
}
115116

116117
override suspend fun RoutingContext.getRepositoryBranches(repository: String) {
117-
call.respondText(
118-
@OptIn(RequiresTransaction::class)
119-
runRead { repositoriesManager.getBranchNames(repositoryId(repository)) }
118+
@OptIn(RequiresTransaction::class)
119+
val branchNames = runRead {
120+
repositoriesManager.getBranchNames(repositoryId(repository))
120121
.filter { call.hasPermission(ModelServerPermissionSchema.repository(repository).branch(it).list) }
121-
.joinToString("\n"),
122-
)
122+
}
123+
if (acceptsJson()) {
124+
call.respond<List<BranchInfo>>(
125+
@OptIn(RequiresTransaction::class)
126+
runRead {
127+
branchNames.mapNotNull { branchName ->
128+
val branchRef = repositoryId(repository).getBranchReference(branchName)
129+
val versionHash = repositoriesManager.getVersionHash(branchRef)
130+
versionHash?.let { BranchInfo(branchName, it) }
131+
}
132+
},
133+
)
134+
} else {
135+
call.respondText(branchNames.joinToString("\n"))
136+
}
123137
}
124138

139+
private fun RoutingContext.acceptsJson(): Boolean =
140+
call.request.acceptItems().any { ContentType.parse(it.value).match(ContentType.Application.Json) }
141+
125142
override suspend fun RoutingContext.getRepositoryBranchDelta(
126143
repository: String,
127144
branch: String,

model-server/src/test/kotlin/org/modelix/model/server/handlers/ModelReplicationServerTest.kt

Lines changed: 74 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ import org.modelix.model.client2.readVersionDelta
4848
import org.modelix.model.client2.runWrite
4949
import org.modelix.model.client2.useVersionStreamFormat
5050
import org.modelix.model.lazy.RepositoryId
51+
import org.modelix.model.server.api.BranchInfo
5152
import org.modelix.model.server.api.v2.VersionDeltaStream
5253
import org.modelix.model.server.api.v2.VersionDeltaStreamV2
5354
import org.modelix.model.server.installDefaultServerPlugins
@@ -169,6 +170,71 @@ class ModelReplicationServerTest {
169170
}
170171
}
171172

173+
@Test
174+
fun `fetch branches as plain`() {
175+
val repositoryId = RepositoryId("repo1")
176+
177+
runWithTestModelServer { _, fixture ->
178+
@OptIn(RequiresTransaction::class)
179+
fixture.repositoriesManager.getTransactionManager().runWrite {
180+
val version = fixture.repositoriesManager.createRepository(repositoryId, null)
181+
fixture.repositoriesManager.forcePush(
182+
branch = repositoryId.getBranchReference("change-request/1"),
183+
newVersionHash = version.getContentHash(),
184+
)
185+
}
186+
187+
val response = client.get {
188+
url {
189+
appendPathSegments("v2", "repositories", repositoryId.id, "branches")
190+
}
191+
}
192+
193+
assertEquals(HttpStatusCode.OK, response.status)
194+
assertContains(response.bodyAsText(), "master")
195+
}
196+
}
197+
198+
@Test
199+
fun `fetch branches as json`() {
200+
val repositoryId = RepositoryId("repo1")
201+
202+
runWithTestModelServer { _, fixture ->
203+
204+
// Arrange
205+
@OptIn(RequiresTransaction::class)
206+
val initialVersion = fixture.repositoriesManager.getTransactionManager().runWrite {
207+
fixture.repositoriesManager.createRepository(repositoryId, null)
208+
.also {
209+
fixture.repositoriesManager.forcePush(
210+
branch = repositoryId.getBranchReference("change-requests/1"),
211+
newVersionHash = it.getContentHash(),
212+
)
213+
}
214+
}
215+
216+
// Act
217+
val client = jsonClient()
218+
val response = client.get {
219+
accept(ContentType.Application.Json)
220+
url {
221+
appendPathSegments("v2", "repositories", repositoryId.id, "branches")
222+
}
223+
}
224+
225+
// Assert
226+
assertEquals(HttpStatusCode.OK, response.status)
227+
response.shouldHaveContentType(ContentType.Application.Json.withCharset(Charsets.UTF_8))
228+
assertEquals(
229+
response.body<List<BranchInfo>>(),
230+
listOf(
231+
BranchInfo("change-requests/1", initialVersion.getContentHash()),
232+
BranchInfo("master", initialVersion.getContentHash()),
233+
),
234+
)
235+
}
236+
}
237+
172238
@Test
173239
fun `responds with 400 when deleting from an invalid repository ID`() {
174240
runWithTestModelServer { _, _ ->
@@ -434,13 +500,7 @@ class ModelReplicationServerTest {
434500
fixture.repositoriesManager.getTransactionManager().runWrite {
435501
fixture.repositoriesManager.createRepository(repositoryId, null)
436502
}
437-
val client = createClient {
438-
install(ContentNegotiation) {
439-
json()
440-
register(branchV1ContentType, KotlinxSerializationConverter(DefaultJson))
441-
}
442-
}
443-
503+
val client = jsonClient()
444504
val response = client.get {
445505
url {
446506
appendPathSegments("v2", "repositories", repositoryId.id, "branches", "master")
@@ -545,6 +605,13 @@ class ModelReplicationServerTest {
545605
}
546606
}
547607

608+
private fun ApplicationTestBuilder.jsonClient(): HttpClient = createClient {
609+
install(ContentNegotiation) {
610+
json()
611+
register(ContentType.Application.Json, KotlinxSerializationConverter(DefaultJson))
612+
}
613+
}
614+
548615
fun <T> Flow<T>.assertNotEmpty(additionalMessage: () -> String = { "" }): Flow<T> {
549616
return onEmpty { throw IllegalArgumentException("At least one element was expected. " + additionalMessage()) }
550617
}

0 commit comments

Comments
 (0)