#20 -- some improvements

This commit is contained in:
Anton Romanov 2021-04-20 12:26:43 +04:00
parent 4fd8a510f3
commit fb0c605206
17 changed files with 232 additions and 75 deletions

View File

@ -13,6 +13,7 @@ import ru.ulstu.extractor.repository.BranchRepository;
import ru.ulstu.extractor.repository.RepositoryRepository; import ru.ulstu.extractor.repository.RepositoryRepository;
import springfox.documentation.annotations.ApiIgnore; import springfox.documentation.annotations.ApiIgnore;
import static ru.ulstu.extractor.controller.Route.DELETE_BRANCH;
import static ru.ulstu.extractor.controller.Route.LIST_REPOSITORY_BRANCHES; import static ru.ulstu.extractor.controller.Route.LIST_REPOSITORY_BRANCHES;
@Controller @Controller
@ -34,4 +35,14 @@ public class BranchController {
model.addAttribute("repository", repositoryRepository.findById(repositoryId).get()); model.addAttribute("repository", repositoryRepository.findById(repositoryId).get());
return LIST_REPOSITORY_BRANCHES; return LIST_REPOSITORY_BRANCHES;
} }
@GetMapping(DELETE_BRANCH)
public String deleteBranch(Model model,
@RequestParam int repositoryId,
@RequestParam Integer id) {
branchRepository.deleteById(id);
model.addAttribute("branches", branchRepository.findByRepositoryId(repositoryId));
model.addAttribute("repository", repositoryRepository.findById(repositoryId).get());
return LIST_REPOSITORY_BRANCHES;
}
} }

View File

@ -44,5 +44,4 @@ public class RepoController {
indexService.index(repositoryUrl, branchName); indexService.index(repositoryUrl, branchName);
return true; return true;
} }
} }

View File

@ -8,9 +8,11 @@ package ru.ulstu.extractor.controller;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.ui.Model; import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import ru.ulstu.extractor.repository.RepositoryRepository; import ru.ulstu.extractor.repository.RepositoryRepository;
import springfox.documentation.annotations.ApiIgnore; import springfox.documentation.annotations.ApiIgnore;
import static ru.ulstu.extractor.controller.Route.DELETE_INDEXED_REPOSITORY;
import static ru.ulstu.extractor.controller.Route.LIST_INDEXED_REPOSITORIES; import static ru.ulstu.extractor.controller.Route.LIST_INDEXED_REPOSITORIES;
@Controller @Controller
@ -27,4 +29,12 @@ public class RepositoryController {
model.addAttribute("repositories", repositoryRepository.findAll()); model.addAttribute("repositories", repositoryRepository.findAll());
return LIST_INDEXED_REPOSITORIES; return LIST_INDEXED_REPOSITORIES;
} }
@GetMapping(DELETE_INDEXED_REPOSITORY)
public String deleteRepo(Model model,
@RequestParam Integer id) {
repositoryRepository.deleteById(id);
model.addAttribute("repositories", repositoryRepository.findAll());
return "redirect:/" + LIST_INDEXED_REPOSITORIES;
}
} }

View File

@ -10,7 +10,9 @@ import org.springframework.stereotype.Component;
@Component @Component
public class Route { public class Route {
public static final String LIST_INDEXED_REPOSITORIES = "listRepositories"; public static final String LIST_INDEXED_REPOSITORIES = "listRepositories";
public static final String DELETE_INDEXED_REPOSITORY = "deleteRepository";
public static final String LIST_REPOSITORY_BRANCHES = "listBranches"; public static final String LIST_REPOSITORY_BRANCHES = "listBranches";
public static final String DELETE_BRANCH = "deleteBranch";
public static final String INDEXING_NEW_REPOSITORY = "indexNewRepository"; public static final String INDEXING_NEW_REPOSITORY = "indexNewRepository";
public static final String FILTER_COMMITS = "filterCommits"; public static final String FILTER_COMMITS = "filterCommits";
public static final String STATISTIC = "statistic"; public static final String STATISTIC = "statistic";

View File

@ -1,12 +1,12 @@
/*
* Copyright (C) 2021 Anton Romanov - All Rights Reserved
* You may use, distribute and modify this code, please write to: romanov73@gmail.com.
*/
package ru.ulstu.extractor.model; package ru.ulstu.extractor.model;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import javax.persistence.CascadeType;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.FetchType; import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne; import javax.persistence.ManyToOne;
import javax.persistence.OneToMany; import javax.persistence.OneToMany;
import java.util.ArrayList; import java.util.ArrayList;
@ -19,9 +19,7 @@ public class Branch extends BaseEntity {
@ManyToOne @ManyToOne
private Repository repository; private Repository repository;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY) @OneToMany(fetch = FetchType.LAZY, mappedBy = "branch")
@JoinColumn(name = "branch_id", unique = true)
@Fetch(FetchMode.SUBSELECT)
private List<Commit> commits = new ArrayList<>(); private List<Commit> commits = new ArrayList<>();
public Branch() { public Branch() {

View File

@ -1,19 +0,0 @@
package ru.ulstu.extractor.model;
import java.util.ArrayList;
import java.util.List;
public class Changes {
private List<FileChange> fileChanges = new ArrayList<>();
public Changes() {
}
public Changes(List<FileChange> fileChanges) {
this.fileChanges = fileChanges;
}
public List<FileChange> getFileChanges() {
return fileChanges;
}
}

View File

@ -23,13 +23,13 @@ public class Commit extends BaseEntity {
private String hash; private String hash;
private Date date; private Date date;
private String message; private String message;
@ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY) @ManyToOne(fetch = FetchType.LAZY)
private Author author; private Author author;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY) @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinColumn(name = "commit_id", unique = true) @JoinColumn(name = "commit_id", unique = true)
@Fetch(FetchMode.SUBSELECT) @Fetch(FetchMode.SUBSELECT)
private List<FileChange> fileChanges = new ArrayList<>(); private List<FileChange> fileChanges = new ArrayList<>();
@ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY) @ManyToOne(fetch = FetchType.LAZY)
private Branch branch; private Branch branch;
public Commit() { public Commit() {

View File

@ -13,17 +13,16 @@ import javax.persistence.Entity;
import javax.persistence.FetchType; import javax.persistence.FetchType;
import javax.persistence.JoinColumn; import javax.persistence.JoinColumn;
import javax.persistence.OneToMany; import javax.persistence.OneToMany;
import javax.persistence.Transient;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@Entity @Entity
public class FileChange extends BaseEntity { public class FileChange extends BaseEntity {
private String file; private String file;
@Transient
private boolean removed; private Boolean removed;
@Transient
private boolean added; private Boolean added;
private Boolean containsEntity; private Boolean containsEntity;
@ -45,11 +44,11 @@ public class FileChange extends BaseEntity {
return file; return file;
} }
public boolean getRemoved() { public Boolean getRemoved() {
return removed; return removed;
} }
public boolean getAdded() { public Boolean getAdded() {
return added; return added;
} }
@ -73,11 +72,11 @@ public class FileChange extends BaseEntity {
this.lineChanges = lineChanges; this.lineChanges = lineChanges;
} }
public boolean isRemoved() { public Boolean isRemoved() {
return removed; return removed;
} }
public boolean isAdded() { public Boolean isAdded() {
return added; return added;
} }

View File

@ -1,14 +1,18 @@
/*
* Copyright (C) 2021 Anton Romanov - All Rights Reserved
* You may use, distribute and modify this code, please write to: romanov73@gmail.com.
*/
package ru.ulstu.extractor.model; package ru.ulstu.extractor.model;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.Transient;
@Entity @Entity
public class LineChange extends BaseEntity { public class LineChange extends BaseEntity {
@Transient
private boolean added; private Boolean added;
@Transient
private boolean removed; private Boolean removed;
private String lineFrom; private String lineFrom;
private String lineTo; private String lineTo;
@ -48,19 +52,19 @@ public class LineChange extends BaseEntity {
return lineTo; return lineTo;
} }
public boolean isAdded() { public Boolean isAdded() {
return added; return added;
} }
public void setAdded(boolean added) { public void setAdded(Boolean added) {
this.added = added; this.added = added;
} }
public boolean isRemoved() { public Boolean isRemoved() {
return removed; return removed;
} }
public void setRemoved(boolean removed) { public void setRemoved(Boolean removed) {
this.removed = removed; this.removed = removed;
} }
} }

View File

@ -16,4 +16,6 @@ import java.util.List;
public interface AuthorRepository extends JpaRepository<Author, Integer> { public interface AuthorRepository extends JpaRepository<Author, Integer> {
@Query("SELECT DISTINCT a.name FROM Commit c, Repository r, Branch b, Author a WHERE c.author = a AND c.branch = b AND r = b.repository AND r = :repository AND b.name = :branchName AND a.name IS NOT NULL AND a.name <> '' ORDER BY a.name") @Query("SELECT DISTINCT a.name FROM Commit c, Repository r, Branch b, Author a WHERE c.author = a AND c.branch = b AND r = b.repository AND r = :repository AND b.name = :branchName AND a.name IS NOT NULL AND a.name <> '' ORDER BY a.name")
List<String> findByRepositoryAndBranch(@Param("repository") Repository repository, @Param("branchName") String branchName); List<String> findByRepositoryAndBranch(@Param("repository") Repository repository, @Param("branchName") String branchName);
List<Author> findByName(String name);
} }

View File

@ -0,0 +1,31 @@
/*
* Copyright (C) 2021 Anton Romanov - All Rights Reserved
* You may use, distribute and modify this code, please write to: romanov73@gmail.com.
*/
package ru.ulstu.extractor.service;
import org.springframework.stereotype.Service;
import ru.ulstu.extractor.model.Author;
import ru.ulstu.extractor.repository.AuthorRepository;
import javax.transaction.Transactional;
import java.util.Optional;
@Service
public class AuthorService {
private final AuthorRepository authorRepository;
public AuthorService(AuthorRepository authorRepository) {
this.authorRepository = authorRepository;
}
@Transactional
public Author findOrCreate(Author author) {
Optional<Author> newAuthor = authorRepository.findByName(author.getName()).stream().findAny();
if (newAuthor.isEmpty()) {
return authorRepository.save(author);
}
return newAuthor.get();
}
}

View File

@ -0,0 +1,40 @@
/*
* Copyright (C) 2021 Anton Romanov - All Rights Reserved
* You may use, distribute and modify this code, please write to: romanov73@gmail.com.
*/
package ru.ulstu.extractor.service;
import org.springframework.stereotype.Service;
import ru.ulstu.extractor.model.Branch;
import ru.ulstu.extractor.model.Commit;
import ru.ulstu.extractor.model.Repository;
import ru.ulstu.extractor.repository.BranchRepository;
import javax.transaction.Transactional;
import java.util.List;
@Service
public class BranchService {
private final BranchRepository branchRepository;
private final CommitService commitService;
public BranchService(BranchRepository branchRepository,
CommitService commitService) {
this.branchRepository = branchRepository;
this.commitService = commitService;
}
@Transactional
public Branch save(Branch branch, List<Commit> commits) {
List<Commit> commitsToRemove = branch.getCommits();
branch.getCommits().clear();
commitService.delete(commitsToRemove);
branch.setCommits(commitService.save(commits));
return branchRepository.save(branch);
}
public Branch findByRepositoryAndName(Repository repository, String branchName) {
return branchRepository.findByRepositoryAndName(repository, branchName);
}
}

View File

@ -1,3 +1,8 @@
/*
* Copyright (C) 2021 Anton Romanov - All Rights Reserved
* You may use, distribute and modify this code, please write to: romanov73@gmail.com.
*/
package ru.ulstu.extractor.service; package ru.ulstu.extractor.service;
import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.api.errors.GitAPIException;
@ -7,17 +12,26 @@ import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import ru.ulstu.extractor.model.Commit; import ru.ulstu.extractor.model.Commit;
import ru.ulstu.extractor.repository.CommitRepository;
import javax.transaction.Transactional;
import java.io.IOException; import java.io.IOException;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
@Service @Service
public class CommitService { public class CommitService {
private final GitRepositoryService gitRepositoryService; private final GitRepositoryService gitRepositoryService;
private final CommitRepository commitRepository;
private final AuthorService authorService;
public CommitService(GitRepositoryService gitRepositoryService) { public CommitService(GitRepositoryService gitRepositoryService,
CommitRepository commitRepository,
AuthorService authorService) {
this.gitRepositoryService = gitRepositoryService; this.gitRepositoryService = gitRepositoryService;
this.commitRepository = commitRepository;
this.authorService = authorService;
} }
public Page<Commit> findPaginated(Pageable pageable, String repositoryUrl, String branchName) throws GitAPIException, IOException { public Page<Commit> findPaginated(Pageable pageable, String repositoryUrl, String branchName) throws GitAPIException, IOException {
@ -34,6 +48,19 @@ public class CommitService {
} }
return new PageImpl<>(commits, PageRequest.of(currentPage, pageSize), commits.size()); return new PageImpl<>(commits, PageRequest.of(currentPage, pageSize), commits.size());
} }
public void delete(List<Commit> commitsToRemove) {
commitRepository.deleteAll(commitsToRemove);
}
@Transactional
public List<Commit> save(List<Commit> commits) {
return commits.stream()
.map(commit -> {
commit.setAuthor(authorService.findOrCreate(commit.getAuthor()));
return commitRepository.save(commit);
}).collect(Collectors.toList());
}
} }

View File

@ -12,7 +12,6 @@ import org.springframework.transaction.annotation.Transactional;
import ru.ulstu.extractor.model.Branch; import ru.ulstu.extractor.model.Branch;
import ru.ulstu.extractor.model.Commit; import ru.ulstu.extractor.model.Commit;
import ru.ulstu.extractor.model.Repository; import ru.ulstu.extractor.model.Repository;
import ru.ulstu.extractor.repository.BranchRepository;
import ru.ulstu.extractor.repository.CommitRepository; import ru.ulstu.extractor.repository.CommitRepository;
import ru.ulstu.extractor.repository.RepositoryRepository; import ru.ulstu.extractor.repository.RepositoryRepository;
@ -23,17 +22,20 @@ import java.util.List;
public class IndexService { public class IndexService {
private final GitRepositoryService gitRepositoryService; private final GitRepositoryService gitRepositoryService;
private final RepositoryRepository repositoryRepository; private final RepositoryRepository repositoryRepository;
private final BranchRepository branchRepository; private final BranchService branchService;
private final CommitRepository commitRepository; private final CommitRepository commitRepository;
private final AuthorService authorService;
public IndexService(GitRepositoryService gitRepositoryService, public IndexService(GitRepositoryService gitRepositoryService,
RepositoryRepository repositoryRepository, RepositoryRepository repositoryRepository,
BranchRepository branchRepository, BranchService branchService,
CommitRepository commitRepository) { CommitRepository commitRepository,
AuthorService authorService) {
this.gitRepositoryService = gitRepositoryService; this.gitRepositoryService = gitRepositoryService;
this.repositoryRepository = repositoryRepository; this.repositoryRepository = repositoryRepository;
this.branchRepository = branchRepository; this.branchService = branchService;
this.commitRepository = commitRepository; this.commitRepository = commitRepository;
this.authorService = authorService;
} }
@Transactional @Transactional
@ -42,15 +44,11 @@ public class IndexService {
if (repository == null) { if (repository == null) {
repository = repositoryRepository.save(new Repository(repositoryUrl)); repository = repositoryRepository.save(new Repository(repositoryUrl));
} }
Branch branch = branchRepository.findByRepositoryAndName(repository, branchName); Branch branch = branchService.findByRepositoryAndName(repository, branchName);
if (branch == null) { if (branch == null) {
branch = branchRepository.save(new Branch(repository, branchName)); branch = new Branch(repository, branchName);
} }
List<Commit> commits = gitRepositoryService.getCommits(repositoryUrl, branchName); List<Commit> commits = gitRepositoryService.getCommits(repositoryUrl, branchName);
List<Commit> commitsToRemove = branch.getCommits(); branchService.save(branch, commits);
branch.getCommits().clear();
commitRepository.deleteAll(commitsToRemove);
branch.setCommits(commits);
branchRepository.save(branch);
} }
} }

View File

@ -17,4 +17,41 @@
<column name="contains_business_logic" type="boolean"/> <column name="contains_business_logic" type="boolean"/>
</addColumn> </addColumn>
</changeSet> </changeSet>
<changeSet author="orion" id="20210420-100000-1">
<addColumn tableName="file_change">
<column name="removed" type="boolean"/>
<column name="added" type="boolean"/>
</addColumn>
<addColumn tableName="line_change">
<column name="removed" type="boolean"/>
<column name="added" type="boolean"/>
</addColumn>
</changeSet>
<changeSet author="orion" id="20210420-100000-2">
<dropForeignKeyConstraint baseTableName="branch" constraintName="fk_repository"/>
<addForeignKeyConstraint baseTableName="branch" baseColumnNames="repository_id" constraintName="fk_repository"
referencedTableName="repository" referencedColumnNames="id" onDelete="CASCADE"
onUpdate="CASCADE"/>
<dropForeignKeyConstraint baseTableName="file_change" constraintName="fk_commit"/>
<addForeignKeyConstraint baseTableName="file_change" baseColumnNames="commit_id" constraintName="fk_commit"
referencedTableName="commit" referencedColumnNames="id" onDelete="CASCADE"
onUpdate="CASCADE"/>
<dropForeignKeyConstraint baseTableName="line_change" constraintName="fk_file_change"/>
<addForeignKeyConstraint baseTableName="line_change" baseColumnNames="file_change_id"
constraintName="fk_file_change" referencedTableName="file_change"
referencedColumnNames="id" onDelete="CASCADE"
onUpdate="CASCADE"/>
<dropForeignKeyConstraint baseTableName="commit" constraintName="fk_author"/>
<addForeignKeyConstraint baseTableName="commit" baseColumnNames="author_id" constraintName="fk_author"
referencedTableName="author" referencedColumnNames="id" onDelete="CASCADE"
onUpdate="CASCADE"/>
<dropForeignKeyConstraint baseTableName="commit" constraintName="fk_branch"/>
<addForeignKeyConstraint baseTableName="commit" baseColumnNames="branch_id" constraintName="fk_branch"
referencedTableName="branch" referencedColumnNames="id" onDelete="CASCADE"
onUpdate="CASCADE"/>
</changeSet>
</databaseChangeLog> </databaseChangeLog>

View File

@ -12,13 +12,22 @@
<thead class="thead-dark"> <thead class="thead-dark">
<tr> <tr>
<th scope="col">Ветки</th> <th scope="col">Ветки</th>
<th width="10%"></th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr th:each="branch: ${branches}"> <tr th:each="branch: ${branches}">
<td> <td>
<a th:href="@{${@route.FILTER_COMMITS} + '?branchName='+${branch.name}+'&repositoryUrl='+${repository.url}}" <a th:href="@{${@route.FILTER_COMMITS} + '?branchName='+${branch.name}+'&repositoryUrl='+${repository.url}}"
th:text="${branch.name}"/></td> th:text="${branch.name}"/>
</td>
<td>
<a role="button" class="btn btn-danger"
th:href="@{'deleteBranch?id=' + ${branch.id} + '&repositoryId='+${repository.id}}"
onclick="return confirm('Удалить ветку?')">
<i class="fa fa-times" aria-hidden="true"></i>
</a>
</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>

View File

@ -8,18 +8,27 @@
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{default}"> layout:decorate="~{default}">
<div class="container" layout:fragment="content"> <div class="container" layout:fragment="content">
<form action="#" th:action="${@route.LIST_INDEXED_REPOSITORIES}" method="POST">
<table class="table table-striped"> <table class="table table-striped">
<thead class="thead-dark"> <thead class="thead-dark">
<tr> <tr>
<th scope="col">Репозиторий</th> <th scope="col">Репозиторий</th>
<th></th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr th:each="repo: ${repositories}"> <tr th:each="repo: ${repositories}">
<td><a th:href="@{${@route.LIST_REPOSITORY_BRANCHES} + '?repositoryId=' + ${repo.id}}" <td><a th:href="@{${@route.LIST_REPOSITORY_BRANCHES} + '?repositoryId=' + ${repo.id}}"
th:text="${repo.url}"></a></td> th:text="${repo.url}"></a></td>
<td>
<a role="button" class="btn btn-danger" th:href="@{'deleteRepository?id=' + ${repo.id}}"
onclick="return confirm('Удалить репозиторий?')">
<i class="fa fa-times" aria-hidden="true"></i>
</a>
</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
</form>
</div> </div>
</html> </html>