Java tutorial
/** * Yobi, Project Hosting SW * * Copyright 2012 NAVER Corp. * http://yobi.io * * @Author Ahn Hyeok Jun * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package playRepository; import models.Project; import models.PullRequest; import models.User; import org.apache.commons.io.FileUtils; import com.fasterxml.jackson.databind.node.ObjectNode; import org.eclipse.jgit.api.CommitCommand; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.lib.RepositoryBuilder; import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.revwalk.RevTree; import org.eclipse.jgit.revwalk.RevWalk; import org.eclipse.jgit.transport.RefSpec; import org.eclipse.jgit.treewalk.TreeWalk; import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TestWatcher; import play.test.FakeApplication; import play.test.Helpers; import support.ExecutionTimeWatcher; import javax.naming.LimitExceededException; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.List; import java.util.Set; import static org.fest.assertions.Assertions.assertThat; import static org.fest.assertions.Fail.fail; import static play.test.Helpers.running; public class GitRepositoryTest { @Rule public TestWatcher watcher = new ExecutionTimeWatcher(); @Before public void before() { GitRepository.setRepoPrefix("resources/test/repo/git/"); } @After public void after() { support.Files.rm_rf(new File(GitRepository.getRepoPrefix())); } @Test public void gitRepository() throws Exception { // Given String userName = "yobi"; String projectName = "testProject"; // When GitRepository repo = new GitRepository(userName, projectName); // Then assertThat(repo).isNotNull(); } @Test public void create() throws Exception { // Given String userName = "yobi"; String projectName = "testProject"; GitRepository repo = new GitRepository(userName, projectName); // When repo.create(); // Then File file = new File(GitRepository.getRepoPrefix() + userName + "/" + projectName + ".git"); assertThat(file.exists()).isTrue(); file = new File(GitRepository.getRepoPrefix() + userName + "/" + projectName + ".git" + "/objects"); assertThat(file.exists()).isTrue(); file = new File(GitRepository.getRepoPrefix() + userName + "/" + projectName + ".git" + "/refs"); assertThat(file.exists()).isTrue(); // cleanup repo.close(); } @Test public void getPatch() throws IOException, GitAPIException { // given String userName = "yobi"; String projectName = "testProject"; String wcPath = GitRepository.getRepoPrefix() + userName + "/" + projectName; String repoPath = wcPath + "/.git"; File repoDir = new File(repoPath); Repository repo = new RepositoryBuilder().setGitDir(repoDir).build(); repo.create(false); Git git = new Git(repo); String testFilePath = wcPath + "/readme.txt"; BufferedWriter out = new BufferedWriter(new FileWriter(testFilePath)); // when out.write("hello 1"); out.flush(); git.add().addFilepattern("readme.txt").call(); git.commit().setMessage("commit 1").call(); out.write("hello 2"); out.flush(); git.add().addFilepattern("readme.txt").call(); RevCommit commit = git.commit().setMessage("commit 2").call(); GitRepository gitRepo = new GitRepository(userName, projectName + "/"); String patch = gitRepo.getPatch(commit.getId().getName()); // then assertThat(patch).contains("-hello 1"); assertThat(patch).contains("+hello 1hello 2"); } @Test public void getHistory() throws IOException, GitAPIException { // given String userName = "yobi"; String projectName = "testProject"; String wcPath = GitRepository.getRepoPrefix() + userName + "/" + projectName; String repoPath = wcPath + "/.git"; File repoDir = new File(repoPath); Repository repo = new RepositoryBuilder().setGitDir(repoDir).build(); repo.create(false); Git git = new Git(repo); String testFilePath = wcPath + "/readme.txt"; BufferedWriter out = new BufferedWriter(new FileWriter(testFilePath)); // when out.write("hello 1"); out.flush(); git.add().addFilepattern("readme.txt").call(); git.commit().setMessage("commit 1").call(); out.write("hello 2"); out.flush(); git.add().addFilepattern("readme.txt").call(); git.commit().setMessage("commit 2").call(); git.tag().setName("tag").setAnnotated(true).call(); out.write("hello 3"); out.flush(); git.add().addFilepattern("readme.txt").call(); git.commit().setMessage("commit 3").call(); GitRepository gitRepo = new GitRepository(userName, projectName + "/"); List<Commit> history2 = gitRepo.getHistory(0, 2, "HEAD", null); List<Commit> history5 = gitRepo.getHistory(0, 5, null, null); List<Commit> tagHistory2 = gitRepo.getHistory(0, 2, "tag", null); // then assertThat(history2.size()).isEqualTo(2); assertThat(history2.get(0).getMessage()).isEqualTo("commit 3"); assertThat(history2.get(1).getMessage()).isEqualTo("commit 2"); assertThat(history5.size()).isEqualTo(3); assertThat(history5.get(0).getMessage()).isEqualTo("commit 3"); assertThat(history5.get(1).getMessage()).isEqualTo("commit 2"); assertThat(history5.get(2).getMessage()).isEqualTo("commit 1"); assertThat(tagHistory2.size()).isEqualTo(2); assertThat(tagHistory2.get(0).getMessage()).isEqualTo("commit 2"); assertThat(tagHistory2.get(1).getMessage()).isEqualTo("commit 1"); } @Test public void cloneRepository() throws Exception { // Given String userName = "whiteship"; String projectName = "testProject"; Project original = createProject(userName, projectName); Project fork = createProject("keesun", projectName); support.Files.rm_rf(GitRepository.getGitDirectory(original)); support.Files.rm_rf(GitRepository.getGitDirectory(fork)); GitRepository fromRepo = new GitRepository(userName, projectName); fromRepo.create(); // When String gitUrl = GitRepository.getGitDirectoryURL(original); GitRepository.cloneRepository(gitUrl, fork); // Then File file = GitRepository.getGitDirectory(fork); assertThat(file.exists()).isTrue(); } @Test public void getMetaDataFromPath() throws Exception { // Given final String userName = "yobi"; final String projectName = "mytest"; final String branchName = "branch"; final String lightWeightTagName = "tag1"; final String annotatedTagName = "tag2"; String wcPath = GitRepository.getRepoPrefix() + userName + "/" + projectName; Repository repository = GitRepository.buildGitRepository(userName, projectName + "/"); repository.create(); Git git = new Git(repository); FileUtils.touch(new File(wcPath + "/hello")); FileUtils.touch(new File(wcPath + "/dir/world")); git.add().addFilepattern("hello").call(); git.add().addFilepattern("dir").call(); git.commit().setAuthor("yobi", "yobi@yobi.io").setMessage("test").call(); git.branchCreate().setName(branchName).call(); git.tag().setName(lightWeightTagName).setAnnotated(false).call(); git.tag().setName(annotatedTagName).setAnnotated(true).setMessage("annotated tag").call(); repository.close(); running(support.Helpers.makeTestApplication(), new Runnable() { @Override public void run() { try { // When GitRepository gitRepository = new GitRepository(userName, projectName + "/"); ObjectNode notExistBranch = gitRepository.getMetaDataFromPath("not_exist_branch", ""); ObjectNode root = gitRepository.getMetaDataFromPath(""); ObjectNode dir = gitRepository.getMetaDataFromPath("dir"); ObjectNode file = gitRepository.getMetaDataFromPath("hello"); ObjectNode branch = gitRepository.getMetaDataFromPath(branchName, ""); ObjectNode lightWeightTag = gitRepository.getMetaDataFromPath(lightWeightTagName, ""); ObjectNode annotatedTag = gitRepository.getMetaDataFromPath(annotatedTagName, ""); // Then assertThat(notExistBranch).isNull(); assertThat(root.get("type").textValue()).isEqualTo("folder"); assertThat(root.get("data").get("hello").get("type").textValue()).isEqualTo("file"); assertThat(root.get("data").get("dir").get("type").textValue()).isEqualTo("folder"); assertThat(dir.get("type").textValue()).isEqualTo("folder"); assertThat(dir.get("data").get("world").get("type").textValue()).isEqualTo("file"); assertThat(file.get("type").textValue()).isEqualTo("file"); assertThat(branch.toString()).isEqualTo(root.toString()); assertThat(lightWeightTag.toString()).isEqualTo(root.toString()); assertThat(annotatedTag.toString()).isEqualTo(root.toString()); } catch (Exception e) { throw new RuntimeException(e); } } }); } @Test public void deleteBranch() throws IOException, GitAPIException { // given Repository repository = support.Git.createRepository("keesun", "test", false); Git git = new Git(repository); String fileName = "readme.md"; String contents = "Hello World"; String commitMessage = "Initial commit"; addCommit(git, fileName, contents, commitMessage, null); git.branchCreate().setName("develop").setForce(true).call(); GitRepository.checkout(repository, "develop"); // When String branchName = "refs/heads/master"; GitRepository.deleteBranch(repository, branchName); // Then List<Ref> refs = git.branchList().call(); for (Ref ref : refs) { if (ref.getName().equals(branchName)) { fail("deleting branch was failed"); } } } public RevCommit addCommit(Git git, String fileName, String contents, String commitMessage, User author) throws IOException, GitAPIException { File newFile = new File(git.getRepository().getWorkTree().getAbsolutePath(), fileName); BufferedWriter out = new BufferedWriter(new FileWriter(newFile)); out.write(contents); out.flush(); git.add().addFilepattern(fileName).call(); CommitCommand commit = git.commit().setMessage(commitMessage); if (author != null) { commit.setAuthor(author.loginId, author.email).setCommitter(author.loginId, author.email); } return commit.call(); } @Test public void isFile() throws Exception { // Given String userName = "yobi"; String projectName = "mytest"; String wcPath = GitRepository.getRepoPrefix() + userName + "/" + projectName; String repoPath = wcPath + "/.git"; String dirName = "dir"; String fileName = "file"; Repository repository = new RepositoryBuilder().setGitDir(new File(repoPath)).build(); repository.create(false); Git git = new Git(repository); FileUtils.forceMkdir(new File(wcPath + "/" + dirName)); FileUtils.touch(new File(wcPath + "/" + fileName)); git.add().addFilepattern(dirName).call(); git.add().addFilepattern(fileName).call(); git.commit().setMessage("test").call(); repository.close(); // When GitRepository gitRepository = new GitRepository(userName, projectName + "/"); // Then assertThat(gitRepository.isFile(dirName)).isEqualTo(false); assertThat(gitRepository.isFile(fileName)).isEqualTo(true); assertThat(gitRepository.isFile("not_exist_file")).isEqualTo(false); assertThat(gitRepository.isFile(fileName, "not_exist_branch")).isEqualTo(false); } @Test public void testGetAllBranches() throws IOException, GitAPIException { FakeApplication app = support.Helpers.makeTestApplication(); Helpers.start(app); // Given String userName = "wansoon"; String projectName = "test"; Project project = createProject(userName, projectName); project.save(); String email = "test@email.com"; String wcPath = GitRepository.getRepoPrefix() + userName + "/" + "clone-" + projectName + ".git"; String repoPath = wcPath + "/.git"; String dirName = "dir"; String fileName = "file"; GitRepository gitRepository = new GitRepository(userName, projectName); gitRepository.create(); Repository repository = new RepositoryBuilder().setGitDir(new File(repoPath)).build(); repository.create(false); Git git = new Git(repository); FileUtils.forceMkdir(new File(wcPath + "/" + dirName)); FileUtils.touch(new File(wcPath + "/" + fileName)); git.add().addFilepattern(dirName).call(); git.add().addFilepattern(fileName).call(); git.commit().setMessage("test").setAuthor(userName, email).call(); String branchName = "testBranch"; git.branchCreate().setName(branchName).setForce(true).call(); git.push().setRemote(GitRepository.getGitDirectoryURL(project)) .setRefSpecs(new RefSpec(branchName + ":" + branchName)).setForce(true).call(); repository.close(); // When List<GitBranch> gitBranches = gitRepository.getBranches(); gitRepository.close(); // Then assertThat(gitBranches.size()).isEqualTo(1); assertThat(gitBranches.get(0).getShortName()).isEqualTo(branchName); Helpers.stop(app); } @Test public void getRelatedAuthors() throws IOException, GitAPIException, LimitExceededException { FakeApplication app = support.Helpers.makeTestApplication(); Helpers.start(app); Repository repository = support.Git.createRepository("yobi", "test", true); // Given User yobi = User.findByLoginId("yobi"); User laziel = User.findByLoginId("laziel"); User doortts = User.findByLoginId("doortts"); User nori = User.findByLoginId("nori"); Git git = new Git(repository); RevCommit from = addCommit(git, "README.md", "hello", "1st commit", yobi); addCommit(git, "test.txt", "text file", "2nd commit", laziel); addCommit(git, "test.txt", "edited text file", "3rd commit", doortts); RevCommit to = addCommit(git, "README.md", "hello, world!", "4th commit", nori); // When Set<User> authors = GitRepository.getRelatedAuthors(repository, from.getName(), to.getName()); // Then assertThat(authors).containsOnly(yobi); repository.close(); Helpers.stop(app); } private Project createProject(String owner, String name) { Project project = new Project(); project.owner = owner; project.name = name; return project; } private PullRequest createPullRequest(Project project) { PullRequest pullRequest = new PullRequest(); pullRequest.toProject = project; return pullRequest; } private byte[] getRawFile(Repository repository, String path) throws IOException { RevTree tree = new RevWalk(repository).parseTree(repository.resolve(Constants.HEAD)); TreeWalk treeWalk = TreeWalk.forPath(repository, path, tree); if (treeWalk.isSubtree()) { return null; } else { return repository.open(treeWalk.getObjectId(0)).getBytes(); } } @Test public void getDiff_bigFile() throws IOException, GitAPIException { // given String userName = "yobi"; String projectName = "testProject"; String wcPath = GitRepository.getRepoPrefix() + userName + "/" + projectName; String repoPath = wcPath + "/.git"; File repoDir = new File(repoPath); Repository repo = new RepositoryBuilder().setGitDir(repoDir).build(); repo.create(false); Git git = new Git(repo); String testFilePath = wcPath + "/readme.txt"; BufferedWriter out = new BufferedWriter(new FileWriter(testFilePath)); char[] cbuf = new char[FileDiff.SIZE_LIMIT + 1]; java.util.Arrays.fill(cbuf, 'a'); out.write(cbuf); // Add a big file out.flush(); git.add().addFilepattern("readme.txt").call(); RevCommit commit = git.commit().setMessage("commit 1").call(); // When FileDiff diff = GitRepository.getDiff(repo, commit).get(0); // Then assertThat(diff.a).describedAs("a").isNull(); assertThat(diff.b).describedAs("b").isNotNull(); assertThat(diff.hasError(FileDiff.Error.A_SIZE_EXCEEDED)).describedAs("a exceeds the size limit.") .isFalse(); assertThat(diff.hasError(FileDiff.Error.B_SIZE_EXCEEDED)).describedAs("b exceeds the size limit.").isTrue(); assertThat(diff.hasError(FileDiff.Error.DIFF_SIZE_EXCEEDED)).describedAs("The diff exceeds the size limit.") .isFalse(); assertThat(diff.hasError(FileDiff.Error.OTHERS_SIZE_EXCEEDED)) .describedAs("The others exceeds the size limit.").isFalse(); } @Test public void getDiff_manyLines() throws IOException, GitAPIException { // given String userName = "yobi"; String projectName = "testProject"; String wcPath = GitRepository.getRepoPrefix() + userName + "/" + projectName; String repoPath = wcPath + "/.git"; File repoDir = new File(repoPath); Repository repo = new RepositoryBuilder().setGitDir(repoDir).build(); repo.create(false); Git git = new Git(repo); String testFilePath = wcPath + "/readme.txt"; BufferedWriter out = new BufferedWriter(new FileWriter(testFilePath)); for (int i = 0; i < FileDiff.LINE_LIMIT + 1; i++) { out.write("a\n"); // Add a big file } out.flush(); git.add().addFilepattern("readme.txt").call(); RevCommit commit = git.commit().setMessage("commit 1").call(); // When FileDiff diff = GitRepository.getDiff(repo, commit).get(0); // Then assertThat(diff.hasError(FileDiff.Error.A_SIZE_EXCEEDED)).describedAs("a exceeds the size limit.") .isFalse(); assertThat(diff.hasError(FileDiff.Error.B_SIZE_EXCEEDED)).describedAs("b exceeds the size limit.").isTrue(); assertThat(diff.hasError(FileDiff.Error.DIFF_SIZE_EXCEEDED)).describedAs("The diff exceeds the size limit.") .isFalse(); assertThat(diff.hasError(FileDiff.Error.OTHERS_SIZE_EXCEEDED)) .describedAs("The others exceeds the size limit.").isFalse(); } @Test public void getDiff_smallChangeOfBigFile() throws IOException, GitAPIException { // given String userName = "yobi"; String projectName = "testProject"; String wcPath = GitRepository.getRepoPrefix() + userName + "/" + projectName; String repoPath = wcPath + "/.git"; File repoDir = new File(repoPath); Repository repo = new RepositoryBuilder().setGitDir(repoDir).build(); repo.create(false); Git git = new Git(repo); String testFilePath = wcPath + "/readme.txt"; BufferedWriter out = new BufferedWriter(new FileWriter(testFilePath)); // Commit a big file for (int i = 0; i < FileDiff.LINE_LIMIT + 1; i++) { out.write("a\n"); // Add a big file } out.flush(); git.add().addFilepattern("readme.txt").call(); git.commit().setMessage("commit 1").call(); // Modify the file out.write("b\n"); out.flush(); git.add().addFilepattern("readme.txt").call(); RevCommit commit = git.commit().setMessage("commit 2").call(); // When FileDiff diff = GitRepository.getDiff(repo, commit).get(0); // Then assertThat(diff.hasError(FileDiff.Error.A_SIZE_EXCEEDED)).describedAs("a exceeds the size limit.") .isFalse(); assertThat(diff.hasError(FileDiff.Error.B_SIZE_EXCEEDED)).describedAs("b exceeds the size limit.") .isFalse(); assertThat(diff.hasError(FileDiff.Error.DIFF_SIZE_EXCEEDED)).describedAs("The diff exceeds the size limit.") .isFalse(); assertThat(diff.hasError(FileDiff.Error.OTHERS_SIZE_EXCEEDED)) .describedAs("The others exceeds the size limit.").isFalse(); } @Test public void getDiff_manyFiles() throws IOException, GitAPIException { // given String userName = "yobi"; String projectName = "testProject"; String wcPath = GitRepository.getRepoPrefix() + userName + "/" + projectName; String repoPath = wcPath + "/.git"; File repoDir = new File(repoPath); Repository repo = new RepositoryBuilder().setGitDir(repoDir).build(); repo.create(false); Git git = new Git(repo); // Add four big files for (int i = 0; i < 4; i++) { String testFilePath = wcPath + "/" + i + ".txt"; BufferedWriter out = new BufferedWriter(new FileWriter(testFilePath)); char[] cbuf = new char[FileDiff.SIZE_LIMIT - 1]; java.util.Arrays.fill(cbuf, 'a'); out.write(cbuf); out.flush(); git.add().addFilepattern(i + ".txt").call(); } // Add a small file String testFilePath = wcPath + "/readme.txt"; BufferedWriter out = new BufferedWriter(new FileWriter(testFilePath)); out.write("hello"); out.flush(); git.add().addFilepattern("readme.txt").call(); RevCommit commit = git.commit().setMessage("commit 1").call(); // When List<FileDiff> diffs = GitRepository.getDiff(repo, commit); FileDiff diff = diffs.get(4); // Then assertThat(diff.hasError(FileDiff.Error.A_SIZE_EXCEEDED)).describedAs("a exceeds the size limit.") .isFalse(); assertThat(diff.hasError(FileDiff.Error.B_SIZE_EXCEEDED)).describedAs("b exceeds the size limit.") .isFalse(); assertThat(diff.hasError(FileDiff.Error.DIFF_SIZE_EXCEEDED)).describedAs("The diff exceeds the size limit.") .isFalse(); assertThat(diff.hasError(FileDiff.Error.OTHERS_SIZE_EXCEEDED)) .describedAs("The others exceeds the size limit.").isTrue(); } }