diff --git a/scm-ui/ui-webapp/src/repos/sources/containers/Sources.tsx b/scm-ui/ui-webapp/src/repos/sources/containers/Sources.tsx index 0a5608e6e5..bdf654b08a 100644 --- a/scm-ui/ui-webapp/src/repos/sources/containers/Sources.tsx +++ b/scm-ui/ui-webapp/src/repos/sources/containers/Sources.tsx @@ -53,7 +53,7 @@ class Sources extends React.Component { const { fetchBranches, repository, revision, path, fetchSources } = this.props; fetchBranches(repository); - fetchSources(repository, revision, path); + fetchSources(repository, this.decodeRevision(revision), path); this.redirectToDefaultBranch(); } @@ -61,12 +61,16 @@ class Sources extends React.Component { componentDidUpdate(prevProps) { const { fetchSources, repository, revision, path } = this.props; if (prevProps.revision !== revision || prevProps.path !== path) { - fetchSources(repository, revision, path); + fetchSources(repository, this.decodeRevision(revision), path); } this.redirectToDefaultBranch(); } + decodeRevision = (revision: string) => { + return revision ? decodeURIComponent(revision) : revision; + }; + redirectToDefaultBranch = () => { const { branches } = this.props; if (this.shouldRedirectToDefaultBranch()) { @@ -171,7 +175,7 @@ class Sources extends React.Component { const mapStateToProps = (state, ownProps) => { const { repository, match } = ownProps; const { revision, path } = match.params; - const decodedRevision = revision ? decodeURIComponent(revision) : revision; + const decodedRevision = revision ? decodeURIComponent(revision) : undefined; const loading = isFetchBranchesPending(state, repository); const error = getFetchBranchesFailure(state, repository); const branches = getBranches(state, repository); @@ -198,7 +202,7 @@ const mapDispatchToProps = dispatch => { dispatch(fetchBranches(repository)); }, fetchSources: (repository: Repository, revision: string, path: string) => { - dispatch(fetchSources(repository, decodeURIComponent(revision), path)); + dispatch(fetchSources(repository, revision, path)); } }; }; diff --git a/scm-ui/ui-webapp/src/repos/sources/modules/sources.ts b/scm-ui/ui-webapp/src/repos/sources/modules/sources.ts index d3d0380a69..826b32f1f6 100644 --- a/scm-ui/ui-webapp/src/repos/sources/modules/sources.ts +++ b/scm-ui/ui-webapp/src/repos/sources/modules/sources.ts @@ -16,10 +16,10 @@ export function fetchSources(repository: Repository, revision: string, path: str .get(createUrl(repository, revision, path)) .then(response => response.json()) .then(sources => { - dispatch(fetchSourcesSuccess(repository, decodeURIComponent(revision), path, sources)); + dispatch(fetchSourcesSuccess(repository, revision, path, sources)); }) .catch(err => { - dispatch(fetchSourcesFailure(repository, decodeURIComponent(revision), path, err)); + dispatch(fetchSourcesFailure(repository, revision, path, err)); }); }; } diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/SourceRootResource.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/SourceRootResource.java index b5c7e205be..b431997462 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/SourceRootResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/SourceRootResource.java @@ -14,6 +14,7 @@ import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.core.Response; import java.io.IOException; +import java.net.URLDecoder; import static sonia.scm.ContextEntry.ContextBuilder.entity; import static sonia.scm.NotFoundException.notFound; @@ -57,7 +58,7 @@ public class SourceRootResource { BrowseCommandBuilder browseCommand = repositoryService.getBrowseCommand(); browseCommand.setPath(path); if (revision != null && !revision.isEmpty()) { - browseCommand.setRevision(revision); + browseCommand.setRevision(URLDecoder.decode(revision, "UTF-8")); } browseCommand.setDisableCache(true); BrowserResult browserResult = browseCommand.getBrowserResult();