diff --git a/CHANGELOG.md b/CHANGELOG.md index 567376895b..c858d212ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## unreleased +## Unreleased +### Added +- SubRepository support ([#1357](https://github.com/scm-manager/scm-manager/pull/1357)) + ### Fixed - Align actionbar item horizontal and enforce correct margin between them ([#1358](https://github.com/scm-manager/scm-manager/pull/1358)) @@ -342,3 +345,4 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 [2.4.1]: https://www.scm-manager.org/download/2.4.1 [2.5.0]: https://www.scm-manager.org/download/2.5.0 [2.6.0]: https://www.scm-manager.org/download/2.6.0 +[2.6.1]: https://www.scm-manager.org/download/2.6.1 diff --git a/scm-plugins/scm-hg-plugin/src/main/resources/sonia/scm/hg/ext/fileview.py b/scm-plugins/scm-hg-plugin/src/main/resources/sonia/scm/hg/ext/fileview.py index 28e88f2ece..0ee335561e 100644 --- a/scm-plugins/scm-hg-plugin/src/main/resources/sonia/scm/hg/ext/fileview.py +++ b/scm-plugins/scm-hg-plugin/src/main/resources/sonia/scm/hg/ext/fileview.py @@ -244,6 +244,7 @@ class File_Printer: self.writer.write( format % (file.path(), file.size(), date, description) ) def print_sub_repository(self, path, subrepo): + self.result_count += 1 if self.shouldPrintResult(): format = b'%s/ %s %s\n' if self.transport: diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnBrowseCommand.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnBrowseCommand.java index e96a933080..00a135dd82 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnBrowseCommand.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/repository/spi/SvnBrowseCommand.java @@ -46,7 +46,6 @@ import java.util.Collection; import java.util.Iterator; import java.util.List; -import static java.util.Comparator.comparing; import static org.tmatesoft.svn.core.SVNErrorCode.FS_NO_SUCH_REVISION; import static sonia.scm.ContextEntry.ContextBuilder.entity; import static sonia.scm.NotFoundException.notFound; @@ -54,12 +53,10 @@ import static sonia.scm.NotFoundException.notFound; //~--- JDK imports ------------------------------------------------------------ /** - * * @author Sebastian Sdorra */ public class SvnBrowseCommand extends AbstractSvnCommand - implements BrowseCommand -{ + implements BrowseCommand { /** * the logger for SvnBrowseCommand @@ -69,8 +66,7 @@ public class SvnBrowseCommand extends AbstractSvnCommand private int resultCount = 0; - SvnBrowseCommand(SvnContext context) - { + SvnBrowseCommand(SvnContext context) { super(context); } @@ -86,8 +82,7 @@ public class SvnBrowseCommand extends AbstractSvnCommand BrowserResult result = null; - try - { + try { SVNRepository svnRepository = open(); if (revisionNumber == -1) { @@ -104,9 +99,7 @@ public class SvnBrowseCommand extends AbstractSvnCommand result = new BrowserResult(String.valueOf(revisionNumber), root); - } - catch (SVNException ex) - { + } catch (SVNException ex) { if (FS_NO_SUCH_REVISION.equals(ex.getErrorMessage().getErrorCode())) { throw notFound(entity("Revision", Long.toString(revisionNumber)).in(this.repository)); } @@ -120,9 +113,8 @@ public class SvnBrowseCommand extends AbstractSvnCommand @SuppressWarnings("unchecked") private void traverse(SVNRepository svnRepository, long revisionNumber, BrowseCommandRequest request, - FileObject parent, String basePath) - throws SVNException - { + FileObject parent, String basePath) + throws SVNException { List entries = new ArrayList<>(svnRepository.getDir(parent.getPath(), revisionNumber, null, (Collection) null)); sort(entries, entry -> entry.getKind() == SVNNodeKind.DIR, SVNDirEntry::getName); for (Iterator iterator = entries.iterator(); resultCount < request.getLimit() + request.getOffset() && iterator.hasNext(); ) { @@ -146,16 +138,13 @@ public class SvnBrowseCommand extends AbstractSvnCommand } } - private String createBasePath(String path) - { + private String createBasePath(String path) { String basePath = Util.EMPTY_STRING; - if (Util.isNotEmpty(path)) - { + if (Util.isNotEmpty(path)) { basePath = path; - if (!basePath.endsWith("/")) - { + if (!basePath.endsWith("/")) { basePath = basePath.concat("/"); } } @@ -164,8 +153,7 @@ public class SvnBrowseCommand extends AbstractSvnCommand } private FileObject createFileObject(BrowseCommandRequest request, - SVNRepository repository, long revision, SVNDirEntry entry, String path) - { + SVNRepository repository, long revision, SVNDirEntry entry, String path) { if (entry == null) { throw notFound(entity("Path", path).in("Revision", Long.toString(revision)).in(this.repository)); } @@ -175,10 +163,8 @@ public class SvnBrowseCommand extends AbstractSvnCommand fileObject.setPath(path.concat(entry.getRelativePath())); fileObject.setDirectory(entry.getKind() == SVNNodeKind.DIR); - if (!request.isDisableLastCommit()) - { - if (entry.getDate() != null) - { + if (!request.isDisableLastCommit()) { + if (entry.getDate() != null) { fileObject.setCommitDate(entry.getDate().getTime()); } @@ -188,35 +174,53 @@ public class SvnBrowseCommand extends AbstractSvnCommand fileObject.setLength(entry.getSize()); if (!request.isDisableSubRepositoryDetection() && fileObject.isDirectory() - && entry.hasProperties()) - { + && entry.hasProperties()) { fetchExternalsProperty(repository, revision, entry, fileObject); } return fileObject; } + private boolean shouldSetExternal(String external) { + return (external.startsWith("http://") || external.startsWith("https://") || external.startsWith("../") + || external.startsWith("^/") || external.startsWith("/")); + } + private void fetchExternalsProperty(SVNRepository repository, long revision, - SVNDirEntry entry, FileObject fileObject) - { - try - { + SVNDirEntry entry, FileObject fileObject) { + try { SVNProperties properties = new SVNProperties(); - repository.getFile(entry.getRelativePath(), revision, properties, null); + repository.getDir(entry.getRelativePath(), revision, properties, (Collection) null); - String externals = properties.getStringValue(SVNProperty.EXTERNALS); + String[] externals = properties.getStringValue(SVNProperty.EXTERNALS).split("\\r?\\n"); + for (String external : externals) { + String subRepoUrl = ""; + String subRepoPath = ""; + for (String externalPart : external.split(" ")) { + if (shouldSetExternal(externalPart)) { + subRepoUrl = externalPart; + } else if (!externalPart.contains("-r")) { + subRepoPath = externalPart; + } + } - if (Util.isNotEmpty(externals)) - { - SubRepository subRepository = new SubRepository(externals); - - fileObject.setSubRepository(subRepository); + if (Util.isNotEmpty(external)) { + SubRepository subRepository = new SubRepository(subRepoUrl); + fileObject.addChild(createSubRepoDirectory(subRepository, subRepoPath)); + } } - } - catch (SVNException ex) - { + } catch (SVNException ex) { logger.error("could not fetch file properties", ex); } } + + private FileObject createSubRepoDirectory(SubRepository subRepository, String subRepoPath) { + FileObject subRepositoryDirectory = new FileObject(); + subRepositoryDirectory.setPath(subRepoPath); + subRepositoryDirectory.setName(subRepoPath); + subRepositoryDirectory.setDirectory(true); + subRepositoryDirectory.setSubRepository(subRepository); + return subRepositoryDirectory; + } } diff --git a/scm-ui/ui-components/src/Breadcrumb.tsx b/scm-ui/ui-components/src/Breadcrumb.tsx index 612714fcdf..1844743def 100644 --- a/scm-ui/ui-components/src/Breadcrumb.tsx +++ b/scm-ui/ui-components/src/Breadcrumb.tsx @@ -50,11 +50,11 @@ const HomeIcon = styled(Icon)` const ActionBar = styled.div` align-self: center; - + /* order actionbar items horizontal */ display: flex; justify-content: flex-start; - + /* ensure space between action bar items */ & > * { /* diff --git a/scm-ui/ui-components/src/__snapshots__/storyshots.test.ts.snap b/scm-ui/ui-components/src/__snapshots__/storyshots.test.ts.snap index e5ed258452..eec24b0966 100644 --- a/scm-ui/ui-components/src/__snapshots__/storyshots.test.ts.snap +++ b/scm-ui/ui-components/src/__snapshots__/storyshots.test.ts.snap @@ -2,7 +2,7 @@ exports[`Storyshots Annotate Default 1`] = `
Arthur Dent
1
2
Tricia Marie McMillan
3
4
Arthur Dent
5
Ford Prefect
6
Arthur Dent
7
8
Arthur Dent Arthur Dent
1
2
Tricia Marie McMillan Tricia Marie McMillan
3
4
Arthur Dent Arthur Dent
5
Ford Prefect Ford Prefect
6
Arthur Dent Arthur Dent
7
8