/* * Copyright (c) 2016 OBiBa. All rights reserved. * * This program and the accompanying materials * are made available under the terms of the GNU Public License v3.0. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.obiba.git.command; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.Collection; import java.util.Scanner; import java.util.Set; import org.apache.shiro.SecurityUtils; import org.apache.shiro.mgt.DefaultSecurityManager; import org.eclipse.jgit.api.errors.NoMessageException; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; import org.obiba.core.util.FileUtil; import org.obiba.git.CommitInfo; import org.obiba.git.GitException; import org.obiba.git.NoSuchGitRepositoryException; import org.obiba.git.TagInfo; import com.google.common.base.Charsets; import com.google.common.collect.Iterables; import com.google.common.io.CharStreams; import com.google.common.io.Files; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.fail; public class GitCommandsTest { private final GitCommandHandler handler = new GitCommandHandler(); private static File testFolder; @BeforeClass public static void init() { SecurityUtils.setSecurityManager(new DefaultSecurityManager()); testFolder = Files.createTempDir(); } @AfterClass public static void cleanup() { try { FileUtil.delete(testFolder); } catch(IOException e) { } } @Test @SuppressWarnings("ConstantConditions") public void test_create_read_files() throws Exception { File repo = getRepoPath(); createDummyFiles(repo); assertThat(readFile(repo, "root.txt")).isEqualTo("This is root file"); assertThat(readFile(repo, "dir/file.txt")).isEqualTo("This is a file in dir"); Iterable<CommitInfo> commitInfos = handler.execute(new LogsCommand.Builder(repo).build()); assertThat(commitInfos).hasSize(1); CommitInfo commitInfo = Iterables.getFirst(commitInfos, null); assertThat(commitInfo).isNotNull(); assertThat(commitInfo.getAuthorName()).isEqualTo(AbstractGitWriteCommand.DEFAULT_AUTHOR_NAME); assertThat(commitInfo.getAuthorEmail()).isEqualTo(AbstractGitWriteCommand.DEFAULT_AUTHOR_EMAIL); assertThat(commitInfo.isHead()).isTrue(); assertThat(commitInfo.isCurrent()).isTrue(); assertThat(commitInfo.getComment()).isEqualTo("Initial commit"); try { handler.execute(new ReadFileCommand.Builder(repo, "none").build()); fail("Should throw GitException"); } catch(GitException e) { assertThat(e).hasRootCauseExactlyInstanceOf(FileNotFoundException.class); } } @Test @SuppressWarnings("ConstantConditions") public void test_delete_files() throws Exception { File repo = getRepoPath(); createDummyFiles(repo); handler.execute(new DeleteFilesCommand.Builder(repo, "dir", "Deleting dir folder.").build()); assertThat(readFile(repo, "root.txt")).isEqualTo("This is root file"); try { readFile(repo, "dir/file.txt"); } catch(GitException e) { assertThat(e).hasRootCauseExactlyInstanceOf(FileNotFoundException.class); } handler.execute(new DeleteFilesCommand.Builder(repo, "root.txt", "Deleting root file").build()); try { assertThat(readFile(repo, "root.txt")); } catch(GitException e) { assertThat(e).hasRootCauseExactlyInstanceOf(FileNotFoundException.class); } } @Test public void test_empty_commit_comment() throws Exception { File repo = getRepoPath(); createDummyFiles(repo); try { handler.execute(new DeleteFilesCommand.Builder(repo, "dir", null).build()); } catch(GitException e) { assertThat(e).hasRootCauseExactlyInstanceOf(NoMessageException.class); } try { handler.execute(new DeleteFilesCommand.Builder(repo, "dir", "").build()); } catch(GitException e) { assertThat(e).hasRootCauseExactlyInstanceOf(NoMessageException.class); } } @Test public void test_exclude_file_delete_commits() throws Exception { File repo = getRepoPath(); createDummyFiles(repo); handler.execute(new DeleteFilesCommand.Builder(repo, "dir", "Deleting files").build()); Iterable<CommitInfo> commitInfos = handler .execute(new LogsCommand.Builder(repo).excludeDeletedCommits(true).build()); assertThat(commitInfos).hasSize(1); CommitInfo commitInfo = Iterables.getFirst(commitInfos, null); assertThat(commitInfo).isNotNull(); assertThat(commitInfo.getComment()).isEqualTo("Initial commit"); } @Test(expected = NoSuchGitRepositoryException.class) public void test_read_files_from_invalid_repo() throws Exception { handler.execute(new ReadFileCommand.Builder(getRepoPath(), "file.txt").build()); } @Test public void test_update_read_files() throws Exception { File repo = getRepoPath(); try(InputStream input = new FileInputStream(createFile("Version 1"))) { handler.execute(new AddFilesCommand.Builder(repo, "First commit").addFile("root.txt", input).build()); } try(InputStream input = new FileInputStream(createFile("Version 2"))) { handler.execute(new AddFilesCommand.Builder(repo, "Second commit").addFile("root.txt", input).build()); } Iterable<CommitInfo> commitInfos = handler.execute(new LogsCommand.Builder(repo).build()); assertThat(commitInfos).hasSize(2); assertThat(readFile(repo, "root.txt")).isEqualTo("Version 2"); } @Test @SuppressWarnings("ConstantConditions") public void test_tags() throws Exception { File repo = getRepoPath(); try(InputStream input = new FileInputStream(createFile("Version 1"))) { handler.execute(new AddFilesCommand.Builder(repo, "First commit").addFile("root.txt", input).build()); } assertThat(handler.execute(new TagListCommand.Builder(repo).build())).isEmpty(); handler.execute(new TagCommand.Builder(repo, "Test first tag", "1.0").build()); Iterable<TagInfo> tagInfos = handler.execute(new TagListCommand.Builder(repo).build()); assertThat(tagInfos).hasSize(1); TagInfo tagInfo = Iterables.getFirst(tagInfos, null); assertThat(tagInfo).isNotNull(); assertThat(tagInfo.getName()).isEqualTo("1.0"); assertThat(tagInfo.getCommitId()).isNotEmpty(); assertThat(readFileFromTag(repo, "root.txt", "1.0")).isEqualTo("Version 1"); assertThat(readFileFromCommit(repo, "root.txt", tagInfo.getCommitId())).isEqualTo("Version 1"); } @Test public void test_list_files_of_empty_repo() throws Exception { File repo = getRepoPath(); assertThat(handler.execute(new ListFilesCommand.Builder(repo).build())).isEmpty(); } @Test public void test_list_files_no_filter_not_recursive() throws Exception { File repo = getRepoPath(); createDummyFiles(repo); Collection<String> files = handler.execute(new ListFilesCommand.Builder(repo).build()); assertThat(files.size()).isEqualTo(2); assertThat(files.contains("dir")).isTrue(); assertThat(files.contains("root.txt")).isTrue(); } @Test public void test_list_files_no_filter_recursive() throws Exception { File repo = getRepoPath(); createDummyFiles(repo); Collection<String> files = handler.execute(new ListFilesCommand.Builder(repo).recursive(true).build()); assertThat(files.size()).isEqualTo(5); assertThat(files.contains("dir/file.txt")).isTrue(); assertThat(files.contains("root.txt")).isTrue(); } @Test public void test_list_files_filtered_recursive() throws Exception { File repo = getRepoPath(); createDummyFiles(repo); Collection<String> files = handler .execute(new ListFilesCommand.Builder(repo).recursive(true).filter("\\/_titi\\.txt|^root|\\.xml$").build()); assertThat(files.size()).isEqualTo(3); assertThat(files.contains("dir/toto.xml")).isTrue(); assertThat(files.contains("root.txt")).isTrue(); assertThat(files.contains("dir/tata/_titi.txt")).isTrue(); } @Test public void test_reading_files() throws Exception { File repo = getRepoPath(); createDummyFiles(repo); Set<InputStream> files = handler .execute(new ReadFilesCommand.Builder(repo).recursive(true).filter("\\/_titi\\.txt|^root|\\.xml$").build()); assertThat(files.size()).isEqualTo(3); for(InputStream is : files) { assertThat(readInputStream(is)).matches("This is another file in dir|This is root file|This is with folders"); } } private void createDummyFiles(File repo) throws IOException { try(InputStream input1 = new FileInputStream(createFile("This is root file")); InputStream input2 = new FileInputStream(createFile("This is a file in dir")); InputStream input3 = new FileInputStream(createFile("This is another file in dir")); InputStream input4 = new FileInputStream(createFile("This is yet another file in dir")); InputStream input5 = new FileInputStream(createFile("This is with folders"))) { handler.execute(new AddFilesCommand.Builder(repo, "Initial commit") // .addFile("root.txt", input1) // .addFile("dir/file.txt", input2) // .addFile("dir/toto.xml", input3) // .addFile("dir/tata_titi.txt", input4) // .addFile("dir/tata/_titi.txt", input5) // .build()); } } private File getRepoPath() throws IOException { File repo = File.createTempFile("obiba", ".git", testFolder); // delete it so we create a new repo if(!repo.delete()) { throw new IllegalStateException("Cannot delete git repo " + repo.getAbsolutePath()); } return repo; } private String readFile(File repo, String path) throws Exception { return readFile(repo, path, null, null); } private String readFileFromTag(File repo, String path, String tag) throws Exception { return readFile(repo, path, null, tag); } private String readFileFromCommit(File repo, String path, String commitId) throws Exception { return readFile(repo, path, commitId, null); } private String readFile(File repo, String path, String commitId, String tag) throws Exception { InputStream inputStream = handler .execute(new ReadFileCommand.Builder(repo, path).commitId(commitId).tag(tag).build()); return CharStreams.toString(new InputStreamReader(inputStream, Charsets.UTF_8)); } private File createFile(CharSequence content) throws IOException { File file = File.createTempFile("obiba", "git", testFolder); file.deleteOnExit(); Files.write(content, file, Charsets.UTF_8); return file; } private String readInputStream(InputStream is) { return new Scanner(is, "UTF-8").useDelimiter("\\A").next(); } }