diff --git a/build.gradle b/build.gradle index f1c0e32..b061bd3 100644 --- a/build.gradle +++ b/build.gradle @@ -71,6 +71,7 @@ dependencies { compile group: 'org.webjars', name: 'bootstrap', version: '4.6.0' compile group: 'org.webjars', name: 'bootstrap-select', version: '1.13.8' compile group: 'org.webjars', name: 'font-awesome', version: '4.7.0' + compile group: 'org.webjars', name: 'highcharts', version: '7.0.0' testCompile group: 'org.springframework.boot', name: 'spring-boot-starter-test' } diff --git a/src/main/java/ru/ulstu/extractor/config/MvcConfiguration.java b/src/main/java/ru/ulstu/extractor/config/MvcConfiguration.java index 2355ca1..035f359 100644 --- a/src/main/java/ru/ulstu/extractor/config/MvcConfiguration.java +++ b/src/main/java/ru/ulstu/extractor/config/MvcConfiguration.java @@ -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.config; import org.springframework.context.annotation.Configuration; @@ -5,12 +10,14 @@ import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import static ru.ulstu.extractor.controller.Route.LIST_INDEXED_REPOSITORIES; + @Configuration public class MvcConfiguration implements WebMvcConfigurer { @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/{articlename:\\w+}"); - registry.addRedirectViewController("/", "/newRepo"); + registry.addRedirectViewController("/", LIST_INDEXED_REPOSITORIES); registry.addRedirectViewController("/default", "/home"); } diff --git a/src/main/java/ru/ulstu/extractor/controller/BranchController.java b/src/main/java/ru/ulstu/extractor/controller/BranchController.java index 8254210..031dc48 100644 --- a/src/main/java/ru/ulstu/extractor/controller/BranchController.java +++ b/src/main/java/ru/ulstu/extractor/controller/BranchController.java @@ -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.controller; import org.springframework.stereotype.Controller; @@ -7,6 +12,8 @@ import org.springframework.web.bind.annotation.RequestParam; import ru.ulstu.extractor.repository.BranchRepository; import ru.ulstu.extractor.repository.RepositoryRepository; +import static ru.ulstu.extractor.controller.Route.LIST_REPOSITORY_BRANCHES; + @Controller public class BranchController { private final RepositoryRepository repositoryRepository; @@ -17,12 +24,12 @@ public class BranchController { this.branchRepository = branchRepository; } - @GetMapping("/details") + @GetMapping(LIST_REPOSITORY_BRANCHES) public String indexBranch( Model model, @RequestParam int repositoryId) { model.addAttribute("branches", branchRepository.findByRepositoryId(repositoryId)); model.addAttribute("repository", repositoryRepository.findById(repositoryId).get()); - return "indexBranch"; + return LIST_REPOSITORY_BRANCHES; } } diff --git a/src/main/java/ru/ulstu/extractor/controller/GitFilteringController.java b/src/main/java/ru/ulstu/extractor/controller/GitFilteringController.java index 85ef6aa..e172698 100644 --- a/src/main/java/ru/ulstu/extractor/controller/GitFilteringController.java +++ b/src/main/java/ru/ulstu/extractor/controller/GitFilteringController.java @@ -1,9 +1,13 @@ +/* + * 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.controller; import org.springframework.data.domain.Page; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; -import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; @@ -11,47 +15,43 @@ import ru.ulstu.extractor.model.Commit; import ru.ulstu.extractor.model.OffsetablePageRequest; import ru.ulstu.extractor.model.mvc.FilterForm; import ru.ulstu.extractor.service.FilteringService; -import ru.ulstu.extractor.service.IndexService; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; import java.util.stream.IntStream; +import static ru.ulstu.extractor.controller.Route.FILTER_COMMITS; + @Controller public class GitFilteringController { + private final static int DEFAULT_PAGE_SIZE = 20; private final FilteringService filteringService; - private final IndexService indexService; - public GitFilteringController(FilteringService filteringService, - IndexService indexService) { + public GitFilteringController(FilteringService filteringService) { this.filteringService = filteringService; - this.indexService = indexService; } - /* @PostMapping("/sendFilter") - public String sendFilter(@ModelAttribute FilterForm filterForm, Model model) throws GitAPIException, IOException { - List list = gitRepositoryService.getCommits(filterForm.getUrl(), filterForm.getBranch()); - model.addAttribute("commits", list); - if (filterForm.getFilter() == null || filterForm.getFilter().isEmpty()) { - model.addAttribute("error", "'Строка' не должно быть пустым"); - return "filtering"; - } - return "resultRepo"; - }*/ - - @RequestMapping(value = "/filtering", method = RequestMethod.GET) + @RequestMapping(value = FILTER_COMMITS, method = RequestMethod.GET) public String listCommits( Model model, - @ModelAttribute FilterForm filterForm, - @RequestParam("page") Optional page, - @RequestParam("size") Optional size, - @RequestParam String repositoryUrl, - @RequestParam String branchName) { + @RequestParam Optional page, + @RequestParam Optional size, + @RequestParam Optional repositoryUrl, + @RequestParam Optional branchName, + @RequestParam Optional author, + @RequestParam Optional filter) { int currentPage = page.orElse(1); - int pageSize = size.orElse(5); + int pageSize = size.orElse(DEFAULT_PAGE_SIZE); + + String notEmptyRepositoryUrl = repositoryUrl.orElseThrow(() -> new RuntimeException("Url repository not present")); + String notEmptyBranchName = branchName.orElseThrow(() -> new RuntimeException("Branch name not present")); - Page commitsPage = indexService.getCommits(repositoryUrl, branchName, new OffsetablePageRequest(currentPage, pageSize)); + Page commitsPage = filteringService.getCommits(notEmptyRepositoryUrl, + notEmptyBranchName, + author.orElse(null), + filter.orElse(null), + new OffsetablePageRequest(currentPage - 1, pageSize)); int totalPages = commitsPage.getTotalPages(); if (totalPages > 0) { List pageNumbers = IntStream.rangeClosed(1, totalPages) @@ -59,11 +59,17 @@ public class GitFilteringController { .collect(Collectors.toList()); model.addAttribute("pageNumbers", pageNumbers); } - filterForm = new FilterForm(); + FilterForm filterForm = new FilterForm(); filterForm.setCommitsPage(commitsPage); - filterForm.setBranch(branchName); - filterForm.setUrl(repositoryUrl); + filterForm.setBranchName(notEmptyBranchName); + filterForm.setRepositoryUrl(notEmptyRepositoryUrl); + filterForm.setAuthor(author.orElse(null)); + filterForm.setFilter(filter.orElse(null)); model.addAttribute("filterForm", filterForm); - return "filtering"; + model.addAttribute("authors", filteringService.getRepositoryAuthors( + notEmptyRepositoryUrl, + notEmptyBranchName + )); + return FILTER_COMMITS; } } diff --git a/src/main/java/ru/ulstu/extractor/controller/GitIndexingController.java b/src/main/java/ru/ulstu/extractor/controller/GitIndexingController.java index 18ddb48..fb6f694 100644 --- a/src/main/java/ru/ulstu/extractor/controller/GitIndexingController.java +++ b/src/main/java/ru/ulstu/extractor/controller/GitIndexingController.java @@ -1,5 +1,13 @@ +/* + * 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.controller; +import org.eclipse.jgit.api.errors.GitAPIException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; @@ -13,10 +21,15 @@ import ru.ulstu.extractor.model.mvc.RepoForm; import ru.ulstu.extractor.service.GitRepositoryService; import ru.ulstu.extractor.service.IndexService; +import java.io.IOException; import java.util.List; +import static ru.ulstu.extractor.controller.Route.FILTER_COMMITS; +import static ru.ulstu.extractor.controller.Route.INDEXING_NEW_REPOSITORY; + @Controller public class GitIndexingController { + private final static Logger LOG = LoggerFactory.getLogger(GitIndexingController.class); private final GitRepositoryService gitRepositoryService; private final IndexService indexService; @@ -26,40 +39,39 @@ public class GitIndexingController { this.indexService = indexService; } - @GetMapping("/newRepo") + @GetMapping(INDEXING_NEW_REPOSITORY) public String indexNewRepo(Model model) { model.addAttribute(new RepoForm()); - return "newRepo"; + return INDEXING_NEW_REPOSITORY; } - @RequestMapping(value = "/newRepo", method = RequestMethod.POST, params = "send") + @RequestMapping(value = INDEXING_NEW_REPOSITORY, method = RequestMethod.POST, params = "send") public String getBranch(@ModelAttribute RepoForm repoForm, Model model) { try { - gitRepositoryService.cloneOrUpdateRepo(repoForm.getRepo()); - List branches = gitRepositoryService.getBranches(repoForm.getRepo()); + List branches = gitRepositoryService.getRemoteBranches(repoForm.getRepo()); model.addAttribute("branches", branches); - return "newRepo"; } catch (Exception ex) { model.addAttribute("error", ex.getMessage()); - return "newRepo"; } + return INDEXING_NEW_REPOSITORY; } - @RequestMapping(value = "/newRepo", method = RequestMethod.POST, params = "next") - public String setBranch(@ModelAttribute RepoForm repoForm, Model model, RedirectAttributes redirectAttributes) { + @RequestMapping(value = INDEXING_NEW_REPOSITORY, method = RequestMethod.POST, params = "next") + public String indexBranch(@ModelAttribute RepoForm repoForm, Model model, RedirectAttributes redirectAttributes) { model.addAttribute("filterForm", new FilterForm(repoForm.getRepo())); if (repoForm.getBranch() == null) { - return "newRepo"; + return INDEXING_NEW_REPOSITORY; } else { try { indexService.index(repoForm.getRepo(), repoForm.getBranch()); - } catch (Exception ex) { + } catch (IOException | GitAPIException ex) { + ex.printStackTrace(); model.addAttribute("error", ex.getMessage()); - return "newRepo"; + return INDEXING_NEW_REPOSITORY; } redirectAttributes.addAttribute("repositoryUrl", repoForm.getRepo()); redirectAttributes.addAttribute("branchName", repoForm.getBranch()); - return "redirect:/filtering"; + return "redirect:/" + FILTER_COMMITS; } } } diff --git a/src/main/java/ru/ulstu/extractor/controller/RepoController.java b/src/main/java/ru/ulstu/extractor/controller/RepoController.java index 09ea5d5..98fafbf 100644 --- a/src/main/java/ru/ulstu/extractor/controller/RepoController.java +++ b/src/main/java/ru/ulstu/extractor/controller/RepoController.java @@ -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.controller; import org.eclipse.jgit.api.errors.GitAPIException; @@ -7,6 +12,7 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import ru.ulstu.extractor.model.Commit; import ru.ulstu.extractor.service.GitRepositoryService; +import ru.ulstu.extractor.service.IndexService; import java.io.IOException; import java.util.List; @@ -18,14 +24,12 @@ import static ru.ulstu.extractor.controller.RepoController.URL; public class RepoController { public static final String URL = "/"; private final GitRepositoryService gitRepositoryService; + private final IndexService indexService; - public RepoController(GitRepositoryService gitRepositoryService) { + public RepoController(GitRepositoryService gitRepositoryService, + IndexService indexService) { this.gitRepositoryService = gitRepositoryService; - } - - @GetMapping("clone") - public void cloneRepository(@RequestParam("url") String url) throws GitAPIException, IOException { - gitRepositoryService.cloneOrUpdateRepo(url); + this.indexService = indexService; } @GetMapping("commits") @@ -34,4 +38,11 @@ public class RepoController { return gitRepositoryService.getCommits(repositoryUrl, branchName); } + @GetMapping("index") + public Boolean indexRepository(@RequestParam("repositoryUrl") String repositoryUrl, + @RequestParam("branchName") String branchName) throws GitAPIException, IOException { + indexService.index(repositoryUrl, branchName); + return true; + } + } diff --git a/src/main/java/ru/ulstu/extractor/controller/BaseIndexingController.java b/src/main/java/ru/ulstu/extractor/controller/RepositoryController.java similarity index 54% rename from src/main/java/ru/ulstu/extractor/controller/BaseIndexingController.java rename to src/main/java/ru/ulstu/extractor/controller/RepositoryController.java index e2a154a..9401504 100644 --- a/src/main/java/ru/ulstu/extractor/controller/BaseIndexingController.java +++ b/src/main/java/ru/ulstu/extractor/controller/RepositoryController.java @@ -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.controller; import org.springframework.stereotype.Controller; @@ -5,17 +10,19 @@ import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import ru.ulstu.extractor.repository.RepositoryRepository; +import static ru.ulstu.extractor.controller.Route.LIST_INDEXED_REPOSITORIES; + @Controller -public class BaseIndexingController { +public class RepositoryController { private final RepositoryRepository repositoryRepository; - public BaseIndexingController(RepositoryRepository repositoryRepository) { + public RepositoryController(RepositoryRepository repositoryRepository) { this.repositoryRepository = repositoryRepository; } - @GetMapping("/indexRepo") + @GetMapping(LIST_INDEXED_REPOSITORIES) public String indexNewRepo(Model model) { model.addAttribute("repositories", repositoryRepository.findAll()); - return "indexRepo"; + return LIST_INDEXED_REPOSITORIES; } } diff --git a/src/main/java/ru/ulstu/extractor/controller/Route.java b/src/main/java/ru/ulstu/extractor/controller/Route.java new file mode 100644 index 0000000..8a0282e --- /dev/null +++ b/src/main/java/ru/ulstu/extractor/controller/Route.java @@ -0,0 +1,37 @@ +/* + * 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.controller; + +import org.springframework.stereotype.Component; + +@Component +public class Route { + public static final String LIST_INDEXED_REPOSITORIES = "listRepositories"; + public static final String LIST_REPOSITORY_BRANCHES = "listBranches"; + public static final String INDEXING_NEW_REPOSITORY = "indexNewRepository"; + public static final String FILTER_COMMITS = "filterCommits"; + public static final String STATISTIC = "statistic"; + + public static String getLIST_INDEXED_REPOSITORIES() { + return LIST_INDEXED_REPOSITORIES; + } + + public static String getLIST_REPOSITORY_BRANCHES() { + return LIST_REPOSITORY_BRANCHES; + } + + public static String getINDEXING_NEW_REPOSITORY() { + return INDEXING_NEW_REPOSITORY; + } + + public static String getFILTER_COMMITS() { + return FILTER_COMMITS; + } + + public static String getSTATISTIC() { + return STATISTIC; + } +} diff --git a/src/main/java/ru/ulstu/extractor/controller/StatisticController.java b/src/main/java/ru/ulstu/extractor/controller/StatisticController.java new file mode 100644 index 0000000..55f1f33 --- /dev/null +++ b/src/main/java/ru/ulstu/extractor/controller/StatisticController.java @@ -0,0 +1,53 @@ +/* + * 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.controller; + +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import ru.ulstu.extractor.repository.CommitRepository; + +import java.util.List; +import java.util.stream.Collectors; + +import static ru.ulstu.extractor.controller.Route.STATISTIC; + +@Controller +public class StatisticController { + private final CommitRepository commitRepository; + + public StatisticController(CommitRepository commitRepository) { + this.commitRepository = commitRepository; + } + + @GetMapping(STATISTIC) + public String indexBranch(Model model) { + List authorCommits = commitRepository.getCommitAuthorStatistic().stream() + .map(stat -> new Object[]{stat.getAuthor(), stat.getCountCommit()}) + .collect(Collectors.toList()); + model.addAttribute("commitAuthorData", authorCommits); + List urlCommits = commitRepository.getCommitUrlStatistic().stream() + .map(stat -> new Object[]{stat.getUrl(), stat.getCountCommit()}) + .collect(Collectors.toList()); + model.addAttribute("commitUrlData", urlCommits); + List timeCommits = commitRepository.getCommitTimeStatistic().stream() + .map(stat -> new Object[]{stat.getDate(), stat.getCountCommit()}) + .collect(Collectors.toList()); + model.addAttribute("commitTimeData", timeCommits); + String[] date = new String[timeCommits.size()]; + for (int i = 0; i < timeCommits.size(); i++) { + date[i] = timeCommits.get(i)[0].toString(); + } + model.addAttribute("dates", date); + String[] url = new String[urlCommits.size()]; + for (int i = 0; i < urlCommits.size(); i++) { + url[i] = urlCommits.get(i)[0].toString().substring(urlCommits.get(i)[0].toString().lastIndexOf("/") + 1); + } + model.addAttribute("urls", url); + + return STATISTIC; + } +} diff --git a/src/main/java/ru/ulstu/extractor/model/CommitAuthorStatistic.java b/src/main/java/ru/ulstu/extractor/model/CommitAuthorStatistic.java new file mode 100644 index 0000000..5587cb2 --- /dev/null +++ b/src/main/java/ru/ulstu/extractor/model/CommitAuthorStatistic.java @@ -0,0 +1,20 @@ +package ru.ulstu.extractor.model; + +public class CommitAuthorStatistic { + private String author; + private Long countCommit; + + public CommitAuthorStatistic(String author, Long countCommit) { + this.author = author; + this.countCommit = countCommit; + } + + public String getAuthor() { + return author; + } + + public Long getCountCommit() { + return countCommit; + } + +} diff --git a/src/main/java/ru/ulstu/extractor/model/CommitTimeStatistic.java b/src/main/java/ru/ulstu/extractor/model/CommitTimeStatistic.java new file mode 100644 index 0000000..7828896 --- /dev/null +++ b/src/main/java/ru/ulstu/extractor/model/CommitTimeStatistic.java @@ -0,0 +1,22 @@ +package ru.ulstu.extractor.model; + +import java.util.Date; + +public class CommitTimeStatistic { + private Date date; + private Long countCommit; + + public CommitTimeStatistic(Date date, Long countCommit) { + this.date = date; + this.countCommit = countCommit; + } + + public Date getDate() { + return date; + } + + public Long getCountCommit() { + return countCommit; + } + +} diff --git a/src/main/java/ru/ulstu/extractor/model/CommitUrlStatistic.java b/src/main/java/ru/ulstu/extractor/model/CommitUrlStatistic.java new file mode 100644 index 0000000..3eb4b37 --- /dev/null +++ b/src/main/java/ru/ulstu/extractor/model/CommitUrlStatistic.java @@ -0,0 +1,20 @@ +package ru.ulstu.extractor.model; + +public class CommitUrlStatistic { + private String url; + private Long countCommit; + + public CommitUrlStatistic(String url, Long countCommit) { + this.url = url; + this.countCommit = countCommit; + } + + public String getUrl() { + return url; + } + + public Long getCountCommit() { + return countCommit; + } + +} diff --git a/src/main/java/ru/ulstu/extractor/model/mvc/FilterForm.java b/src/main/java/ru/ulstu/extractor/model/mvc/FilterForm.java index 6180b13..2d42b74 100644 --- a/src/main/java/ru/ulstu/extractor/model/mvc/FilterForm.java +++ b/src/main/java/ru/ulstu/extractor/model/mvc/FilterForm.java @@ -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.model.mvc; import org.springframework.data.domain.Page; @@ -5,15 +10,24 @@ import ru.ulstu.extractor.model.Commit; public class FilterForm { private String filter; - private String url; - private String branch; + private String repositoryUrl; + private String branchName; + private String author; private Page commitsPage; public FilterForm() { } + public String getAuthor() { + return author; + } + + public void setAuthor(String author) { + this.author = author; + } + public FilterForm(String url) { - this.url = url; + this.repositoryUrl = url; } public String getFilter() { @@ -24,34 +38,38 @@ public class FilterForm { this.filter = filter; } - public String getUrl() { - return url; + public Page getCommitsPage() { + return commitsPage; } - public void setUrl(String url) { - this.url = url; + public void setCommitsPage(Page commitsPage) { + this.commitsPage = commitsPage; } - public String getBranch() { - return branch; + public String getRepositoryUrl() { + return repositoryUrl; } - public void setBranch(String branch) { - this.branch = branch; + public void setRepositoryUrl(String repositoryUrl) { + this.repositoryUrl = repositoryUrl; } - public Page getCommitsPage() { - return commitsPage; + public String getBranchName() { + return branchName; } - public void setCommitsPage(Page commitsPage) { - this.commitsPage = commitsPage; + public void setBranchName(String branchName) { + this.branchName = branchName; } @Override public String toString() { return "FilterForm{" + - "subject='" + filter + + "filter='" + filter + '\'' + + ", repositoryUrl='" + repositoryUrl + '\'' + + ", branchName='" + branchName + '\'' + + ", author='" + author + '\'' + + ", commitsPage=" + commitsPage + '}'; } } diff --git a/src/main/java/ru/ulstu/extractor/repository/AuthorRepository.java b/src/main/java/ru/ulstu/extractor/repository/AuthorRepository.java index 504aaf2..a99a1b1 100644 --- a/src/main/java/ru/ulstu/extractor/repository/AuthorRepository.java +++ b/src/main/java/ru/ulstu/extractor/repository/AuthorRepository.java @@ -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.repository; import org.springframework.data.jpa.repository.JpaRepository; @@ -9,6 +14,6 @@ import ru.ulstu.extractor.model.Repository; import java.util.List; public interface AuthorRepository extends JpaRepository { - @Query("SELECT a 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") - List findByRepositoryAndBranch(@Param("repository") Repository repository, @Param("branchName") String branchName); + @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 findByRepositoryAndBranch(@Param("repository") Repository repository, @Param("branchName") String branchName); } diff --git a/src/main/java/ru/ulstu/extractor/repository/CommitRepository.java b/src/main/java/ru/ulstu/extractor/repository/CommitRepository.java index 3c32439..00fde10 100644 --- a/src/main/java/ru/ulstu/extractor/repository/CommitRepository.java +++ b/src/main/java/ru/ulstu/extractor/repository/CommitRepository.java @@ -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.repository; import org.springframework.data.domain.Page; @@ -6,9 +11,24 @@ import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; import ru.ulstu.extractor.model.Commit; +import ru.ulstu.extractor.model.CommitAuthorStatistic; +import ru.ulstu.extractor.model.CommitTimeStatistic; +import ru.ulstu.extractor.model.CommitUrlStatistic; import ru.ulstu.extractor.model.Repository; +import java.util.List; + public interface CommitRepository extends JpaRepository { - @Query("SELECT c FROM Commit c, Repository r, Branch b WHERE c.branch = b AND r = b.repository AND r = :repository AND b.name = :branchName") - Page findByRepositoryAndBranch(Pageable pageable, @Param("repository") Repository repository, @Param("branchName") String branchName); + @Query("SELECT c FROM Commit c, Repository r, Branch b, Author a WHERE c.branch = b AND r = b.repository AND a = c.author AND r = :repository AND b.name = :branchName AND (:author IS NULL OR :author = '' OR a.name = :author) AND (:filter IS NULL OR :filter = '' OR lower(c.message) LIKE lower(concat('%', :filter,'%')))") + Page findByRepositoryAndBranch(Pageable pageable, @Param("repository") Repository repository, @Param("branchName") String branchName, @Param("author") String author, @Param("filter") String filter); + + @Query("SELECT new ru.ulstu.extractor.model.CommitAuthorStatistic(c.author.name, COUNT(DISTINCT c.hash)) FROM Commit c GROUP by c.author.name") + List getCommitAuthorStatistic(); + + @Query("SELECT new ru.ulstu.extractor.model.CommitUrlStatistic(c.branch.repository.url, COUNT(DISTINCT c.hash)) FROM Commit c GROUP by c.branch.repository.url") + List getCommitUrlStatistic(); + + @Query("SELECT new ru.ulstu.extractor.model.CommitTimeStatistic(cast(c.date as date), COUNT(DISTINCT c.hash)) FROM Commit c GROUP by cast(c.date as date) ORDER by cast(c.date as date)") + List getCommitTimeStatistic(); + } diff --git a/src/main/java/ru/ulstu/extractor/service/FilteringService.java b/src/main/java/ru/ulstu/extractor/service/FilteringService.java index b6b7cf7..f85f3fb 100644 --- a/src/main/java/ru/ulstu/extractor/service/FilteringService.java +++ b/src/main/java/ru/ulstu/extractor/service/FilteringService.java @@ -1,13 +1,54 @@ +/* + * 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 com.sun.istack.NotNull; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; +import ru.ulstu.extractor.model.Commit; +import ru.ulstu.extractor.repository.AuthorRepository; +import ru.ulstu.extractor.repository.CommitRepository; +import ru.ulstu.extractor.repository.RepositoryRepository; + +import java.util.List; @Service public class FilteringService { + private final AuthorRepository authorRepository; + private final CommitRepository commitRepository; + private final RepositoryRepository repositoryRepository; - private final IndexService indexService; + public FilteringService(AuthorRepository authorRepository, + CommitRepository commitRepository, + RepositoryRepository repositoryRepository) { + this.authorRepository = authorRepository; + this.commitRepository = commitRepository; + this.repositoryRepository = repositoryRepository; + } + + public List getRepositoryAuthors(@NotNull String repositoryUrl, + @NotNull String branchName) { + return authorRepository.findByRepositoryAndBranch( + repositoryRepository.findByUrl(repositoryUrl), + branchName + ); + } - public FilteringService(IndexService indexService) { - this.indexService = indexService; + public Page getCommits(@NotNull String repositoryUrl, + @NotNull String branchName, + String author, + String filter, + Pageable pageable) { + return commitRepository.findByRepositoryAndBranch( + pageable, + repositoryRepository.findByUrl(repositoryUrl), + branchName, + author, + filter + ); } } diff --git a/src/main/java/ru/ulstu/extractor/service/GitRepositoryService.java b/src/main/java/ru/ulstu/extractor/service/GitRepositoryService.java index 419817d..a20915b 100644 --- a/src/main/java/ru/ulstu/extractor/service/GitRepositoryService.java +++ b/src/main/java/ru/ulstu/extractor/service/GitRepositoryService.java @@ -12,7 +12,6 @@ import org.eclipse.jgit.api.ListBranchCommand; import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.diff.DiffFormatter; import org.eclipse.jgit.internal.storage.file.FileRepository; -import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.revwalk.RevCommit; import org.springframework.beans.factory.annotation.Value; @@ -26,6 +25,9 @@ import ru.ulstu.extractor.model.LineChange; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URISyntaxException; +import java.net.URL; import java.nio.file.Path; import java.time.Instant; import java.util.ArrayList; @@ -42,20 +44,32 @@ public class GitRepositoryService { @Value("${extractor.custom-projects-dir}") private String customProjectsDir; - public void cloneOrUpdateRepo(String url) throws GitAPIException, IOException { - Git git; - if (projectDirExists(getProjectDirectoryFile(url))) { - Repository localRepo = new FileRepository(getProjectGitDirectory(url)); - git = new Git(localRepo); - git.pull().call(); - localRepo.close(); - } else { - git = Git.cloneRepository() - .setURI(url) - .setDirectory(getProjectDirectoryFile(url)) - .call(); - } + public List getRemoteBranches(String url) throws GitAPIException, IOException { + cloneOrUpdateRepo(url); + Repository localRepo = new FileRepository(getProjectGitDirectory(url)); + Git git = new Git(localRepo); + List branches = git.branchList().setListMode(ListBranchCommand.ListMode.REMOTE) + .call() + .stream() + .map(r -> new Branch(r.getName().replace(BRANCH_PREFIX, ""))) + .collect(Collectors.toList()); git.close(); + localRepo.close(); + return branches; + } + + public List getLocalBranches(String url) throws GitAPIException, IOException { + cloneOrUpdateRepo(url); + Repository localRepo = new FileRepository(getProjectGitDirectory(url)); + Git git = new Git(localRepo); + List branches = git.branchList() + .call() + .stream() + .map(r -> new Branch(r.getName().replace(BRANCH_PREFIX, ""))) + .collect(Collectors.toList()); + git.close(); + localRepo.close(); + return branches; } private String getProjectDirectory(String url) { @@ -83,12 +97,18 @@ public class GitRepositoryService { Git git = new Git(localRepo); git.pull().call(); if (!localRepo.getBranch().equals(branchName)) { - Ref ref = git.checkout(). - setCreateBranch(true). - setName(branchName). - setUpstreamMode(CreateBranchCommand.SetupUpstreamMode.TRACK). - setStartPoint("origin/" + branchName). - call(); + if (getLocalBranches(repositoryUrl).stream().anyMatch(localBranch -> localBranch.getName().contains(branchName))) { + git.checkout() + .setName(branchName) + .call(); + } else { + git.checkout() + .setCreateBranch(true) + .setName(branchName) + .setUpstreamMode(CreateBranchCommand.SetupUpstreamMode.TRACK) + .setStartPoint("origin/" + branchName) + .call(); + } } List commits = new ArrayList<>(); git.log().call().forEach(commits::add); @@ -112,7 +132,58 @@ public class GitRepositoryService { return list; } - public List findDiffBetweenTwoRevisions(RevCommit laterCommit, RevCommit earlierCommit, Repository localRepo) { + public void remove(String repositoryUrl) throws IOException { + FileUtils.deleteDirectory(getProjectDirectoryFile(repositoryUrl)); + } + + private void cloneOrUpdateRepo(String url) throws GitAPIException, IOException { + Git git; + if (projectDirExists(getProjectDirectoryFile(url))) { + Repository localRepo = new FileRepository(getProjectGitDirectory(url)); + git = new Git(localRepo); + git.pull().call(); + localRepo.close(); + } else { + git = Git.cloneRepository() + .setURI(url) + .setDirectory(getProjectDirectoryFile(url)) + .call(); + } + git.close(); + } + + private String getProjectDirectory(String url) { + return (isBlank(customProjectsDir) + ? System.getProperty("java.io.tmpdir") + : customProjectsDir) + url.substring(url.lastIndexOf('/')); + } + + private String getProjectGitDirectory(String url) { + return getProjectDirectory(url) + "/.git"; + } + + private File getProjectDirectoryFile(String url) { + validateUrl(url); + return Path.of(getProjectDirectory(url)) + .toFile(); + } + + private void validateUrl(String url) { + if (url == null || url.isEmpty()) { + throw new RuntimeException("Repository url must not empty"); + } + try { + new URL(url).toURI(); + } catch (MalformedURLException | URISyntaxException e) { + throw new RuntimeException("Repository url not valid"); + } + } + + private boolean projectDirExists(File file) { + return file.exists(); + } + + private List findDiffBetweenTwoRevisions(RevCommit laterCommit, RevCommit earlierCommit, Repository localRepo) { if (laterCommit == null || earlierCommit == null) { return null; } @@ -210,22 +281,4 @@ public class GitRepositoryService { } return Optional.empty(); } - - public List getBranches(String url) throws GitAPIException, IOException { - cloneOrUpdateRepo(url); - Repository localRepo = new FileRepository(getProjectGitDirectory(url)); - Git git = new Git(localRepo); - List branches = git.branchList().setListMode(ListBranchCommand.ListMode.REMOTE) - .call() - .stream() - .map(r -> new Branch(r.getName().replace(BRANCH_PREFIX, ""))) - .collect(Collectors.toList()); - git.close(); - localRepo.close(); - return branches; - } - - public void remove(String repositoryUrl) throws IOException { - FileUtils.deleteDirectory(getProjectDirectoryFile(repositoryUrl)); - } } diff --git a/src/main/java/ru/ulstu/extractor/service/IndexService.java b/src/main/java/ru/ulstu/extractor/service/IndexService.java index 332a3e1..44b7414 100644 --- a/src/main/java/ru/ulstu/extractor/service/IndexService.java +++ b/src/main/java/ru/ulstu/extractor/service/IndexService.java @@ -1,15 +1,17 @@ +/* + * 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 com.sun.istack.NotNull; import org.eclipse.jgit.api.errors.GitAPIException; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; -import ru.ulstu.extractor.model.Author; +import org.springframework.transaction.annotation.Transactional; import ru.ulstu.extractor.model.Branch; import ru.ulstu.extractor.model.Commit; import ru.ulstu.extractor.model.Repository; -import ru.ulstu.extractor.repository.AuthorRepository; import ru.ulstu.extractor.repository.BranchRepository; import ru.ulstu.extractor.repository.CommitRepository; import ru.ulstu.extractor.repository.RepositoryRepository; @@ -23,43 +25,32 @@ public class IndexService { private final RepositoryRepository repositoryRepository; private final BranchRepository branchRepository; private final CommitRepository commitRepository; - private final AuthorRepository authorRepository; - public IndexService(GitRepositoryService gitRepositoryService, RepositoryRepository repositoryRepository, BranchRepository branchRepository, - CommitRepository commitRepository, - AuthorRepository authorRepository) { + CommitRepository commitRepository) { this.gitRepositoryService = gitRepositoryService; this.repositoryRepository = repositoryRepository; this.branchRepository = branchRepository; this.commitRepository = commitRepository; - this.authorRepository = authorRepository; } + @Transactional public void index(@NotNull String repositoryUrl, @NotNull String branchName) throws GitAPIException, IOException { Repository repository = repositoryRepository.findByUrl(repositoryUrl); if (repository == null) { - repositoryRepository.save(new Repository(repositoryUrl)); + repository = repositoryRepository.save(new Repository(repositoryUrl)); } Branch branch = branchRepository.findByRepositoryAndName(repository, branchName); if (branch == null) { - branchRepository.save(new Branch(repository, branchName)); + branch = branchRepository.save(new Branch(repository, branchName)); } List commits = gitRepositoryService.getCommits(repositoryUrl, branchName); - commitRepository.deleteAll(branch.getCommits()); + List commitsToRemove = branch.getCommits(); branch.getCommits().clear(); + commitRepository.deleteAll(commitsToRemove); branch.setCommits(commits); branchRepository.save(branch); - gitRepositoryService.remove(repositoryUrl); - } - - public List getRepositoryAuthors(@NotNull String repositoryUrl, @NotNull String branchName) { - return authorRepository.findByRepositoryAndBranch(repositoryRepository.findByUrl(repositoryUrl), branchName); - } - - public Page getCommits(@NotNull String repositoryUrl, @NotNull String branchName, Pageable pageable) { - return commitRepository.findByRepositoryAndBranch(pageable, repositoryRepository.findByUrl(repositoryUrl), branchName); } } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 938472e..603e99a 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,5 +1,11 @@ +# +# Copyright (C) 2021 Anton Romanov - All Rights Reserved +# You may use, distribute and modify this code, please write to: romanov73@gmail.com. +# + spring.main.banner-mode=off server.port=8080 +server.jetty.connection-idle-timeout=1000s # Available levels are: TRACE, DEBUG, INFO, WARN, ERROR, FATAL, OFF logging.level.ru.ulstu=DEBUG extractor.custom-projects-dir= diff --git a/src/main/resources/messages.properties b/src/main/resources/messages.properties index 34bbcb8..e6edf95 100644 --- a/src/main/resources/messages.properties +++ b/src/main/resources/messages.properties @@ -1,4 +1,10 @@ +# +# Copyright (C) 2021 Anton Romanov - All Rights Reserved +# You may use, distribute and modify this code, please write to: romanov73@gmail.com. +# + messages.app-name=GitExtractor v0.1.0 messages.menu.home=Main messages.menu.indexed-repos=List of indexed repos -messages.menu.new-repo=Analyse new repo \ No newline at end of file +messages.menu.new-repo=Analyse new repo +messages.menu.statistic=Statistic \ No newline at end of file diff --git a/src/main/resources/messages_en.properties b/src/main/resources/messages_en.properties index 34bbcb8..e6edf95 100644 --- a/src/main/resources/messages_en.properties +++ b/src/main/resources/messages_en.properties @@ -1,4 +1,10 @@ +# +# Copyright (C) 2021 Anton Romanov - All Rights Reserved +# You may use, distribute and modify this code, please write to: romanov73@gmail.com. +# + messages.app-name=GitExtractor v0.1.0 messages.menu.home=Main messages.menu.indexed-repos=List of indexed repos -messages.menu.new-repo=Analyse new repo \ No newline at end of file +messages.menu.new-repo=Analyse new repo +messages.menu.statistic=Statistic \ No newline at end of file diff --git a/src/main/resources/messages_ru.properties b/src/main/resources/messages_ru.properties index dfda9c7..30c525b 100644 --- a/src/main/resources/messages_ru.properties +++ b/src/main/resources/messages_ru.properties @@ -1,4 +1,10 @@ +# +# Copyright (C) 2021 Anton Romanov - All Rights Reserved +# You may use, distribute and modify this code, please write to: romanov73@gmail.com. +# + messages.app-name=GitЁxtractor v0.1.0 messages.menu.home=На главную messages.menu.indexed-repos=Список проиндексированных репозиториев -messages.menu.new-repo=Анализ нового репозитория \ No newline at end of file +messages.menu.new-repo=Анализ нового репозитория +messages.menu.statistic=Статистика \ No newline at end of file diff --git a/src/main/resources/templates/default.html b/src/main/resources/templates/default.html index 04f7459..254f42c 100644 --- a/src/main/resources/templates/default.html +++ b/src/main/resources/templates/default.html @@ -1,3 +1,8 @@ + + @@ -22,10 +27,15 @@ @@ -41,6 +51,8 @@
diff --git a/src/main/resources/templates/error.html b/src/main/resources/templates/error.html index d3eefef..ce4f465 100644 --- a/src/main/resources/templates/error.html +++ b/src/main/resources/templates/error.html @@ -1,18 +1,17 @@ + + - -

Ошибка

-

Страница: Page URL

@@ -34,13 +33,15 @@

${url}
-
-
${exception.message}
-
    -
  • ${ste}
  • -
+

+
+ ${exception.message}
+
    +
  • ${ste}
  • +
diff --git a/src/main/resources/templates/filterCommits.html b/src/main/resources/templates/filterCommits.html new file mode 100644 index 0000000..2836270 --- /dev/null +++ b/src/main/resources/templates/filterCommits.html @@ -0,0 +1,112 @@ + + + + +
+ +
+
+
+ Автор +
+
+ + +
+
+ Дата: +
+
+ +
+
+ - +
+
+ +
+
+
+
+ Искать по тексту: +
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
АвторДатаСообщение
+
+ Страницы: + +
+ diff --git a/src/main/resources/templates/filtering.html b/src/main/resources/templates/filtering.html deleted file mode 100644 index 365ac17..0000000 --- a/src/main/resources/templates/filtering.html +++ /dev/null @@ -1,58 +0,0 @@ - - - - Простая обработка формы на Spring MVC - - -
-
-

Фильтровать данные:

- По автору - - Дата с - - по - -

Строки:
- - -

-

- - - - - - - - - - - - - - - -
AuthorDateCommit
-

- -

-
-
- - diff --git a/src/main/resources/templates/index.html b/src/main/resources/templates/index.html deleted file mode 100644 index 939171f..0000000 --- a/src/main/resources/templates/index.html +++ /dev/null @@ -1,32 +0,0 @@ - - - - Простая обработка формы на Spring MVC - - -
-

Форма

-
-

- - - - - - - - - - - -
Тема:
Кому:
Сообщение: