
code: new feature - revision compare
@4544c088215ab121f5301abf4ca788611a57feef
+++ app/controllers/CompareApp.java
... | ... | @@ -0,0 +1,65 @@ |
1 | +/** | |
2 | + * Yobi, Project Hosting SW | |
3 | + * | |
4 | + * Copyright 2013 NAVER Corp. | |
5 | + * http://yobi.io | |
6 | + * | |
7 | + * @Author kjkmadness | |
8 | + * | |
9 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
10 | + * you may not use this file except in compliance with the License. | |
11 | + * You may obtain a copy of the License at | |
12 | + * | |
13 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
14 | + * | |
15 | + * Unless required by applicable law or agreed to in writing, software | |
16 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
17 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
18 | + * See the License for the specific language governing permissions and | |
19 | + * limitations under the License. | |
20 | + */ | |
21 | +package controllers; | |
22 | + | |
23 | +import java.util.List; | |
24 | + | |
25 | +import controllers.annotation.IsAllowed; | |
26 | +import models.Project; | |
27 | +import models.enumeration.Operation; | |
28 | +import play.mvc.Controller; | |
29 | +import play.mvc.Result; | |
30 | +import playRepository.Commit; | |
31 | +import playRepository.FileDiff; | |
32 | +import playRepository.PlayRepository; | |
33 | +import playRepository.RepositoryService; | |
34 | +import utils.ErrorViews; | |
35 | +import views.html.code.compare_svn; | |
36 | +import views.html.code.compare; | |
37 | + | |
38 | +public class CompareApp extends Controller { | |
39 | + @IsAllowed(Operation.READ) | |
40 | + public static Result compare(String ownerName, String projectName, String revA, String revB) | |
41 | + throws Exception { | |
42 | + Project project = Project.findByOwnerAndProjectName(ownerName, projectName); | |
43 | + PlayRepository repository = RepositoryService.getRepository(project); | |
44 | + Commit commitA = repository.getCommit(revA); | |
45 | + Commit commitB = repository.getCommit(revB); | |
46 | + | |
47 | + if (commitA == null || commitB == null) { | |
48 | + return notFound(ErrorViews.NotFound.render("error.notfound.commit", project)); | |
49 | + } | |
50 | + | |
51 | + if (RepositoryService.VCS_SUBVERSION.equals(project.vcs)) { | |
52 | + String patch = repository.getPatch(revA, revB); | |
53 | + if (patch == null) { | |
54 | + return notFound(ErrorViews.NotFound.render("error.notfound", project)); | |
55 | + } | |
56 | + return ok(compare_svn.render(project, commitA, commitB, patch)); | |
57 | + } else { | |
58 | + List<FileDiff> diffs = repository.getDiff(revA, revB); | |
59 | + if (diffs == null) { | |
60 | + return notFound(ErrorViews.NotFound.render("error.notfound", project)); | |
61 | + } | |
62 | + return ok(compare.render(project, commitA, commitB, diffs)); | |
63 | + } | |
64 | + } | |
65 | +} |
--- app/playRepository/GitRepository.java
+++ app/playRepository/GitRepository.java
... | ... | @@ -576,32 +576,55 @@ |
576 | 576 |
*/ |
577 | 577 |
@Override |
578 | 578 |
public String getPatch(String rev) throws IOException { |
579 |
- // Get the trees, from current commit and its parent, as treeWalk. |
|
580 |
- ObjectId commitId = repository.resolve(rev); |
|
579 |
+ RevCommit commit = getRevCommit(rev); |
|
581 | 580 |
|
582 |
- if (commitId == null) { |
|
581 |
+ if (commit == null) { |
|
583 | 582 |
return null; |
584 | 583 |
} |
585 | 584 |
|
586 |
- TreeWalk treeWalk = new TreeWalk(repository); |
|
587 |
- RevWalk revWalk = new RevWalk(repository); |
|
588 |
- RevCommit commit = revWalk.parseCommit(commitId); |
|
585 |
+ RevCommit parent = null; |
|
589 | 586 |
if (commit.getParentCount() > 0) { |
590 |
- RevTree tree = revWalk.parseCommit(commit.getParent(0).getId()).getTree(); |
|
591 |
- treeWalk.addTree(tree); |
|
592 |
- } else { |
|
593 |
- treeWalk.addTree(new EmptyTreeIterator()); |
|
587 |
+ parent = commit.getParent(0); |
|
594 | 588 |
} |
595 |
- treeWalk.addTree(commit.getTree()); |
|
596 | 589 |
|
597 |
- // Render the difference from treeWalk which has two trees. |
|
590 |
+ return getPatch(parent, commit); |
|
591 |
+ } |
|
592 |
+ |
|
593 |
+ @Override |
|
594 |
+ public String getPatch(String revA, String revB) throws IOException { |
|
595 |
+ RevCommit commitA = getRevCommit(revA); |
|
596 |
+ RevCommit commitB = getRevCommit(revB); |
|
597 |
+ |
|
598 |
+ if (commitA == null || commitB == null) { |
|
599 |
+ return null; |
|
600 |
+ } |
|
601 |
+ |
|
602 |
+ return getPatch(commitA, commitB); |
|
603 |
+ } |
|
604 |
+ |
|
605 |
+ /* |
|
606 |
+ * Render the difference from treeWalk which has two trees. |
|
607 |
+ */ |
|
608 |
+ private String getPatch(RevCommit commitA, RevCommit commitB) throws IOException { |
|
609 |
+ TreeWalk treeWalk = new TreeWalk(repository); |
|
610 |
+ addTree(treeWalk, commitA); |
|
611 |
+ addTree(treeWalk, commitB); |
|
612 |
+ treeWalk.setRecursive(true); |
|
613 |
+ |
|
598 | 614 |
ByteArrayOutputStream out = new ByteArrayOutputStream(); |
599 | 615 |
DiffFormatter diffFormatter = new DiffFormatter(out); |
600 | 616 |
diffFormatter.setRepository(repository); |
601 |
- treeWalk.setRecursive(true); |
|
602 | 617 |
diffFormatter.format(DiffEntry.scan(treeWalk)); |
603 | 618 |
|
604 | 619 |
return out.toString("UTF-8"); |
620 |
+ } |
|
621 |
+ |
|
622 |
+ private void addTree(TreeWalk treeWalk, RevCommit commit) throws IOException { |
|
623 |
+ if (commit == null) { |
|
624 |
+ treeWalk.addTree(new EmptyTreeIterator()); |
|
625 |
+ } else { |
|
626 |
+ treeWalk.addTree(commit.getTree()); |
|
627 |
+ } |
|
605 | 628 |
} |
606 | 629 |
|
607 | 630 |
/** |
... | ... | @@ -1352,6 +1375,7 @@ |
1352 | 1375 |
return getDiff(repository, revA, repository, revB); |
1353 | 1376 |
} |
1354 | 1377 |
|
1378 |
+ @Override |
|
1355 | 1379 |
public List<FileDiff> getDiff(String revA, String revB) throws IOException { |
1356 | 1380 |
return getDiff(this.repository, revA, revB); |
1357 | 1381 |
} |
--- app/playRepository/PlayRepository.java
+++ app/playRepository/PlayRepository.java
... | ... | @@ -71,8 +71,12 @@ |
71 | 71 |
*/ |
72 | 72 |
public abstract String getPatch(String commitId) throws IOException, SVNException; |
73 | 73 |
|
74 |
+ String getPatch(String revA, String revB) throws IOException, SVNException; |
|
75 |
+ |
|
74 | 76 |
public abstract List<FileDiff> getDiff(String commitId) throws IOException; |
75 | 77 |
|
78 |
+ List<FileDiff> getDiff(String revA, String revB) throws IOException; |
|
79 |
+ |
|
76 | 80 |
/** |
77 | 81 |
* {@code untilRevName}에 해당하는 리비전까지의 커밋 목록을 반환한다. |
78 | 82 |
* |
--- app/playRepository/SVNRepository.java
+++ app/playRepository/SVNRepository.java
... | ... | @@ -227,9 +227,18 @@ |
227 | 227 |
|
228 | 228 |
@Override |
229 | 229 |
public String getPatch(String commitId) throws SVNException { |
230 |
+ long rev = Integer.parseInt(commitId); |
|
231 |
+ return getPatch(rev - 1, rev); |
|
232 |
+ } |
|
233 |
+ |
|
234 |
+ @Override |
|
235 |
+ public String getPatch(String revA, String revB) throws SVNException { |
|
236 |
+ return getPatch(Long.parseLong(revA), Long.parseLong(revB)); |
|
237 |
+ } |
|
238 |
+ |
|
239 |
+ private String getPatch(long revA, long revB) throws SVNException { |
|
230 | 240 |
// Prepare required arguments. |
231 | 241 |
SVNURL svnURL = SVNURL.fromFile(new File(getRepoPrefix() + ownerName + "/" + projectName)); |
232 |
- long rev = Integer.parseInt(commitId); |
|
233 | 242 |
|
234 | 243 |
// Get diffClient. |
235 | 244 |
SVNClientManager clientManager = SVNClientManager.newInstance(); |
... | ... | @@ -238,9 +247,8 @@ |
238 | 247 |
// Using diffClient, write the changes by commitId into |
239 | 248 |
// byteArrayOutputStream, as unified format. |
240 | 249 |
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); |
241 |
- diffClient.doDiff(svnURL, null, SVNRevision.create(rev - 1), SVNRevision.create(rev), |
|
250 |
+ diffClient.doDiff(svnURL, null, SVNRevision.create(revA), SVNRevision.create(revB), |
|
242 | 251 |
SVNDepth.INFINITY, true, byteArrayOutputStream); |
243 |
- |
|
244 | 252 |
|
245 | 253 |
return byteArrayOutputStream.toString(); |
246 | 254 |
} |
... | ... | @@ -251,6 +259,11 @@ |
251 | 259 |
} |
252 | 260 |
|
253 | 261 |
@Override |
262 |
+ public List<FileDiff> getDiff(String revA, String revB) throws IOException { |
|
263 |
+ throw new UnsupportedOperationException(); |
|
264 |
+ } |
|
265 |
+ |
|
266 |
+ @Override |
|
254 | 267 |
public List<Commit> getHistory(int page, int limit, String until, String path) throws |
255 | 268 |
IOException, GitAPIException, SVNException { |
256 | 269 |
// Get the repository |
+++ app/views/code/compare.scala.html
... | ... | @@ -0,0 +1,45 @@ |
1 | +@** | |
2 | +* Yobi, Project Hosting SW | |
3 | +* | |
4 | +* Copyright 2013 NAVER Corp. | |
5 | +* http://yobi.io | |
6 | +* | |
7 | +* @Author kjkmadness | |
8 | +* | |
9 | +* Licensed under the Apache License, Version 2.0 (the "License"); | |
10 | +* you may not use this file except in compliance with the License. | |
11 | +* You may obtain a copy of the License at | |
12 | +* | |
13 | +* http://www.apache.org/licenses/LICENSE-2.0 | |
14 | +* | |
15 | +* Unless required by applicable law or agreed to in writing, software | |
16 | +* distributed under the License is distributed on an "AS IS" BASIS, | |
17 | +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
18 | +* See the License for the specific language governing permissions and | |
19 | +* limitations under the License. | |
20 | +**@ | |
21 | +@(project: Project, commitA: playRepository.Commit, commitB: playRepository.Commit, diff: List[playRepository.FileDiff]) | |
22 | +@projectLayout(commitA.getId + ".." + commitB.getId, project, utils.MenuType.CODE) { | |
23 | +@projectMenu(project, utils.MenuType.CODE, "main-menu-only") | |
24 | +<div class="project-page-wrap"> | |
25 | + <div class="code-browse-wrap"> | |
26 | + <p class="commitInfo"> | |
27 | + <strong class="commitId">@{"@"}@commitA.getId..@commitB.getId</strong> | |
28 | + </p> | |
29 | + @if(diff.isEmpty){ | |
30 | + <div class="alert">@Messages("code.noChanges")</div> | |
31 | + } else { | |
32 | + <div class="diff-body"> | |
33 | + @views.html.partial_diff(diff, null, project, project) | |
34 | + </div> | |
35 | + } | |
36 | + </div> | |
37 | +</div> | |
38 | +<script type="text/javascript"> | |
39 | + $(document).ready(function(){ | |
40 | + $yobi.loadModule("code.Diff", { | |
41 | + "bCommentable": false, | |
42 | + }); | |
43 | + }); | |
44 | +</script> | |
45 | +} |
+++ app/views/code/compare_svn.scala.html
... | ... | @@ -0,0 +1,53 @@ |
1 | +@** | |
2 | +* Yobi, Project Hosting SW | |
3 | +* | |
4 | +* Copyright 2013 NAVER Corp. | |
5 | +* http://yobi.io | |
6 | +* | |
7 | +* @Author kjkmadness | |
8 | +* | |
9 | +* Licensed under the Apache License, Version 2.0 (the "License"); | |
10 | +* you may not use this file except in compliance with the License. | |
11 | +* You may obtain a copy of the License at | |
12 | +* | |
13 | +* http://www.apache.org/licenses/LICENSE-2.0 | |
14 | +* | |
15 | +* Unless required by applicable law or agreed to in writing, software | |
16 | +* distributed under the License is distributed on an "AS IS" BASIS, | |
17 | +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
18 | +* See the License for the specific language governing permissions and | |
19 | +* limitations under the License. | |
20 | +**@ | |
21 | +@(project: Project, commitA: playRepository.Commit, commitB: playRepository.Commit, patch: String) | |
22 | + | |
23 | +@import org.apache.commons.lang3.StringUtils | |
24 | + | |
25 | +@projectLayout(commitA.getId + ".." + commitB.getId, project, utils.MenuType.CODE) { | |
26 | +@projectMenu(project, utils.MenuType.CODE, "main-menu-only") | |
27 | +<div class="project-page-wrap"> | |
28 | + <div class="code-browse-wrap"> | |
29 | + <p class="commitInfo"> | |
30 | + <strong class="commitId">@{"@"}@commitA.getId..@commitB.getId</strong> | |
31 | + </p> | |
32 | + @if(StringUtils.isEmpty(patch)){ | |
33 | + <div class="alert">@Messages("code.noChanges")</div> | |
34 | + } else { | |
35 | + <div class="diff-wrap"> | |
36 | + <div id="commit" data-commit-origin="true" class="diff-body hide">@patch</div> | |
37 | + </div> | |
38 | + } | |
39 | + </div> | |
40 | +</div> | |
41 | +@common.mergely() | |
42 | +<script type="text/javascript"> | |
43 | + $(document).ready(function(){ | |
44 | + $yobi.loadModule("code.SvnDiff", { | |
45 | + "bCommentable" : false, | |
46 | + "sParentCommitId": "@commitA.getId", | |
47 | + "sCommitId" : "@commitB.getId", | |
48 | + "sTplFileURL" : "@routes.CodeApp.codeBrowserWithBranch(project.owner, project.name, "${commitId}", "${path}")", | |
49 | + "sTplRawURL" : "@routes.CodeApp.showRawFile(project.owner, project.name, "${commitId}", "${path}")" | |
50 | + }); | |
51 | + }); | |
52 | +</script> | |
53 | +} |
--- conf/routes
+++ conf/routes
... | ... | @@ -238,5 +238,8 @@ |
238 | 238 |
POST /:user/:project/pullRequest/:number/review controllers.ReviewApp.review(user, project, number: Long) |
239 | 239 |
POST /:user/:project/pullRequest/:number/unreview controllers.ReviewApp.unreview(user, project, number: Long) |
240 | 240 |
|
241 |
+# Compare |
|
242 |
+GET /:user/:project/compare/:revA..:revB controllers.CompareApp.compare(user, project, revA, revB) |
|
243 |
+ |
|
241 | 244 |
# remove trailing slash - must be the bottom of this file |
242 | 245 |
GET /*paths controllers.Application.removeTrailer(paths) |
Add a comment
Delete comment
Once you delete this comment, you won't be able to recover it. Are you sure you want to delete this comment?