Skip to content

Commit ba35766

Browse files
committed
(refs #12)Implementing Gist fork
1 parent caa0a0a commit ba35766

File tree

12 files changed

+157
-27
lines changed

12 files changed

+157
-27
lines changed
1.36 KB
Loading
1.34 KB
Loading

src/main/resources/update/1_3.sql

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
ALTER TABLE GIST ADD COLUMN ORIGIN_USER_NAME VARCHAR(100);
2+
ALTER TABLE GIST ADD COLUMN ORIGIN_REPOSITORY_NAME VARCHAR(100);
3+
ALTER TABLE GIST ADD COLUMN PARENT_USER_NAME VARCHAR(100);
4+
ALTER TABLE GIST ADD COLUMN PARENT_REPOSITORY_NAME VARCHAR(100);

src/main/scala/Plugin.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ class Plugin extends gitbucket.core.plugin.Plugin {
1919
override val description: String = "Provides Gist feature on GitBucket."
2020

2121
override val versions: List[Version] = List(
22+
Version(1, 3),
2223
Version(1, 2),
2324
Version(1, 0)
2425
)
@@ -46,6 +47,8 @@ class Plugin extends gitbucket.core.plugin.Plugin {
4647
override val images = Seq(
4748
"images/menu-revisions-active.png" -> fromClassPath("images/menu-revisions-active.png"),
4849
"images/menu-revisions.png" -> fromClassPath("images/menu-revisions.png"),
50+
"images/menu-forks-active.png" -> fromClassPath("images/menu-forks-active.png"),
51+
"images/menu-forks.png" -> fromClassPath("images/menu-forks.png"),
4952
"images/snippet.png" -> fromClassPath("images/snippet.png")
5053
)
5154

src/main/scala/gitbucket/gist/controller/GistController.scala

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package gitbucket.gist.controller
33
import java.io.File
44
import jp.sf.amateras.scalatra.forms._
55

6-
import gitbucket.core.model.Account
76
import gitbucket.core.controller.ControllerBase
87
import gitbucket.core.service.AccountService
98
import gitbucket.core.util._
@@ -204,10 +203,14 @@ trait GistControllerBase extends ControllerBase {
204203
}
205204
}
206205
}
206+
207207
val gist = getGist(userName, repoName).get
208+
val originUserName = gist.originUserName.getOrElse(userName)
209+
val originRepoName = gist.originRepositoryName.getOrElse(repoName)
210+
208211
html.revisions(
209-
"revision",
210212
gist,
213+
getForkedCount(originUserName, originRepoName),
211214
GistRepositoryURL(gist, baseUrl, context.settings),
212215
isEditable(userName),
213216
commits
@@ -281,6 +284,51 @@ trait GistControllerBase extends ControllerBase {
281284
html.editor(count, "", JGitUtil.ContentInfo("text", None, Some("UTF-8")))
282285
}
283286

287+
post("/gist/:userName/:repoName/fork")(usersOnly {
288+
val userName = params("userName")
289+
val repoName = params("repoName")
290+
val loginAccount = context.loginAccount.get
291+
292+
if(getGist(loginAccount.userName, repoName).isDefined){
293+
redirect(s"${context.path}/gist/${userName}/${repoName}")
294+
} else {
295+
getGist(userName, repoName).map { gist =>
296+
// Insert to the database at first
297+
val originUserName = gist.originUserName.getOrElse(gist.userName)
298+
val originRepoName = gist.originRepositoryName.getOrElse(gist.repositoryName)
299+
300+
registerGist(loginAccount.userName, repoName, gist.isPrivate, gist.title, gist.description,
301+
Some(originUserName), Some(originRepoName), Some(userName), Some(repoName))
302+
303+
// Clone repository
304+
JGitUtil.cloneRepository(
305+
new File(GistRepoDir, userName + "/" + repoName),
306+
new File(GistRepoDir, loginAccount.userName + "/" + repoName)
307+
)
308+
309+
redirect(s"${context.path}/gist/${loginAccount.userName}/${repoName}")
310+
311+
} getOrElse NotFound
312+
}
313+
})
314+
315+
get("/gist/:userName/:repoName/forks"){
316+
val userName = params("userName")
317+
val repoName = params("repoName")
318+
319+
val gist = getGist(userName, repoName).get
320+
val originUserName = gist.originUserName.getOrElse(userName)
321+
val originRepoName = gist.originRepositoryName.getOrElse(repoName)
322+
323+
html.forks(
324+
gist,
325+
getForkedCount(originUserName, originRepoName),
326+
GistRepositoryURL(gist, baseUrl, context.settings),
327+
getForkedGists(originUserName, originRepoName),
328+
isEditable(userName)
329+
)
330+
}
331+
284332
private def _gist(userName: String, repoName: Option[String] = None, revision: String = "master") = {
285333
repoName match {
286334
case None => {
@@ -318,14 +366,16 @@ trait GistControllerBase extends ControllerBase {
318366
if(gitdir.exists){
319367
using(Git.open(gitdir)){ git =>
320368
val gist = getGist(userName, repoName).get
369+
val originUserName = gist.originUserName.getOrElse(userName)
370+
val originRepoName = gist.originRepositoryName.getOrElse(repoName)
321371

322372
if(!gist.isPrivate || context.loginAccount.exists(x => x.isAdmin || x.userName == userName)){
323373
val files: Seq[(String, String)] = JGitUtil.getFileList(git, revision, ".").map { file =>
324374
file.name -> StringUtil.convertFromByteArray(JGitUtil.getContentFromId(git, file.id, true).get)
325375
}
326376
html.detail(
327-
"code",
328377
gist,
378+
getForkedCount(originUserName, originRepoName),
329379
GistRepositoryURL(gist, baseUrl, context.settings),
330380
revision,
331381
files,

src/main/scala/gitbucket/gist/model/Gist.scala

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,18 @@ trait GistComponent { self: gitbucket.core.model.Profile =>
77
lazy val Gists = TableQuery[Gists]
88

99
class Gists(tag: Tag) extends Table[Gist](tag, "GIST") {
10-
val userName = column[String]("USER_NAME")
11-
val repositoryName = column[String]("REPOSITORY_NAME")
12-
val isPrivate = column[Boolean]("PRIVATE")
13-
val title = column[String]("TITLE")
14-
val description = column[String]("DESCRIPTION")
15-
val registeredDate = column[java.util.Date]("REGISTERED_DATE")
16-
val updatedDate = column[java.util.Date]("UPDATED_DATE")
17-
def * = (userName, repositoryName, isPrivate, title, description, registeredDate, updatedDate) <> (Gist.tupled, Gist.unapply)
10+
val userName = column[String]("USER_NAME")
11+
val repositoryName = column[String]("REPOSITORY_NAME")
12+
val isPrivate = column[Boolean]("PRIVATE")
13+
val title = column[String]("TITLE")
14+
val description = column[String]("DESCRIPTION")
15+
val registeredDate = column[java.util.Date]("REGISTERED_DATE")
16+
val updatedDate = column[java.util.Date]("UPDATED_DATE")
17+
val originUserName = column[String]("ORIGIN_USER_NAME")
18+
val originRepositoryName = column[String]("ORIGIN_REPOSITORY_NAME")
19+
val parentUserName = column[String]("PARENT_USER_NAME")
20+
val parentRepositoryName = column[String]("PARENT_REPOSITORY_NAME")
21+
def * = (userName, repositoryName, isPrivate, title, description, registeredDate, updatedDate, originUserName.?, originRepositoryName.?, parentUserName.?, parentRepositoryName.?) <> (Gist.tupled, Gist.unapply)
1822
}
1923
}
2024

@@ -25,7 +29,11 @@ case class Gist(
2529
title: String,
2630
description: String,
2731
registeredDate: java.util.Date,
28-
updatedDate: java.util.Date
32+
updatedDate: java.util.Date,
33+
originUserName: Option[String],
34+
originRepositoryName: Option[String],
35+
parentUserName: Option[String],
36+
parentRepositoryName: Option[String]
2937
)
3038

3139

src/main/scala/gitbucket/gist/service/GistService.scala

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,17 @@ trait GistService {
3333
def getGist(userName: String, repositoryName: String)(implicit s: Session): Option[Gist] =
3434
Gists.filter(t => (t.userName === userName.bind) && (t.repositoryName === repositoryName.bind)).firstOption
3535

36-
def registerGist(userName: String, repositoryName: String, isPrivate: Boolean, title: String, description: String)(implicit s: Session): Unit =
37-
Gists.insert(Gist(userName, repositoryName, isPrivate, title, description, new java.util.Date(), new java.util.Date()))
36+
def getForkedCount(userName: String, repositoryName: String)(implicit s: Session): Int =
37+
Query(Gists.filter(t => (t.originUserName === userName.bind) && (t.originRepositoryName === repositoryName.bind)).length).first
38+
39+
def getForkedGists(userName: String, repositoryName: String)(implicit s: Session): List[Gist] =
40+
Gists.filter(t => (t.originUserName === userName.bind) && (t.originRepositoryName === repositoryName.bind)).sortBy(_.userName).list
41+
42+
def registerGist(userName: String, repositoryName: String, isPrivate: Boolean, title: String, description: String,
43+
originUserName: Option[String] = None, originRepositoryName: Option[String] = None,
44+
parentUserName: Option[String] = None, parentRepositoryName: Option[String] = None)(implicit s: Session): Unit =
45+
Gists.insert(Gist(userName, repositoryName, isPrivate, title, description, new java.util.Date(), new java.util.Date(),
46+
originUserName, originRepositoryName, parentUserName, parentRepositoryName))
3847

3948
def updateGist(userName: String, repositoryName: String, title: String, description: String)(implicit s: Session): Unit =
4049
Gists

src/main/twirl/gitbucket/gist/detail.scala.html

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
@(active: String,
2-
gist: gitbucket.gist.model.Gist,
1+
@(gist: gitbucket.gist.model.Gist,
2+
forkedCount: Int,
33
repositoryUrl: gitbucket.gist.util.GistUtils.GistRepositoryURL,
44
revision: String,
55
files: Seq[(String, String)],
@@ -8,9 +8,9 @@
88
@import gitbucket.core.view.helpers._
99
@import gitbucket.core.service.RepositoryService.RepositoryInfo
1010
@gitbucket.core.html.main(if(gist.description.isEmpty) gist.repositoryName else gist.description){
11-
@gitbucket.gist.html.header(gist, editable)
11+
@gitbucket.gist.html.header(gist, forkedCount, editable)
1212
<div class="container body">
13-
@gitbucket.gist.html.menu(active, gist, repositoryUrl)
13+
@gitbucket.gist.html.menu("code", gist, repositoryUrl)
1414
<div style="margin-right: 180px;">
1515
<div style="margin-bottom: 10px;">
1616
@gist.description
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
@(gist: gitbucket.gist.model.Gist,
2+
forkedCount: Int,
3+
repositoryUrl: gitbucket.gist.util.GistUtils.GistRepositoryURL,
4+
forkedGists: List[gitbucket.gist.model.Gist],
5+
editable: Boolean)(implicit context: gitbucket.core.controller.Context)
6+
@import context._
7+
@import gitbucket.core.view.helpers._
8+
@gitbucket.core.html.main("Snippets"){
9+
@gitbucket.gist.html.header(gist, forkedCount, editable)
10+
<div class="container body">
11+
@gitbucket.gist.html.menu("forks", gist, repositoryUrl)
12+
<div style="margin-right: 180px;">
13+
@forkedGists.map { forkedGist =>
14+
<div class="block">
15+
@avatar(forkedGist.userName, 20)
16+
<a href="@path/gist/@forkedGist.userName/@forkedGist.repositoryName">@forkedGist.userName</a>
17+
<div class="pull-right">
18+
<a href="@path/gist/@forkedGist.userName/@forkedGist.repositoryName" class="btn btn-small">View Fork</a>
19+
</div>
20+
</div>
21+
}
22+
</div>
23+
</div>
24+
}
Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
@(gist: gitbucket.gist.model.Gist,
2+
forkedCount: Int,
23
editable: Boolean)(implicit context: gitbucket.core.controller.Context)
34
@import context._
45
@import gitbucket.core.view.helpers._
@@ -10,15 +11,40 @@
1011
@if(gist.isPrivate){
1112
<span class="label label-warning">Secret</span>
1213
}
13-
@if(editable){
14-
<div class="pull-right">
15-
<a href="@path/gist/@gist.userName/@gist.repositoryName/edit" class="btn">Edit</a>
16-
<a href="@path/gist/@gist.userName/@gist.repositoryName/delete" class="btn" id="delete">Delete</a>
14+
<div class="pull-right">
15+
@if(editable){
16+
<a href="@path/gist/@gist.userName/@gist.repositoryName/edit" class="btn btn-small">Edit</a>
17+
<a href="@path/gist/@gist.userName/@gist.repositoryName/delete" class="btn btn-small" id="delete">Delete</a>
18+
}
19+
<div class="input-prepend" style="margin-bottom: 0px;">
20+
@if(loginAccount.isEmpty){
21+
<a title="You must be signed in to fork a repository" href="@path/signin" class="btn btn-small">Fork</a>
22+
} else {
23+
<a id="fork-link" href="javascript:void(0);" class="btn btn-small">Fork</a>
24+
}
25+
<span class="add-on count"><a href="@path/gist/@gist.userName/@gist.repositoryName/forks">@forkedCount</a></span>
1726
</div>
18-
}
27+
@if(loginAccount.isDefined){
28+
<form id="fork-form" method="post" action="@path/gist/@gist.userName/@gist.repositoryName/fork">
29+
@*
30+
<input type="hidden" name="account" value="@loginAccount.get.userName"/>
31+
*@
32+
</form>
33+
}
34+
</div>
1935
</div>
2036
<div class="muted" style="margin-top: -10px; margin-left: 30px;">
2137
Created at @gist.registeredDate
2238
</div>
2339
</div>
2440
<hr style="margin-bottom: 20px;"/>
41+
<script>
42+
$(function(){
43+
@if(loginAccount.isDefined){
44+
$(document).on("click", "a#fork-link", function(e) {
45+
e.preventDefault();
46+
$('#fork-form').submit();
47+
});
48+
}
49+
});
50+
</script>

0 commit comments

Comments
 (0)