# HG changeset patch # User Mike Becker # Date 1690057924 -7200 # Node ID 671c1c8fbf1c98c346f8938da0db428e396786c2 # Parent ea6181255423613cd61be439f096106601302801 add full support for commit references - fixes #276 diff -r ea6181255423 -r 671c1c8fbf1c setup/postgres/psql_create_tables.sql --- a/setup/postgres/psql_create_tables.sql Sat Jul 22 15:07:23 2023 +0200 +++ b/setup/postgres/psql_create_tables.sql Sat Jul 22 22:32:04 2023 +0200 @@ -1,6 +1,3 @@ --- This script creates the module management tables --- - create table lpit_user ( userid serial primary key, @@ -10,6 +7,8 @@ givenname text ); +create type vcstype as enum ('None', 'Mercurial', 'Git'); + create table lpit_project ( projectid serial primary key, @@ -18,6 +17,7 @@ ordinal integer not null default 0, description text, repoUrl text, + vcs vcstype not null default 'None'::vcstype, owner integer references lpit_user (userid) ); @@ -168,3 +168,12 @@ ); create unique index lpit_issue_relation_unique on lpit_issue_relation (from_issue, to_issue, type); + +create table lpit_commit_ref +( + issueid integer not null references lpit_issue (issueid) on delete cascade, + commit_hash text not null, + commit_brief text not null +); + +create unique index lpit_commit_ref_unique on lpit_commit_ref (issueid, commit_hash); diff -r ea6181255423 -r 671c1c8fbf1c src/main/kotlin/de/uapcore/lightpit/RequestMapping.kt --- a/src/main/kotlin/de/uapcore/lightpit/RequestMapping.kt Sat Jul 22 15:07:23 2023 +0200 +++ b/src/main/kotlin/de/uapcore/lightpit/RequestMapping.kt Sat Jul 22 22:32:04 2023 +0200 @@ -173,6 +173,10 @@ } } + val body: String by lazy { + request.reader.lineSequence().joinToString("\n") + } + private fun forward(jsp: String) { request.getRequestDispatcher(jspPath(jsp)).forward(request, response) } diff -r ea6181255423 -r 671c1c8fbf1c src/main/kotlin/de/uapcore/lightpit/dao/DataAccessObject.kt --- a/src/main/kotlin/de/uapcore/lightpit/dao/DataAccessObject.kt Sat Jul 22 15:07:23 2023 +0200 +++ b/src/main/kotlin/de/uapcore/lightpit/dao/DataAccessObject.kt Sat Jul 22 22:32:04 2023 +0200 @@ -26,6 +26,7 @@ package de.uapcore.lightpit.dao import de.uapcore.lightpit.entities.* +import de.uapcore.lightpit.types.CommitRef import de.uapcore.lightpit.viewmodel.ComponentSummary import de.uapcore.lightpit.viewmodel.IssueSummary import de.uapcore.lightpit.viewmodel.VersionSummary @@ -70,6 +71,8 @@ fun collectIssueSummary(project: Project): IssueSummary fun collectIssueSummary(assignee: User): IssueSummary + fun mergeCommitRefs(refs: List) + fun listIssues(project: Project, includeDone: Boolean): List fun listIssues(project: Project, includeDone: Boolean, version: Version?, component: Component?): List fun findIssue(id: Int): Issue? @@ -101,4 +104,5 @@ * Lists the issue comment history of the project with [projectId] for the past [days]. */ fun listIssueCommentHistory(projectId: Int, days: Int): List + fun listCommitRefs(issue: Issue): List } diff -r ea6181255423 -r 671c1c8fbf1c src/main/kotlin/de/uapcore/lightpit/dao/PostgresDataAccessObject.kt --- a/src/main/kotlin/de/uapcore/lightpit/dao/PostgresDataAccessObject.kt Sat Jul 22 15:07:23 2023 +0200 +++ b/src/main/kotlin/de/uapcore/lightpit/dao/PostgresDataAccessObject.kt Sat Jul 22 22:32:04 2023 +0200 @@ -26,6 +26,7 @@ package de.uapcore.lightpit.dao import de.uapcore.lightpit.entities.* +import de.uapcore.lightpit.types.CommitRef import de.uapcore.lightpit.types.IssueHistoryType import de.uapcore.lightpit.types.RelationType import de.uapcore.lightpit.types.WebColor @@ -358,7 +359,7 @@ //language=SQL private val projectQuery = """ - select projectid, name, node, ordinal, description, repourl, + select projectid, name, node, ordinal, description, vcs, repourl, userid, username, lastname, givenname, mail from lpit_project left join lpit_user owner on lpit_project.owner = owner.userid @@ -370,6 +371,7 @@ node = getString("node") ordinal = getInt("ordinal") description = getString("description") + vcs = getEnum("vcs") repoUrl = getString("repourl") owner = extractOptionalUser() } @@ -381,6 +383,7 @@ setStringSafe(i++, node) setInt(i++, ordinal) setStringOrNull(i++, description) + setEnum(i++, vcs) setStringOrNull(i++, repoUrl) setIntOrNull(i++, owner?.id) } @@ -405,14 +408,14 @@ } override fun insertProject(project: Project) { - withStatement("insert into lpit_project (name, node, ordinal, description, repourl, owner) values (?, ?, ?, ?, ?, ?)") { + withStatement("insert into lpit_project (name, node, ordinal, description, vcs, repourl, owner) values (?, ?, ?, ?, ?::vcstype, ?, ?)") { setProject(1, project) executeUpdate() } } override fun updateProject(project: Project) { - withStatement("update lpit_project set name = ?, node = ?, ordinal = ?, description = ?, repourl = ?, owner = ? where projectid = ?") { + withStatement("update lpit_project set name = ?, node = ?, ordinal = ?, description = ?, vcs = ?::vcstype, repourl = ?, owner = ? where projectid = ?") { val col = setProject(1, project) setInt(col, project.id) executeUpdate() @@ -471,6 +474,17 @@ } } + override fun mergeCommitRefs(refs: List) { + withStatement("insert into lpit_commit_ref (issueid, commit_hash, commit_brief) values (?,?,?) on conflict do nothing") { + refs.forEach { ref -> + setInt(1, ref.issueId) + setString(2, ref.hash) + setString(3, ref.message) + executeUpdate() + } + } + } + // // @@ -636,6 +650,18 @@ } } + override fun listCommitRefs(issue: Issue): List = + withStatement("select commit_hash, commit_brief from lpit_commit_ref where issueid = ?") { + setInt(1, issue.id) + queryAll { + CommitRef( + issueId = issue.id, + hash = it.getString("commit_hash"), + message = it.getString("commit_brief") + ) + } + } + // // diff -r ea6181255423 -r 671c1c8fbf1c src/main/kotlin/de/uapcore/lightpit/entities/Project.kt --- a/src/main/kotlin/de/uapcore/lightpit/entities/Project.kt Sat Jul 22 15:07:23 2023 +0200 +++ b/src/main/kotlin/de/uapcore/lightpit/entities/Project.kt Sat Jul 22 22:32:04 2023 +0200 @@ -25,11 +25,14 @@ package de.uapcore.lightpit.entities +import de.uapcore.lightpit.types.VcsType + data class Project(override val id: Int) : Entity, HasNode { var name: String = "" override var node: String = name var ordinal = 0 var description: String? = null + var vcs: VcsType = VcsType.None var repoUrl: String? = null var owner: User? = null } \ No newline at end of file diff -r ea6181255423 -r 671c1c8fbf1c src/main/kotlin/de/uapcore/lightpit/servlet/ProjectServlet.kt --- a/src/main/kotlin/de/uapcore/lightpit/servlet/ProjectServlet.kt Sat Jul 22 15:07:23 2023 +0200 +++ b/src/main/kotlin/de/uapcore/lightpit/servlet/ProjectServlet.kt Sat Jul 22 22:32:04 2023 +0200 @@ -46,6 +46,7 @@ get("/%project/edit", this::projectForm) get("/-/create", this::projectForm) post("/-/commit", this::projectCommit) + post("/%project/vcs/analyze", this::vcsAnalyze) get("/%project/versions/", this::versions) get("/%project/versions/%version/edit", this::versionForm) @@ -243,6 +244,7 @@ description = http.param("description") ?: "" ordinal = http.param("ordinal")?.toIntOrNull() ?: 0 repoUrl = http.param("repoUrl") ?: "" + vcs = VcsType.valueOf(http.param("vcs") ?: "None") owner = (http.param("owner")?.toIntOrNull() ?: -1).let { if (it < 0) null else dao.findUser(it) } @@ -261,6 +263,26 @@ http.renderCommit("projects/${project.node}") } + private fun vcsAnalyze(http: HttpRequest, dao: DataAccessObject) { + val projectInfo = obtainProjectInfo(http, dao) + if (projectInfo == null) { + http.response.sendError(404) + return + } + + // if analysis is not configured, reject the request + if (projectInfo.project.vcs == VcsType.None) { + http.response.sendError(404) + return + } + + // obtain the list of issues for this project to filter cross-project references + val knownIds = dao.listIssues(projectInfo.project, true).map { it.id } + + // read the provided commit log and merge only the refs that relate issues from the current project + dao.mergeCommitRefs(parseCommitRefs(http.body).filter { knownIds.contains(it.issueId) }) + } + private fun versions(http: HttpRequest, dao: DataAccessObject) { val projectInfo = obtainProjectInfo(http, dao) if (projectInfo == null) { @@ -475,7 +497,8 @@ component, dao.listIssues(project, true), dao.listIssueRelations(issue), - relationError + relationError, + dao.listCommitRefs(issue) ) feedPath = feedPath(projectInfo.project) navigationMenu = activeProjectNavMenu( diff -r ea6181255423 -r 671c1c8fbf1c src/main/kotlin/de/uapcore/lightpit/types/VcsType.kt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/main/kotlin/de/uapcore/lightpit/types/VcsType.kt Sat Jul 22 22:32:04 2023 +0200 @@ -0,0 +1,29 @@ +/* + * Copyright 2023 Mike Becker. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +package de.uapcore.lightpit.types + +enum class VcsType {None, Mercurial, Git} \ No newline at end of file diff -r ea6181255423 -r 671c1c8fbf1c src/main/kotlin/de/uapcore/lightpit/viewmodel/Issues.kt --- a/src/main/kotlin/de/uapcore/lightpit/viewmodel/Issues.kt Sat Jul 22 15:07:23 2023 +0200 +++ b/src/main/kotlin/de/uapcore/lightpit/viewmodel/Issues.kt Sat Jul 22 22:32:04 2023 +0200 @@ -99,6 +99,8 @@ } } +data class CommitLink(val url: String, val hash: String, val message: String) + class IssueDetailView( val issue: Issue, val comments: List, @@ -110,10 +112,12 @@ /** * Optional resource key to an error message for the relation editor. */ - val relationError: String? + val relationError: String?, + commitRefs: List ) : View() { val relationTypes = RelationType.values() val linkableIssues = projectIssues.filterNot { it.id == issue.id } + val commitLinks: List private val parser: Parser private val renderer: HtmlRenderer @@ -131,8 +135,24 @@ for (comment in comments) { comment.commentFormatted = formatMarkdown(comment.comment) } + + val commitBaseUrl = project.repoUrl + commitLinks = (if (commitBaseUrl == null || project.vcs == VcsType.None) emptyList() else commitRefs.map { + CommitLink(buildCommitUrl(commitBaseUrl, project.vcs, it.hash), it.hash, it.message) + }) } + private fun buildCommitUrl(baseUrl: String, vcs: VcsType, hash: String): String = + with (StringBuilder(baseUrl)) { + if (!endsWith("/")) append('/') + when (vcs) { + VcsType.Mercurial -> append("rev/") + else -> append("commit/") + } + append(hash) + toString() + } + private fun formatEmojis(text: String) = text .replace("(/)", "✅") .replace("(x)", "❌") diff -r ea6181255423 -r 671c1c8fbf1c src/main/resources/localization/strings.properties --- a/src/main/resources/localization/strings.properties Sat Jul 22 15:07:23 2023 +0200 +++ b/src/main/resources/localization/strings.properties Sat Jul 22 22:32:04 2023 +0200 @@ -83,6 +83,9 @@ issue.comments.lastupdate=Last edited: issue.comments.updateCount=total edits issue.comments=Comments +issue.commits.hash=Hash +issue.commits.message=Brief +issue.commits=Commits issue.created=Created issue.description=Description issue.eta=ETA @@ -156,6 +159,8 @@ project.name=Name project.owner=Project Lead project.repoUrl=Repository +project.vcs=Version Control +project.vcs.none=Do not analyze repository project=Project user.displayname=Developer user.givenname=Given Name diff -r ea6181255423 -r 671c1c8fbf1c src/main/resources/localization/strings_de.properties --- a/src/main/resources/localization/strings_de.properties Sat Jul 22 15:07:23 2023 +0200 +++ b/src/main/resources/localization/strings_de.properties Sat Jul 22 22:32:04 2023 +0200 @@ -83,6 +83,9 @@ issue.comments.lastupdate=Zuletzt bearbeitet: issue.comments.updateCount=mal bearbeitet issue.comments=Kommentare +issue.commits.hash=Hash +issue.commits.message=Zusammenfassung +issue.commits=Commits issue.created=Erstellt issue.description=Beschreibung issue.eta=Zieldatum @@ -156,6 +159,8 @@ project.name=Name project.owner=Projektleitung project.repoUrl=Repository +project.vcs=Versionskontrolle +project.vcs.none=Keine Analyse durchf\u00fchren project=Projekt user.displayname=Entwickler user.givenname=Vorname diff -r ea6181255423 -r 671c1c8fbf1c src/main/webapp/WEB-INF/changelogs/changelog-de.jspf --- a/src/main/webapp/WEB-INF/changelogs/changelog-de.jspf Sat Jul 22 15:07:23 2023 +0200 +++ b/src/main/webapp/WEB-INF/changelogs/changelog-de.jspf Sat Jul 22 22:32:04 2023 +0200 @@ -24,6 +24,12 @@ --%> <%@ page contentType="text/html;charset=UTF-8" %> +

Version 1.1.0

+ +
    +
  • Integration von Commit-Logs für Mercurial und Git hinzugefügt.
  • +
+

Version 1.0.1

    diff -r ea6181255423 -r 671c1c8fbf1c src/main/webapp/WEB-INF/changelogs/changelog.jspf --- a/src/main/webapp/WEB-INF/changelogs/changelog.jspf Sat Jul 22 15:07:23 2023 +0200 +++ b/src/main/webapp/WEB-INF/changelogs/changelog.jspf Sat Jul 22 22:32:04 2023 +0200 @@ -24,6 +24,12 @@ --%> <%@ page contentType="text/html;charset=UTF-8" %> +

    Version 1.1.0

    + +
      +
    • Add integration of mercurial and git commit logs.
    • +
    +

    Version 1.0.1

      diff -r ea6181255423 -r 671c1c8fbf1c src/main/webapp/WEB-INF/jsp/issue-view.jsp --- a/src/main/webapp/WEB-INF/jsp/issue-view.jsp Sat Jul 22 15:07:23 2023 +0200 +++ b/src/main/webapp/WEB-INF/jsp/issue-view.jsp Sat Jul 22 22:32:04 2023 +0200 @@ -156,6 +156,31 @@
      + + +

      + + + + + + + + + + + + + + + + + + + +
      ${commitLink.hash}
      +
      +

      diff -r ea6181255423 -r 671c1c8fbf1c src/main/webapp/WEB-INF/jsp/project-form.jsp --- a/src/main/webapp/WEB-INF/jsp/project-form.jsp Sat Jul 22 15:07:23 2023 +0200 +++ b/src/main/webapp/WEB-INF/jsp/project-form.jsp Sat Jul 22 22:32:04 2023 +0200 @@ -55,6 +55,17 @@ " /> + + + + + +