mirror of
https://github.com/scm-manager/scm-manager.git
synced 2026-03-04 11:20:53 +01:00
Repository specific mercurial encoding (#1583)
* Use HgRepositoryConfig instead of HgConfig for hg commands * Rename HgConfig to HgGlobalConfig * Resolve encoding from repository specific configuration * Add ui for repository specific configuration * Validate encoding on dto
This commit is contained in:
2
gradle/changelog/hg_repository_encoding.yaml
Normal file
2
gradle/changelog/hg_repository_encoding.yaml
Normal file
@@ -0,0 +1,2 @@
|
||||
- type: added
|
||||
description: Mercurial encoding configuration per repository ([#1577](https://github.com/scm-manager/scm-manager/issues/1577), [#1583](https://github.com/scm-manager/scm-manager/issues/1583))
|
||||
@@ -35,6 +35,12 @@ dependencies {
|
||||
implementation libraries.commonsCompress
|
||||
testImplementation libraries.shiroUnit
|
||||
testImplementation libraries.logback
|
||||
|
||||
// validation api
|
||||
testImplementation libraries.validator
|
||||
testImplementation libraries.elApi
|
||||
testImplementation libraries.elRuntime
|
||||
testImplementation libraries.resteasyValidatorProvider
|
||||
}
|
||||
|
||||
scmPlugin {
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package sonia.scm.api.v2.resources;
|
||||
|
||||
import javax.validation.Constraint;
|
||||
import javax.validation.Payload;
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
@Documented
|
||||
@Retention(RUNTIME)
|
||||
@Target({ FIELD, METHOD, CONSTRUCTOR, ANNOTATION_TYPE })
|
||||
@Constraint(validatedBy = EncodingValidator.class)
|
||||
public @interface Encoding {
|
||||
String message() default "Invalid encoding";
|
||||
Class<?>[] groups() default { };
|
||||
Class<? extends Payload>[] payload() default { };
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package sonia.scm.api.v2.resources;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
|
||||
import javax.validation.ConstraintValidator;
|
||||
import javax.validation.ConstraintValidatorContext;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.UnsupportedCharsetException;
|
||||
|
||||
public class EncodingValidator implements ConstraintValidator<Encoding, String> {
|
||||
|
||||
@Override
|
||||
public void initialize(Encoding constraintAnnotation) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid(String value, ConstraintValidatorContext context) {
|
||||
if (Strings.isNullOrEmpty(value)) {
|
||||
return true;
|
||||
}
|
||||
try {
|
||||
Charset.forName(value);
|
||||
return true;
|
||||
} catch (UnsupportedCharsetException ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package sonia.scm.api.v2.resources;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.inject.util.Providers;
|
||||
import sonia.scm.repository.Repository;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Provider;
|
||||
|
||||
public class HgConfigLinks {
|
||||
|
||||
private final Provider<ScmPathInfoStore> pathInfoStore;
|
||||
|
||||
@Inject
|
||||
public HgConfigLinks(Provider<ScmPathInfoStore> pathInfoStore) {
|
||||
this.pathInfoStore = pathInfoStore;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public HgConfigLinks(ScmPathInfoStore pathInfoStore) {
|
||||
this.pathInfoStore = Providers.of(pathInfoStore);
|
||||
}
|
||||
|
||||
|
||||
public ConfigLinks global() {
|
||||
LinkBuilder linkBuilder = new LinkBuilder(pathInfoStore.get().get(), HgConfigResource.class);
|
||||
return new ConfigLinks() {
|
||||
@Override
|
||||
public String get() {
|
||||
return linkBuilder.method("get").parameters().href();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String update() {
|
||||
return linkBuilder.method("update").parameters().href();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public ConfigLinks repository(Repository repository) {
|
||||
return repository(repository.getNamespace(), repository.getName());
|
||||
}
|
||||
|
||||
public ConfigLinks repository(String namespace, String name) {
|
||||
LinkBuilder linkBuilder = new LinkBuilder(pathInfoStore.get().get(), HgConfigResource.class, HgRepositoryConfigResource.class)
|
||||
.method("getRepositoryConfigResource")
|
||||
.parameters();
|
||||
|
||||
return new ConfigLinks() {
|
||||
@Override
|
||||
public String get() {
|
||||
return linkBuilder.method("getHgRepositoryConfig").parameters(namespace, name).href();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String update() {
|
||||
return linkBuilder.method("updateHgRepositoryConfig").parameters(namespace, name).href();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public interface ConfigLinks {
|
||||
String get();
|
||||
String update();
|
||||
}
|
||||
}
|
||||
@@ -33,13 +33,14 @@ import io.swagger.v3.oas.annotations.parameters.RequestBody;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import sonia.scm.config.ConfigurationPermissions;
|
||||
import sonia.scm.repository.HgConfig;
|
||||
import sonia.scm.repository.HgGlobalConfig;
|
||||
import sonia.scm.repository.HgRepositoryHandler;
|
||||
import sonia.scm.web.HgVndMediaType;
|
||||
import sonia.scm.web.VndMediaType;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Provider;
|
||||
import javax.validation.Valid;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.PUT;
|
||||
@@ -57,20 +58,23 @@ import javax.ws.rs.core.Response;
|
||||
public class HgConfigResource {
|
||||
|
||||
static final String HG_CONFIG_PATH_V2 = "v2/config/hg";
|
||||
private final HgConfigDtoToHgConfigMapper dtoToConfigMapper;
|
||||
private final HgConfigToHgConfigDtoMapper configToDtoMapper;
|
||||
private final HgGlobalConfigDtoToHgConfigMapper dtoToConfigMapper;
|
||||
private final HgGlobalConfigToHgGlobalConfigDtoMapper configToDtoMapper;
|
||||
private final HgRepositoryHandler repositoryHandler;
|
||||
private final Provider<HgConfigAutoConfigurationResource> autoconfigResource;
|
||||
private final Provider<HgGlobalConfigAutoConfigurationResource> autoconfigResource;
|
||||
private final Provider<HgRepositoryConfigResource> repositoryConfigResource;
|
||||
|
||||
@Inject
|
||||
public HgConfigResource(HgConfigDtoToHgConfigMapper dtoToConfigMapper,
|
||||
HgConfigToHgConfigDtoMapper configToDtoMapper,
|
||||
public HgConfigResource(HgGlobalConfigDtoToHgConfigMapper dtoToConfigMapper,
|
||||
HgGlobalConfigToHgGlobalConfigDtoMapper configToDtoMapper,
|
||||
HgRepositoryHandler repositoryHandler,
|
||||
Provider<HgConfigAutoConfigurationResource> autoconfigResource) {
|
||||
Provider<HgGlobalConfigAutoConfigurationResource> autoconfigResource,
|
||||
Provider<HgRepositoryConfigResource> repositoryConfigResource) {
|
||||
this.dtoToConfigMapper = dtoToConfigMapper;
|
||||
this.configToDtoMapper = configToDtoMapper;
|
||||
this.repositoryHandler = repositoryHandler;
|
||||
this.autoconfigResource = autoconfigResource;
|
||||
this.repositoryConfigResource = repositoryConfigResource;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -85,7 +89,7 @@ public class HgConfigResource {
|
||||
description = "success",
|
||||
content = @Content(
|
||||
mediaType = HgVndMediaType.CONFIG,
|
||||
schema = @Schema(implementation = HgConfigDto.class)
|
||||
schema = @Schema(implementation = HgGlobalGlobalConfigDto.class)
|
||||
)
|
||||
)
|
||||
@ApiResponse(responseCode = "401", description = "not authenticated / invalid credentials")
|
||||
@@ -99,12 +103,12 @@ public class HgConfigResource {
|
||||
))
|
||||
public Response get() {
|
||||
|
||||
ConfigurationPermissions.read(HgConfig.PERMISSION).check();
|
||||
ConfigurationPermissions.read(HgGlobalConfig.PERMISSION).check();
|
||||
|
||||
HgConfig config = repositoryHandler.getConfig();
|
||||
HgGlobalConfig config = repositoryHandler.getConfig();
|
||||
|
||||
if (config == null) {
|
||||
config = new HgConfig();
|
||||
config = new HgGlobalConfig();
|
||||
repositoryHandler.setConfig(config);
|
||||
}
|
||||
|
||||
@@ -127,7 +131,7 @@ public class HgConfigResource {
|
||||
requestBody = @RequestBody(
|
||||
content = @Content(
|
||||
mediaType = HgVndMediaType.CONFIG,
|
||||
schema = @Schema(implementation = UpdateHgConfigDto.class),
|
||||
schema = @Schema(implementation = UpdateHgGlobalConfigDto.class),
|
||||
examples = @ExampleObject(
|
||||
name = "Overwrites current configuration with this one.",
|
||||
value = "{\n \"disabled\":false,\n \"hgBinary\":\"hg\",\n \"encoding\":\"UTF-8\",\n \"showRevisionInId\":false,\n \"enableHttpPostArgs\":false\n}",
|
||||
@@ -149,9 +153,9 @@ public class HgConfigResource {
|
||||
mediaType = VndMediaType.ERROR_TYPE,
|
||||
schema = @Schema(implementation = ErrorDto.class)
|
||||
))
|
||||
public Response update(HgConfigDto configDto) {
|
||||
public Response update(@Valid HgGlobalGlobalConfigDto configDto) {
|
||||
|
||||
HgConfig config = dtoToConfigMapper.map(configDto);
|
||||
HgGlobalConfig config = dtoToConfigMapper.map(configDto);
|
||||
|
||||
ConfigurationPermissions.write(config).check();
|
||||
|
||||
@@ -162,7 +166,13 @@ public class HgConfigResource {
|
||||
}
|
||||
|
||||
@Path("auto-configuration")
|
||||
public HgConfigAutoConfigurationResource getAutoConfigurationResource() {
|
||||
public HgGlobalConfigAutoConfigurationResource getAutoConfigurationResource() {
|
||||
return autoconfigResource.get();
|
||||
}
|
||||
|
||||
|
||||
@Path("{namespace}/{name}")
|
||||
public HgRepositoryConfigResource getRepositoryConfigResource() {
|
||||
return repositoryConfigResource.get();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
package sonia.scm.api.v2.resources;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
@@ -32,7 +32,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.parameters.RequestBody;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
import sonia.scm.config.ConfigurationPermissions;
|
||||
import sonia.scm.repository.HgConfig;
|
||||
import sonia.scm.repository.HgGlobalConfig;
|
||||
import sonia.scm.repository.HgRepositoryHandler;
|
||||
import sonia.scm.web.HgVndMediaType;
|
||||
import sonia.scm.web.VndMediaType;
|
||||
@@ -42,14 +42,14 @@ import javax.ws.rs.PUT;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
public class HgConfigAutoConfigurationResource {
|
||||
public class HgGlobalConfigAutoConfigurationResource {
|
||||
|
||||
private final HgRepositoryHandler repositoryHandler;
|
||||
private final HgConfigDtoToHgConfigMapper dtoToConfigMapper;
|
||||
private final HgGlobalConfigDtoToHgConfigMapper dtoToConfigMapper;
|
||||
|
||||
@Inject
|
||||
public HgConfigAutoConfigurationResource(HgConfigDtoToHgConfigMapper dtoToConfigMapper,
|
||||
HgRepositoryHandler repositoryHandler) {
|
||||
public HgGlobalConfigAutoConfigurationResource(HgGlobalConfigDtoToHgConfigMapper dtoToConfigMapper,
|
||||
HgRepositoryHandler repositoryHandler) {
|
||||
this.dtoToConfigMapper = dtoToConfigMapper;
|
||||
this.repositoryHandler = repositoryHandler;
|
||||
}
|
||||
@@ -92,7 +92,7 @@ public class HgConfigAutoConfigurationResource {
|
||||
requestBody = @RequestBody(
|
||||
content = @Content(
|
||||
mediaType = HgVndMediaType.CONFIG,
|
||||
schema = @Schema(implementation = UpdateHgConfigDto.class),
|
||||
schema = @Schema(implementation = UpdateHgGlobalConfigDto.class),
|
||||
examples = @ExampleObject(
|
||||
name = "Overwrites current configuration with this one and installs the mercurial binary.",
|
||||
value = "{\n \"disabled\":false,\n \"hgBinary\":\"hg\",\n \"pythonBinary\":\"python\",\n \"pythonPath\":\"\",\n \"encoding\":\"UTF-8\",\n \"useOptimizedBytecode\":false,\n \"showRevisionInId\":false,\n \"disableHookSSLValidation\":false,\n \"enableHttpPostArgs\":false\n}",
|
||||
@@ -114,14 +114,14 @@ public class HgConfigAutoConfigurationResource {
|
||||
mediaType = VndMediaType.ERROR_TYPE,
|
||||
schema = @Schema(implementation = ErrorDto.class)
|
||||
))
|
||||
public Response autoConfiguration(HgConfigDto configDto) {
|
||||
public Response autoConfiguration(HgGlobalGlobalConfigDto configDto) {
|
||||
|
||||
HgConfig config;
|
||||
HgGlobalConfig config;
|
||||
|
||||
if (configDto != null) {
|
||||
config = dtoToConfigMapper.map(configDto);
|
||||
} else {
|
||||
config = new HgConfig();
|
||||
config = new HgGlobalConfig();
|
||||
}
|
||||
|
||||
ConfigurationPermissions.write(config).check();
|
||||
@@ -21,15 +21,15 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
package sonia.scm.api.v2.resources;
|
||||
|
||||
import org.mapstruct.Mapper;
|
||||
import sonia.scm.repository.HgConfig;
|
||||
import sonia.scm.repository.HgGlobalConfig;
|
||||
|
||||
// Mapstruct does not support parameterized (i.e. non-default) constructors. Thus, we need to use field injection.
|
||||
@SuppressWarnings("squid:S3306")
|
||||
@Mapper
|
||||
public abstract class HgConfigDtoToHgConfigMapper {
|
||||
public abstract HgConfig map(HgConfigDto dto);
|
||||
public abstract class HgGlobalConfigDtoToHgConfigMapper {
|
||||
public abstract HgGlobalConfig map(HgGlobalGlobalConfigDto dto);
|
||||
}
|
||||
@@ -21,14 +21,14 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
package sonia.scm.api.v2.resources;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import sonia.scm.config.ConfigurationPermissions;
|
||||
import sonia.scm.plugin.Extension;
|
||||
import sonia.scm.repository.HgConfig;
|
||||
import sonia.scm.repository.HgGlobalConfig;
|
||||
import sonia.scm.web.JsonEnricherBase;
|
||||
import sonia.scm.web.JsonEnricherContext;
|
||||
|
||||
@@ -39,19 +39,19 @@ import static java.util.Collections.singletonMap;
|
||||
import static sonia.scm.web.VndMediaType.INDEX;
|
||||
|
||||
@Extension
|
||||
public class HgConfigInIndexResource extends JsonEnricherBase {
|
||||
public class HgGlobalConfigInIndexResource extends JsonEnricherBase {
|
||||
|
||||
private final Provider<ScmPathInfoStore> scmPathInfoStore;
|
||||
|
||||
@Inject
|
||||
public HgConfigInIndexResource(Provider<ScmPathInfoStore> scmPathInfoStore, ObjectMapper objectMapper) {
|
||||
public HgGlobalConfigInIndexResource(Provider<ScmPathInfoStore> scmPathInfoStore, ObjectMapper objectMapper) {
|
||||
super(objectMapper);
|
||||
this.scmPathInfoStore = scmPathInfoStore;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enrich(JsonEnricherContext context) {
|
||||
if (resultHasMediaType(INDEX, context) && ConfigurationPermissions.read(HgConfig.PERMISSION).isPermitted()) {
|
||||
if (resultHasMediaType(INDEX, context) && ConfigurationPermissions.read(HgGlobalConfig.PERMISSION).isPermitted()) {
|
||||
String hgConfigUrl = new LinkBuilder(scmPathInfoStore.get().get(), HgConfigResource.class)
|
||||
.method("get")
|
||||
.parameters()
|
||||
@@ -21,15 +21,16 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
package sonia.scm.api.v2.resources;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import de.otto.edison.hal.Links;
|
||||
import org.mapstruct.AfterMapping;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.MappingTarget;
|
||||
import sonia.scm.config.ConfigurationPermissions;
|
||||
import sonia.scm.repository.HgConfig;
|
||||
import sonia.scm.repository.HgGlobalConfig;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
@@ -39,27 +40,23 @@ import static de.otto.edison.hal.Links.linkingTo;
|
||||
// Mapstruct does not support parameterized (i.e. non-default) constructors. Thus, we need to use field injection.
|
||||
@SuppressWarnings("squid:S3306")
|
||||
@Mapper
|
||||
public abstract class HgConfigToHgConfigDtoMapper extends BaseMapper<HgConfig, HgConfigDto> {
|
||||
public abstract class HgGlobalConfigToHgGlobalConfigDtoMapper extends BaseMapper<HgGlobalConfig, HgGlobalGlobalConfigDto> {
|
||||
|
||||
@Inject
|
||||
private ScmPathInfoStore scmPathInfoStore;
|
||||
private HgConfigLinks links;
|
||||
|
||||
@VisibleForTesting
|
||||
void setLinks(HgConfigLinks links) {
|
||||
this.links = links;
|
||||
}
|
||||
|
||||
@AfterMapping
|
||||
void appendLinks(HgConfig config, @MappingTarget HgConfigDto target) {
|
||||
Links.Builder linksBuilder = linkingTo().self(self());
|
||||
void appendLinks(HgGlobalConfig config, @MappingTarget HgGlobalGlobalConfigDto target) {
|
||||
HgConfigLinks.ConfigLinks configLinks = links.global();
|
||||
Links.Builder linksBuilder = linkingTo().self(configLinks.get());
|
||||
if (ConfigurationPermissions.write(config).isPermitted()) {
|
||||
linksBuilder.single(link("update", update()));
|
||||
linksBuilder.single(link("update", configLinks.update()));
|
||||
}
|
||||
target.add(linksBuilder.build());
|
||||
}
|
||||
|
||||
private String self() {
|
||||
LinkBuilder linkBuilder = new LinkBuilder(scmPathInfoStore.get(), HgConfigResource.class);
|
||||
return linkBuilder.method("get").parameters().href();
|
||||
}
|
||||
|
||||
private String update() {
|
||||
LinkBuilder linkBuilder = new LinkBuilder(scmPathInfoStore.get(), HgConfigResource.class);
|
||||
return linkBuilder.method("update").parameters().href();
|
||||
}
|
||||
}
|
||||
@@ -34,12 +34,13 @@ import lombok.Setter;
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@SuppressWarnings("java:S2160") // we don't need equals for dto
|
||||
public class HgConfigDto extends HalRepresentation implements UpdateHgConfigDto {
|
||||
|
||||
public class HgGlobalGlobalConfigDto extends HalRepresentation implements UpdateHgGlobalConfigDto {
|
||||
|
||||
private boolean disabled;
|
||||
|
||||
@Encoding
|
||||
private String encoding;
|
||||
|
||||
private String hgBinary;
|
||||
private boolean showRevisionInId;
|
||||
private boolean enableHttpPostArgs;
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package sonia.scm.api.v2.resources;
|
||||
|
||||
import de.otto.edison.hal.HalRepresentation;
|
||||
import de.otto.edison.hal.Links;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@SuppressWarnings("java:S2160") // we don't need equals for a dto
|
||||
public class HgRepositoryConfigDto extends HalRepresentation {
|
||||
|
||||
@Encoding
|
||||
private String encoding;
|
||||
|
||||
public HgRepositoryConfigDto(Links links) {
|
||||
super(links);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package sonia.scm.api.v2.resources;
|
||||
|
||||
import sonia.scm.plugin.Extension;
|
||||
import sonia.scm.repository.HgRepositoryHandler;
|
||||
import sonia.scm.repository.Repository;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
@Extension
|
||||
@Enrich(Repository.class)
|
||||
public class HgRepositoryConfigEnricher implements HalEnricher {
|
||||
|
||||
private final HgConfigLinks links;
|
||||
|
||||
@Inject
|
||||
public HgRepositoryConfigEnricher(HgConfigLinks links) {
|
||||
this.links = links;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enrich(HalEnricherContext context, HalAppender appender) {
|
||||
Repository repository = context.oneRequireByType(Repository.class);
|
||||
if (isHgRepository(repository)) {
|
||||
appender.appendLink("configuration", links.repository(repository).get());
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isHgRepository(Repository repository) {
|
||||
return HgRepositoryHandler.TYPE_NAME.equals(repository.getType());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package sonia.scm.api.v2.resources;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import de.otto.edison.hal.Links;
|
||||
import org.mapstruct.Context;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.mapstruct.ObjectFactory;
|
||||
import sonia.scm.repository.HgRepositoryConfig;
|
||||
import sonia.scm.repository.Repository;
|
||||
import sonia.scm.repository.RepositoryPermissions;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static de.otto.edison.hal.Link.link;
|
||||
import static de.otto.edison.hal.Links.linkingTo;
|
||||
|
||||
@Mapper
|
||||
public abstract class HgRepositoryConfigMapper {
|
||||
|
||||
@Inject
|
||||
private HgConfigLinks links;
|
||||
|
||||
@VisibleForTesting
|
||||
void setLinks(HgConfigLinks links) {
|
||||
this.links = links;
|
||||
}
|
||||
|
||||
@Mapping(target = "attributes", ignore = true) // We do not map HAL attributes
|
||||
abstract HgRepositoryConfigDto map(@Context Repository repository, HgRepositoryConfig config);
|
||||
abstract HgRepositoryConfig map(HgRepositoryConfigDto dto);
|
||||
|
||||
@ObjectFactory
|
||||
HgRepositoryConfigDto createDto(@Context Repository repository) {
|
||||
HgConfigLinks.ConfigLinks configLinks = this.links.repository(repository);
|
||||
Links.Builder linksBuilder = linkingTo().self(configLinks.get());
|
||||
if (RepositoryPermissions.custom("hg", repository).isPermitted()) {
|
||||
linksBuilder.single(link("update", configLinks.update()));
|
||||
}
|
||||
return new HgRepositoryConfigDto(linksBuilder.build());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package sonia.scm.api.v2.resources;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.media.Content;
|
||||
import io.swagger.v3.oas.annotations.media.ExampleObject;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.parameters.RequestBody;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
import sonia.scm.repository.HgRepositoryConfigStore;
|
||||
import sonia.scm.repository.NamespaceAndName;
|
||||
import sonia.scm.repository.Repository;
|
||||
import sonia.scm.repository.RepositoryManager;
|
||||
import sonia.scm.web.HgVndMediaType;
|
||||
import sonia.scm.web.VndMediaType;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.validation.Valid;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.PUT;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
import static sonia.scm.ContextEntry.ContextBuilder.entity;
|
||||
import static sonia.scm.NotFoundException.notFound;
|
||||
|
||||
public class HgRepositoryConfigResource {
|
||||
|
||||
private final RepositoryManager repositoryManager;
|
||||
private final HgRepositoryConfigStore store;
|
||||
private final HgRepositoryConfigMapper mapper;
|
||||
|
||||
@Inject
|
||||
public HgRepositoryConfigResource(RepositoryManager repositoryManager, HgRepositoryConfigStore store, HgRepositoryConfigMapper mapper) {
|
||||
this.repositoryManager = repositoryManager;
|
||||
this.store = store;
|
||||
this.mapper = mapper;
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("")
|
||||
@Produces(HgVndMediaType.REPO_CONFIG)
|
||||
@Operation(
|
||||
summary = "Hg configuration",
|
||||
description = "Returns the global mercurial configuration.",
|
||||
tags = "Mercurial",
|
||||
operationId = "hg_get_repo_config"
|
||||
)
|
||||
@ApiResponse(
|
||||
responseCode = "200",
|
||||
description = "success",
|
||||
content = @Content(
|
||||
mediaType = HgVndMediaType.REPO_CONFIG,
|
||||
schema = @Schema(implementation = HgGlobalGlobalConfigDto.class)
|
||||
)
|
||||
)
|
||||
@ApiResponse(responseCode = "401", description = "not authenticated / invalid credentials")
|
||||
@ApiResponse(responseCode = "403", description = "not authorized, the current user does not have the \"repository:read:{repositoryId}\" privilege")
|
||||
@ApiResponse(
|
||||
responseCode = "500",
|
||||
description = "internal server error",
|
||||
content = @Content(
|
||||
mediaType = VndMediaType.ERROR_TYPE,
|
||||
schema = @Schema(implementation = ErrorDto.class)
|
||||
))
|
||||
public HgRepositoryConfigDto getHgRepositoryConfig(@PathParam("namespace") String namespace, @PathParam("name") String name) {
|
||||
Repository repository = getRepository(namespace, name);
|
||||
return mapper.map(repository, store.of(repository));
|
||||
}
|
||||
|
||||
@PUT
|
||||
@Path("")
|
||||
@Consumes(HgVndMediaType.REPO_CONFIG)
|
||||
@Operation(
|
||||
summary = "Modify hg configuration",
|
||||
description = "Modifies the repository specific mercurial configuration.",
|
||||
tags = "Mercurial",
|
||||
operationId = "hg_put_repo_config",
|
||||
requestBody = @RequestBody(
|
||||
content = @Content(
|
||||
mediaType = HgVndMediaType.CONFIG,
|
||||
schema = @Schema(implementation = UpdateHgGlobalConfigDto.class),
|
||||
examples = @ExampleObject(
|
||||
name = "Overwrites current configuration with this one.",
|
||||
value = "{\n \"encoding\":\"UTF-8\" \n}",
|
||||
summary = "Simple update configuration"
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
@ApiResponse(
|
||||
responseCode = "204",
|
||||
description = "update success"
|
||||
)
|
||||
@ApiResponse(responseCode = "401", description = "not authenticated / invalid credentials")
|
||||
@ApiResponse(responseCode = "403", description = "not authorized, the current user does not have the \"repository:hg:{repositoryId}\" privilege")
|
||||
@ApiResponse(
|
||||
responseCode = "500",
|
||||
description = "internal server error",
|
||||
content = @Content(
|
||||
mediaType = VndMediaType.ERROR_TYPE,
|
||||
schema = @Schema(implementation = ErrorDto.class)
|
||||
))
|
||||
public Response updateHgRepositoryConfig(
|
||||
@PathParam("namespace") String namespace,
|
||||
@PathParam("name") String name,
|
||||
@Valid HgRepositoryConfigDto dto
|
||||
) {
|
||||
Repository repository = getRepository(namespace, name);
|
||||
store.store(repository, mapper.map(dto));
|
||||
return Response.noContent().build();
|
||||
}
|
||||
|
||||
private Repository getRepository(String namespace, String name) {
|
||||
NamespaceAndName namespaceAndName = new NamespaceAndName(namespace, name);
|
||||
Repository repository = repositoryManager.get(namespaceAndName);
|
||||
if (repository == null) {
|
||||
throw notFound(entity(namespaceAndName));
|
||||
}
|
||||
return repository;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
package sonia.scm.api.v2.resources;
|
||||
|
||||
interface UpdateHgConfigDto {
|
||||
interface UpdateHgGlobalConfigDto {
|
||||
boolean isDisabled();
|
||||
|
||||
String getHgBinary();
|
||||
@@ -24,10 +24,10 @@
|
||||
|
||||
package sonia.scm.autoconfig;
|
||||
|
||||
import sonia.scm.repository.HgConfig;
|
||||
import sonia.scm.repository.HgGlobalConfig;
|
||||
|
||||
public interface AutoConfigurator {
|
||||
|
||||
void configure(HgConfig config);
|
||||
void configure(HgGlobalConfig config);
|
||||
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ package sonia.scm.autoconfig;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import sonia.scm.repository.HgConfig;
|
||||
import sonia.scm.repository.HgGlobalConfig;
|
||||
|
||||
public class NoOpAutoConfigurator implements AutoConfigurator {
|
||||
|
||||
@@ -36,7 +36,7 @@ public class NoOpAutoConfigurator implements AutoConfigurator {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(HgConfig config) {
|
||||
public void configure(HgGlobalConfig config) {
|
||||
// if we do not know the environment, we could not configure mercurial
|
||||
LOG.debug("no mercurial autoconfiguration available on this platform");
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ import com.google.common.base.Splitter;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import sonia.scm.repository.HgConfig;
|
||||
import sonia.scm.repository.HgGlobalConfig;
|
||||
import sonia.scm.repository.HgVerifier;
|
||||
|
||||
import java.io.File;
|
||||
@@ -68,7 +68,7 @@ public class PosixAutoConfigurator implements AutoConfigurator {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(HgConfig config) {
|
||||
public void configure(HgGlobalConfig config) {
|
||||
Optional<Path> hg = findInPath();
|
||||
if (hg.isPresent()) {
|
||||
config.setHgBinary(hg.get().toAbsolutePath().toString());
|
||||
|
||||
@@ -28,7 +28,7 @@ import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Splitter;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import sonia.scm.repository.HgConfig;
|
||||
import sonia.scm.repository.HgGlobalConfig;
|
||||
import sonia.scm.repository.HgVerifier;
|
||||
|
||||
import java.io.File;
|
||||
@@ -72,7 +72,7 @@ public class WindowsAutoConfigurator implements AutoConfigurator {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(HgConfig config) {
|
||||
public void configure(HgGlobalConfig config) {
|
||||
Set<String> fsPaths = new LinkedHashSet<>(pathFromEnv());
|
||||
resolveRegistryKeys(fsPaths);
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ public class DefaultHgEnvironmentBuilder implements HgEnvironmentBuilder {
|
||||
static final String ENV_TRANSACTION_ID = "SCM_TRANSACTION_ID";
|
||||
|
||||
private final AccessTokenBuilderFactory accessTokenBuilderFactory;
|
||||
private final HgRepositoryHandler repositoryHandler;
|
||||
private final HgConfigResolver configResolver;
|
||||
private final HookEnvironment hookEnvironment;
|
||||
private final HookServer server;
|
||||
|
||||
@@ -68,11 +68,11 @@ public class DefaultHgEnvironmentBuilder implements HgEnvironmentBuilder {
|
||||
|
||||
@Inject
|
||||
public DefaultHgEnvironmentBuilder(
|
||||
AccessTokenBuilderFactory accessTokenBuilderFactory, HgRepositoryHandler repositoryHandler,
|
||||
AccessTokenBuilderFactory accessTokenBuilderFactory, HgConfigResolver configResolver,
|
||||
HookEnvironment hookEnvironment, HookServer server
|
||||
) {
|
||||
this.accessTokenBuilderFactory = accessTokenBuilderFactory;
|
||||
this.repositoryHandler = repositoryHandler;
|
||||
this.configResolver = configResolver;
|
||||
this.hookEnvironment = hookEnvironment;
|
||||
this.server = server;
|
||||
}
|
||||
@@ -94,9 +94,8 @@ public class DefaultHgEnvironmentBuilder implements HgEnvironmentBuilder {
|
||||
}
|
||||
|
||||
private void read(ImmutableMap.Builder<String, String> env, Repository repository) {
|
||||
HgConfig config = repositoryHandler.getConfig();
|
||||
|
||||
File directory = repositoryHandler.getDirectory(repository.getId());
|
||||
HgConfig config = configResolver.resolve(repository);
|
||||
File directory = config.getDirectory();
|
||||
|
||||
env.put(ENV_REPOSITORY_NAME, repository.getNamespace() + "/" + repository.getName());
|
||||
env.put(ENV_REPOSITORY_ID, repository.getId());
|
||||
|
||||
@@ -24,128 +24,17 @@
|
||||
|
||||
package sonia.scm.repository;
|
||||
|
||||
import lombok.Value;
|
||||
|
||||
import sonia.scm.util.Util;
|
||||
import java.io.File;
|
||||
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import javax.xml.bind.annotation.XmlTransient;
|
||||
@Value
|
||||
public class HgConfig {
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
@XmlRootElement(name = "config")
|
||||
public class HgConfig extends RepositoryConfig {
|
||||
|
||||
public static final String PERMISSION = "hg";
|
||||
|
||||
@Override
|
||||
@XmlTransient // Only for permission checks, don't serialize to XML
|
||||
public String getId() {
|
||||
// Don't change this without migrating SCM permission configuration!
|
||||
return PERMISSION;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getEncoding()
|
||||
{
|
||||
return encoding;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getHgBinary()
|
||||
{
|
||||
return hgBinary;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isShowRevisionInId()
|
||||
{
|
||||
return showRevisionInId;
|
||||
}
|
||||
|
||||
public boolean isEnableHttpPostArgs() {
|
||||
return enableHttpPostArgs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public boolean isValid()
|
||||
{
|
||||
return super.isValid() && Util.isNotEmpty(hgBinary);
|
||||
}
|
||||
|
||||
//~--- set methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param encoding
|
||||
*/
|
||||
public void setEncoding(String encoding)
|
||||
{
|
||||
this.encoding = encoding;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param hgBinary
|
||||
*/
|
||||
public void setHgBinary(String hgBinary)
|
||||
{
|
||||
this.hgBinary = hgBinary;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param showRevisionInId
|
||||
*/
|
||||
public void setShowRevisionInId(boolean showRevisionInId)
|
||||
{
|
||||
this.showRevisionInId = showRevisionInId;
|
||||
}
|
||||
|
||||
public void setEnableHttpPostArgs(boolean enableHttpPostArgs) {
|
||||
this.enableHttpPostArgs = enableHttpPostArgs;
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private String encoding = "UTF-8";
|
||||
|
||||
/** Field description */
|
||||
private String hgBinary;
|
||||
|
||||
/** Field description */
|
||||
private boolean showRevisionInId = false;
|
||||
|
||||
private boolean enableHttpPostArgs = false;
|
||||
String hgBinary;
|
||||
String encoding;
|
||||
boolean showRevisionInId;
|
||||
boolean enableHttpPostArgs;
|
||||
File directory;
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package sonia.scm.repository;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.MoreObjects;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.io.File;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class HgConfigResolver {
|
||||
|
||||
private final HgRepositoryHandler repositoryHandler;
|
||||
private final Function<Repository, HgRepositoryConfig> repositoryConfigResolver;
|
||||
private final Function<Repository, File> directoryResolver;
|
||||
|
||||
@Inject
|
||||
public HgConfigResolver(HgRepositoryHandler repositoryHandler, HgRepositoryConfigStore repositoryConfigStore) {
|
||||
this(
|
||||
repositoryHandler,
|
||||
repositoryConfigStore::of,
|
||||
repository -> repositoryHandler.getDirectory(repository.getId())
|
||||
);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public HgConfigResolver(HgRepositoryHandler repositoryHandler) {
|
||||
this(
|
||||
repositoryHandler,
|
||||
repository -> repositoryHandler.getDirectory(repository.getId())
|
||||
);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public HgConfigResolver(HgRepositoryHandler repositoryHandler, Function<Repository, File> directoryResolver) {
|
||||
this.repositoryHandler = repositoryHandler;
|
||||
this.repositoryConfigResolver = (repository -> new HgRepositoryConfig());
|
||||
this.directoryResolver = directoryResolver;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public HgConfigResolver(HgRepositoryHandler repositoryHandler, Function<Repository, HgRepositoryConfig> repositoryConfigResolver, Function<Repository, File> directoryResolver) {
|
||||
this.repositoryHandler = repositoryHandler;
|
||||
this.repositoryConfigResolver = repositoryConfigResolver;
|
||||
this.directoryResolver = directoryResolver;
|
||||
}
|
||||
|
||||
public boolean isConfigured() {
|
||||
return repositoryHandler.isConfigured();
|
||||
}
|
||||
|
||||
public HgConfig resolve(Repository repository) {
|
||||
HgGlobalConfig globalConfig = repositoryHandler.getConfig();
|
||||
HgRepositoryConfig repositoryConfig = repositoryConfigResolver.apply(repository);
|
||||
return new HgConfig(
|
||||
globalConfig.getHgBinary(),
|
||||
MoreObjects.firstNonNull(repositoryConfig.getEncoding(), globalConfig.getEncoding()),
|
||||
globalConfig.isShowRevisionInId(),
|
||||
globalConfig.isEnableHttpPostArgs(),
|
||||
directoryResolver.apply(repository)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package sonia.scm.repository;
|
||||
|
||||
|
||||
import sonia.scm.util.Util;
|
||||
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import javax.xml.bind.annotation.XmlTransient;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
@XmlRootElement(name = "config")
|
||||
public class HgGlobalConfig extends RepositoryConfig {
|
||||
|
||||
public static final String PERMISSION = "hg";
|
||||
|
||||
@Override
|
||||
@XmlTransient // Only for permission checks, don't serialize to XML
|
||||
public String getId() {
|
||||
// Don't change this without migrating SCM permission configuration!
|
||||
return PERMISSION;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getEncoding()
|
||||
{
|
||||
return encoding;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getHgBinary()
|
||||
{
|
||||
return hgBinary;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isShowRevisionInId()
|
||||
{
|
||||
return showRevisionInId;
|
||||
}
|
||||
|
||||
public boolean isEnableHttpPostArgs() {
|
||||
return enableHttpPostArgs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public boolean isValid()
|
||||
{
|
||||
return super.isValid() && Util.isNotEmpty(hgBinary);
|
||||
}
|
||||
|
||||
//~--- set methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param encoding
|
||||
*/
|
||||
public void setEncoding(String encoding)
|
||||
{
|
||||
this.encoding = encoding;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param hgBinary
|
||||
*/
|
||||
public void setHgBinary(String hgBinary)
|
||||
{
|
||||
this.hgBinary = hgBinary;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param showRevisionInId
|
||||
*/
|
||||
public void setShowRevisionInId(boolean showRevisionInId)
|
||||
{
|
||||
this.showRevisionInId = showRevisionInId;
|
||||
}
|
||||
|
||||
public void setEnableHttpPostArgs(boolean enableHttpPostArgs) {
|
||||
this.enableHttpPostArgs = enableHttpPostArgs;
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private String encoding = "UTF-8";
|
||||
|
||||
/** Field description */
|
||||
private String hgBinary;
|
||||
|
||||
/** Field description */
|
||||
private boolean showRevisionInId = false;
|
||||
|
||||
private boolean enableHttpPostArgs = false;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package sonia.scm.repository;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
@Data
|
||||
@XmlRootElement
|
||||
public class HgRepositoryConfig {
|
||||
String encoding;
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package sonia.scm.repository;
|
||||
|
||||
import sonia.scm.store.ConfigurationStore;
|
||||
import sonia.scm.store.ConfigurationStoreFactory;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
public class HgRepositoryConfigStore {
|
||||
|
||||
private static final String STORE_NAME = "hgConfig";
|
||||
private final ConfigurationStoreFactory factory;
|
||||
|
||||
@Inject
|
||||
public HgRepositoryConfigStore(ConfigurationStoreFactory factory) {
|
||||
this.factory = factory;
|
||||
}
|
||||
|
||||
public HgRepositoryConfig of(Repository repository) {
|
||||
ConfigurationStore<HgRepositoryConfig> store = store(repository);
|
||||
return store.getOptional().orElse(new HgRepositoryConfig());
|
||||
}
|
||||
|
||||
public void store(Repository repository, HgRepositoryConfig config) {
|
||||
RepositoryPermissions.custom("hg", repository).check();
|
||||
store(repository).set(config);
|
||||
}
|
||||
|
||||
private ConfigurationStore<HgRepositoryConfig> store(Repository repository) {
|
||||
return factory.withType(HgRepositoryConfig.class)
|
||||
.withName(STORE_NAME)
|
||||
.forRepository(repository)
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -25,7 +25,6 @@
|
||||
package sonia.scm.repository;
|
||||
|
||||
import com.aragost.javahg.RepositoryConfiguration;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import sonia.scm.repository.hooks.HookEnvironment;
|
||||
@@ -38,32 +37,21 @@ import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.charset.UnsupportedCharsetException;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
@Singleton
|
||||
public class HgRepositoryFactory {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(HgRepositoryFactory.class);
|
||||
|
||||
private final HgRepositoryHandler handler;
|
||||
private final HgConfigResolver configResolver;
|
||||
private final HookEnvironment hookEnvironment;
|
||||
private final HgEnvironmentBuilder environmentBuilder;
|
||||
private final Function<Repository, File> directoryResolver;
|
||||
|
||||
@Inject
|
||||
public HgRepositoryFactory(HgRepositoryHandler handler, HookEnvironment hookEnvironment, HgEnvironmentBuilder environmentBuilder) {
|
||||
this(
|
||||
handler, hookEnvironment, environmentBuilder,
|
||||
repository -> handler.getDirectory(repository.getId())
|
||||
);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public HgRepositoryFactory(HgRepositoryHandler handler, HookEnvironment hookEnvironment, HgEnvironmentBuilder environmentBuilder, Function<Repository, File> directoryResolver) {
|
||||
this.handler = handler;
|
||||
public HgRepositoryFactory(HgConfigResolver configResolver, HookEnvironment hookEnvironment, HgEnvironmentBuilder environmentBuilder) {
|
||||
this.configResolver = configResolver;
|
||||
this.hookEnvironment = hookEnvironment;
|
||||
this.environmentBuilder = environmentBuilder;
|
||||
this.directoryResolver = directoryResolver;
|
||||
}
|
||||
|
||||
public com.aragost.javahg.Repository openForRead(Repository repository) {
|
||||
@@ -75,7 +63,8 @@ public class HgRepositoryFactory {
|
||||
}
|
||||
|
||||
private com.aragost.javahg.Repository open(Repository repository, Map<String, String> environment) {
|
||||
File directory = directoryResolver.apply(repository);
|
||||
HgConfig config = configResolver.resolve(repository);
|
||||
File directory = config.getDirectory();
|
||||
|
||||
RepositoryConfiguration repoConfiguration = RepositoryConfiguration.DEFAULT;
|
||||
repoConfiguration.getEnvironment().putAll(environment);
|
||||
@@ -84,18 +73,18 @@ public class HgRepositoryFactory {
|
||||
boolean pending = hookEnvironment.isPending();
|
||||
repoConfiguration.setEnablePendingChangesets(pending);
|
||||
|
||||
Charset encoding = encoding();
|
||||
Charset encoding = encoding(config);
|
||||
repoConfiguration.setEncoding(encoding);
|
||||
|
||||
repoConfiguration.setHgBin(handler.getConfig().getHgBinary());
|
||||
repoConfiguration.setHgBin(config.getHgBinary());
|
||||
|
||||
LOG.trace("open hg repository {}: encoding: {}, pending: {}", directory, encoding, pending);
|
||||
|
||||
return com.aragost.javahg.Repository.open(repoConfiguration, directory);
|
||||
}
|
||||
|
||||
private Charset encoding() {
|
||||
String charset = handler.getConfig().getEncoding();
|
||||
private Charset encoding(HgConfig config) {
|
||||
String charset = config.getEncoding();
|
||||
try {
|
||||
return Charset.forName(charset);
|
||||
} catch (UnsupportedCharsetException ex) {
|
||||
|
||||
@@ -55,7 +55,7 @@ import java.io.OutputStream;
|
||||
@Singleton
|
||||
@Extension
|
||||
public class HgRepositoryHandler
|
||||
extends AbstractSimpleRepositoryHandler<HgConfig> {
|
||||
extends AbstractSimpleRepositoryHandler<HgGlobalConfig> {
|
||||
|
||||
public static final String TYPE_DISPLAYNAME = "Mercurial";
|
||||
public static final String TYPE_NAME = "hg";
|
||||
@@ -84,7 +84,7 @@ public class HgRepositoryHandler
|
||||
this.configurator = configurator;
|
||||
}
|
||||
|
||||
public void doAutoConfiguration(HgConfig autoConfig) {
|
||||
public void doAutoConfiguration(HgGlobalConfig autoConfig) {
|
||||
configurator.configure(autoConfig);
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@ public class HgRepositoryHandler
|
||||
super.loadConfig();
|
||||
|
||||
if (config == null) {
|
||||
config = new HgConfig();
|
||||
config = new HgGlobalConfig();
|
||||
storeConfig();
|
||||
}
|
||||
|
||||
@@ -109,7 +109,7 @@ public class HgRepositoryHandler
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isConfigValid(HgConfig config) {
|
||||
private boolean isConfigValid(HgGlobalConfig config) {
|
||||
return config.isValid() && new HgVerifier().isValid(config);
|
||||
}
|
||||
|
||||
@@ -175,8 +175,8 @@ public class HgRepositoryHandler
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<HgConfig> getConfigClass() {
|
||||
return HgConfig.class;
|
||||
protected Class<HgGlobalConfig> getConfigClass() {
|
||||
return HgGlobalConfig.class;
|
||||
}
|
||||
|
||||
private void writeHgExtensions(SCMContextProvider context) {
|
||||
|
||||
@@ -47,7 +47,7 @@ public class HgVerifier {
|
||||
this.versionResolver = versionResolver;
|
||||
}
|
||||
|
||||
public boolean isValid(HgConfig config) {
|
||||
public boolean isValid(HgGlobalConfig config) {
|
||||
return isValid(config.getHgBinary());
|
||||
}
|
||||
|
||||
|
||||
@@ -25,8 +25,8 @@
|
||||
package sonia.scm.repository.hooks;
|
||||
|
||||
import sonia.scm.NotFoundException;
|
||||
import sonia.scm.repository.HgConfigResolver;
|
||||
import sonia.scm.repository.HgRepositoryFactory;
|
||||
import sonia.scm.repository.HgRepositoryHandler;
|
||||
import sonia.scm.repository.Repository;
|
||||
import sonia.scm.repository.RepositoryManager;
|
||||
import sonia.scm.repository.spi.HgHookContextProvider;
|
||||
@@ -36,13 +36,13 @@ import javax.inject.Inject;
|
||||
public class HookContextProviderFactory {
|
||||
|
||||
private final RepositoryManager repositoryManager;
|
||||
private final HgRepositoryHandler repositoryHandler;
|
||||
private final HgConfigResolver configResolver;
|
||||
private final HgRepositoryFactory repositoryFactory;
|
||||
|
||||
@Inject
|
||||
public HookContextProviderFactory(RepositoryManager repositoryManager, HgRepositoryHandler repositoryHandler, HgRepositoryFactory repositoryFactory) {
|
||||
public HookContextProviderFactory(RepositoryManager repositoryManager, HgConfigResolver configResolver, HgRepositoryFactory repositoryFactory) {
|
||||
this.repositoryManager = repositoryManager;
|
||||
this.repositoryHandler = repositoryHandler;
|
||||
this.configResolver = configResolver;
|
||||
this.repositoryFactory = repositoryFactory;
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ public class HookContextProviderFactory {
|
||||
if (repository == null) {
|
||||
throw new NotFoundException(Repository.class, repositoryId);
|
||||
}
|
||||
return new HgHookContextProvider(repositoryHandler, repositoryFactory, repository, node);
|
||||
return new HgHookContextProvider(configResolver, repositoryFactory, repository, node);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -28,8 +28,8 @@ package sonia.scm.repository.spi;
|
||||
|
||||
import com.aragost.javahg.Repository;
|
||||
import sonia.scm.repository.HgConfig;
|
||||
import sonia.scm.repository.HgConfigResolver;
|
||||
import sonia.scm.repository.HgRepositoryFactory;
|
||||
import sonia.scm.repository.HgRepositoryHandler;
|
||||
import sonia.scm.repository.RepositoryProvider;
|
||||
|
||||
import java.io.Closeable;
|
||||
@@ -43,14 +43,14 @@ import java.io.File;
|
||||
*/
|
||||
public class HgCommandContext implements Closeable, RepositoryProvider {
|
||||
|
||||
private final HgRepositoryHandler handler;
|
||||
private final HgConfigResolver configResolver;
|
||||
private final HgRepositoryFactory factory;
|
||||
private final sonia.scm.repository.Repository scmRepository;
|
||||
|
||||
private Repository repository;
|
||||
|
||||
public HgCommandContext(HgRepositoryHandler handler, HgRepositoryFactory factory, sonia.scm.repository.Repository scmRepository) {
|
||||
this.handler = handler;
|
||||
public HgCommandContext(HgConfigResolver configResolver, HgRepositoryFactory factory, sonia.scm.repository.Repository scmRepository) {
|
||||
this.configResolver = configResolver;
|
||||
this.factory = factory;
|
||||
this.scmRepository = scmRepository;
|
||||
}
|
||||
@@ -66,14 +66,17 @@ public class HgCommandContext implements Closeable, RepositoryProvider {
|
||||
return factory.openForWrite(scmRepository);
|
||||
}
|
||||
|
||||
private HgConfig config;
|
||||
|
||||
public HgConfig getConfig()
|
||||
{
|
||||
return handler.getConfig();
|
||||
public HgConfig getConfig() {
|
||||
if (config == null) {
|
||||
config = configResolver.resolve(scmRepository);
|
||||
}
|
||||
return config;
|
||||
}
|
||||
|
||||
public File getDirectory() {
|
||||
return handler.getDirectory(scmRepository.getId());
|
||||
return getConfig().getDirectory();
|
||||
}
|
||||
|
||||
public sonia.scm.repository.Repository getScmRepository() {
|
||||
@@ -85,7 +88,6 @@ public class HgCommandContext implements Closeable, RepositoryProvider {
|
||||
return getScmRepository();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
if (repository != null) {
|
||||
|
||||
@@ -27,8 +27,9 @@ package sonia.scm.repository.spi;
|
||||
import com.aragost.javahg.Repository;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import sonia.scm.repository.HgConfig;
|
||||
import sonia.scm.repository.HgConfigResolver;
|
||||
import sonia.scm.repository.HgRepositoryFactory;
|
||||
import sonia.scm.repository.HgRepositoryHandler;
|
||||
import sonia.scm.repository.spi.javahg.HgLogChangesetCommand;
|
||||
import sonia.scm.web.HgUtil;
|
||||
|
||||
@@ -40,15 +41,15 @@ public class HgHookChangesetProvider implements HookChangesetProvider {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(HgHookChangesetProvider.class);
|
||||
|
||||
private final HgRepositoryHandler handler;
|
||||
private final HgConfigResolver configResolver;
|
||||
private final HgRepositoryFactory factory;
|
||||
private final sonia.scm.repository.Repository scmRepository;
|
||||
private final String startRev;
|
||||
|
||||
private HookChangesetResponse response;
|
||||
|
||||
public HgHookChangesetProvider(HgRepositoryHandler handler, HgRepositoryFactory factory, sonia.scm.repository.Repository scmRepository, String startRev) {
|
||||
this.handler = handler;
|
||||
public HgHookChangesetProvider(HgConfigResolver configResolver, HgRepositoryFactory factory, sonia.scm.repository.Repository scmRepository, String startRev) {
|
||||
this.configResolver = configResolver;
|
||||
this.factory = factory;
|
||||
this.scmRepository = scmRepository;
|
||||
this.startRev = startRev;
|
||||
@@ -62,7 +63,8 @@ public class HgHookChangesetProvider implements HookChangesetProvider {
|
||||
try {
|
||||
repository = factory.openForRead(scmRepository);
|
||||
|
||||
HgLogChangesetCommand cmd = HgLogChangesetCommand.on(repository, handler.getConfig());
|
||||
HgConfig config = configResolver.resolve(scmRepository);
|
||||
HgLogChangesetCommand cmd = HgLogChangesetCommand.on(repository, config);
|
||||
|
||||
response = new HookChangesetResponse(
|
||||
cmd.rev(startRev.concat(":").concat(HgUtil.REVISION_TIP)).execute()
|
||||
|
||||
@@ -26,8 +26,8 @@ package sonia.scm.repository.spi;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import sonia.scm.repository.HgConfigResolver;
|
||||
import sonia.scm.repository.HgRepositoryFactory;
|
||||
import sonia.scm.repository.HgRepositoryHandler;
|
||||
import sonia.scm.repository.Repository;
|
||||
import sonia.scm.repository.api.HgHookBranchProvider;
|
||||
import sonia.scm.repository.api.HgHookMessageProvider;
|
||||
@@ -61,8 +61,8 @@ public class HgHookContextProvider extends HookContextProvider {
|
||||
private HgHookBranchProvider hookBranchProvider;
|
||||
private HgHookTagProvider hookTagProvider;
|
||||
|
||||
public HgHookContextProvider(HgRepositoryHandler handler, HgRepositoryFactory factory, Repository repository, String startRev) {
|
||||
this.hookChangesetProvider = new HgHookChangesetProvider(handler, factory, repository, startRev);
|
||||
public HgHookContextProvider(HgConfigResolver configResolver, HgRepositoryFactory factory, Repository repository, String startRev) {
|
||||
this.hookChangesetProvider = new HgHookChangesetProvider(configResolver, factory, repository, startRev);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -27,6 +27,7 @@ package sonia.scm.repository.spi;
|
||||
import com.google.common.io.Closeables;
|
||||
import sonia.scm.event.ScmEventBus;
|
||||
import sonia.scm.repository.Feature;
|
||||
import sonia.scm.repository.HgConfigResolver;
|
||||
import sonia.scm.repository.HgRepositoryFactory;
|
||||
import sonia.scm.repository.HgRepositoryHandler;
|
||||
import sonia.scm.repository.Repository;
|
||||
@@ -70,6 +71,7 @@ public class HgRepositoryServiceProvider extends RepositoryServiceProvider {
|
||||
private final ScmEventBus eventBus;
|
||||
|
||||
HgRepositoryServiceProvider(HgRepositoryHandler handler,
|
||||
HgConfigResolver configResolver,
|
||||
HgRepositoryFactory factory,
|
||||
HgRepositoryHookEventFactory eventFactory,
|
||||
ScmEventBus eventBus,
|
||||
@@ -77,7 +79,7 @@ public class HgRepositoryServiceProvider extends RepositoryServiceProvider {
|
||||
this.handler = handler;
|
||||
this.eventBus = eventBus;
|
||||
this.eventFactory = eventFactory;
|
||||
this.context = new HgCommandContext(handler, factory, repository);
|
||||
this.context = new HgCommandContext(configResolver, factory, repository);
|
||||
this.lazyChangesetResolver = new HgLazyChangesetResolver(factory, repository);
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ package sonia.scm.repository.spi;
|
||||
import com.google.inject.Inject;
|
||||
import sonia.scm.event.ScmEventBus;
|
||||
import sonia.scm.plugin.Extension;
|
||||
import sonia.scm.repository.HgConfigResolver;
|
||||
import sonia.scm.repository.HgRepositoryFactory;
|
||||
import sonia.scm.repository.HgRepositoryHandler;
|
||||
import sonia.scm.repository.Repository;
|
||||
@@ -38,17 +39,20 @@ import sonia.scm.repository.Repository;
|
||||
public class HgRepositoryServiceResolver implements RepositoryServiceResolver {
|
||||
|
||||
private final HgRepositoryHandler handler;
|
||||
private final HgConfigResolver configResolver;
|
||||
private final HgRepositoryFactory factory;
|
||||
private final ScmEventBus eventBus;
|
||||
private final HgRepositoryHookEventFactory eventFactory;
|
||||
|
||||
@Inject
|
||||
public HgRepositoryServiceResolver(HgRepositoryHandler handler,
|
||||
HgConfigResolver configResolver,
|
||||
HgRepositoryFactory factory,
|
||||
ScmEventBus eventBus,
|
||||
HgRepositoryHookEventFactory eventFactory
|
||||
) {
|
||||
this.handler = handler;
|
||||
this.configResolver = configResolver;
|
||||
this.factory = factory;
|
||||
this.eventBus = eventBus;
|
||||
this.eventFactory = eventFactory;
|
||||
@@ -59,7 +63,7 @@ public class HgRepositoryServiceResolver implements RepositoryServiceResolver {
|
||||
HgRepositoryServiceProvider provider = null;
|
||||
|
||||
if (HgRepositoryHandler.TYPE_NAME.equalsIgnoreCase(repository.getType())) {
|
||||
provider = new HgRepositoryServiceProvider(handler, factory, eventFactory, eventBus, repository);
|
||||
provider = new HgRepositoryServiceProvider(handler, configResolver, factory, eventFactory, eventBus, repository);
|
||||
}
|
||||
|
||||
return provider;
|
||||
|
||||
@@ -28,7 +28,7 @@ import com.google.common.io.ByteStreams;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import sonia.scm.SCMContext;
|
||||
import sonia.scm.repository.HgConfig;
|
||||
import sonia.scm.repository.HgGlobalConfig;
|
||||
import sonia.scm.repository.HgExtensions;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -41,15 +41,15 @@ public class HgVersionCommand {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(HgVersionCommand.class);
|
||||
public static final String UNKNOWN = "python/x.y.z mercurial/x.y.z";
|
||||
|
||||
private final HgConfig config;
|
||||
private final HgGlobalConfig config;
|
||||
private final String extension;
|
||||
private final ProcessExecutor executor;
|
||||
|
||||
public HgVersionCommand(HgConfig config) {
|
||||
public HgVersionCommand(HgGlobalConfig config) {
|
||||
this(config, extension(), command -> new ProcessBuilder(command).start());
|
||||
}
|
||||
|
||||
HgVersionCommand(HgConfig config, String extension, ProcessExecutor executor) {
|
||||
HgVersionCommand(HgGlobalConfig config, String extension, ProcessExecutor executor) {
|
||||
this.config = config;
|
||||
this.extension = extension;
|
||||
this.executor = executor;
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
package sonia.scm.repository.spi.javahg;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
@@ -61,9 +61,7 @@ public class HgIncomingChangesetCommand
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static HgIncomingChangesetCommand on(Repository repository,
|
||||
HgConfig config)
|
||||
{
|
||||
public static HgIncomingChangesetCommand on(Repository repository, HgConfig config) {
|
||||
return new HgIncomingChangesetCommand(repository, config);
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
package sonia.scm.repository.spi.javahg;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
@@ -52,9 +52,7 @@ public abstract class HgIncomingOutgoingChangesetCommand
|
||||
* @param repository
|
||||
* @param config
|
||||
*/
|
||||
public HgIncomingOutgoingChangesetCommand(Repository repository,
|
||||
HgConfig config)
|
||||
{
|
||||
public HgIncomingOutgoingChangesetCommand(Repository repository, HgConfig config) {
|
||||
super(repository, config);
|
||||
}
|
||||
|
||||
|
||||
@@ -21,13 +21,12 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
package sonia.scm.repository.spi.javahg;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import com.aragost.javahg.Repository;
|
||||
|
||||
import sonia.scm.repository.HgConfig;
|
||||
|
||||
/**
|
||||
|
||||
@@ -31,10 +31,10 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import sonia.scm.SCMContext;
|
||||
import sonia.scm.config.ScmConfiguration;
|
||||
import sonia.scm.repository.HgConfig;
|
||||
import sonia.scm.repository.HgEnvironmentBuilder;
|
||||
import sonia.scm.repository.HgExtensions;
|
||||
import sonia.scm.repository.HgRepositoryHandler;
|
||||
import sonia.scm.repository.HgConfig;
|
||||
import sonia.scm.repository.HgConfigResolver;
|
||||
import sonia.scm.repository.Repository;
|
||||
import sonia.scm.repository.RepositoryRequestListenerUtil;
|
||||
import sonia.scm.repository.spi.ScmProviderHttpServlet;
|
||||
@@ -60,38 +60,41 @@ import java.util.List;
|
||||
@Singleton
|
||||
public class HgCGIServlet extends HttpServlet implements ScmProviderHttpServlet {
|
||||
|
||||
/** Field description */
|
||||
private static final long serialVersionUID = -3492811300905099810L;
|
||||
|
||||
/** the logger for HgCGIServlet */
|
||||
private static final Logger logger =
|
||||
LoggerFactory.getLogger(HgCGIServlet.class);
|
||||
|
||||
//~--- constructors ---------------------------------------------------------
|
||||
private final CGIExecutorFactory cgiExecutorFactory;
|
||||
private final HgConfigResolver configResolver;
|
||||
private final File extension;
|
||||
private final ScmConfiguration configuration;
|
||||
private final HgCGIExceptionHandler exceptionHandler;
|
||||
private final RepositoryRequestListenerUtil requestListenerUtil;
|
||||
private final HgEnvironmentBuilder environmentBuilder;
|
||||
|
||||
@Inject
|
||||
public HgCGIServlet(CGIExecutorFactory cgiExecutorFactory,
|
||||
HgConfigResolver configResolver,
|
||||
ScmConfiguration configuration,
|
||||
HgRepositoryHandler handler,
|
||||
RepositoryRequestListenerUtil requestListenerUtil,
|
||||
HgEnvironmentBuilder environmentBuilder)
|
||||
{
|
||||
this.cgiExecutorFactory = cgiExecutorFactory;
|
||||
this.configResolver = configResolver;
|
||||
this.configuration = configuration;
|
||||
this.handler = handler;
|
||||
this.requestListenerUtil = requestListenerUtil;
|
||||
this.environmentBuilder = environmentBuilder;
|
||||
this.exceptionHandler = new HgCGIExceptionHandler();
|
||||
this.extension = HgExtensions.CGISERVE.getFile(SCMContext.getContext());
|
||||
}
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
public void service(HttpServletRequest request,
|
||||
HttpServletResponse response, Repository repository)
|
||||
{
|
||||
if (!handler.isConfigured())
|
||||
if (!configResolver.isConfigured())
|
||||
{
|
||||
exceptionHandler.sendFormattedError(request, response,
|
||||
HgCGIExceptionHandler.ERROR_NOT_CONFIGURED);
|
||||
@@ -141,10 +144,9 @@ public class HgCGIServlet extends HttpServlet implements ScmProviderHttpServlet
|
||||
EnvList env = executor.getEnvironment();
|
||||
environmentBuilder.write(repository).forEach(env::set);
|
||||
|
||||
File directory = handler.getDirectory(repository.getId());
|
||||
executor.setWorkDirectory(directory);
|
||||
HgConfig config = configResolver.resolve(repository);
|
||||
executor.setWorkDirectory(config.getDirectory());
|
||||
|
||||
HgConfig config = handler.getConfig();
|
||||
executor.setArgs(createArgs(config));
|
||||
executor.execute(config.getHgBinary());
|
||||
}
|
||||
@@ -174,26 +176,4 @@ public class HgCGIServlet extends HttpServlet implements ScmProviderHttpServlet
|
||||
args.add("--config");
|
||||
args.add(key + "=" + value);
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private final CGIExecutorFactory cgiExecutorFactory;
|
||||
|
||||
/** Field description */
|
||||
private final File extension;
|
||||
|
||||
/** Field description */
|
||||
private final ScmConfiguration configuration;
|
||||
|
||||
/** Field description */
|
||||
private final HgCGIExceptionHandler exceptionHandler;
|
||||
|
||||
/** Field description */
|
||||
private final HgRepositoryHandler handler;
|
||||
|
||||
/** Field description */
|
||||
private final RepositoryRequestListenerUtil requestListenerUtil;
|
||||
|
||||
private final HgEnvironmentBuilder environmentBuilder;
|
||||
}
|
||||
|
||||
@@ -28,8 +28,9 @@ package sonia.scm.web;
|
||||
|
||||
import com.google.inject.servlet.ServletModule;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
import sonia.scm.api.v2.resources.HgConfigDtoToHgConfigMapper;
|
||||
import sonia.scm.api.v2.resources.HgConfigToHgConfigDtoMapper;
|
||||
import sonia.scm.api.v2.resources.HgGlobalConfigDtoToHgConfigMapper;
|
||||
import sonia.scm.api.v2.resources.HgGlobalConfigToHgGlobalConfigDtoMapper;
|
||||
import sonia.scm.api.v2.resources.HgRepositoryConfigMapper;
|
||||
import sonia.scm.plugin.Extension;
|
||||
import sonia.scm.repository.spi.HgWorkingCopyFactory;
|
||||
import sonia.scm.repository.spi.SimpleHgWorkingCopyFactory;
|
||||
@@ -43,8 +44,9 @@ public class HgServletModule extends ServletModule {
|
||||
|
||||
@Override
|
||||
protected void configureServlets() {
|
||||
bind(HgConfigDtoToHgConfigMapper.class).to(Mappers.getMapper(HgConfigDtoToHgConfigMapper.class).getClass());
|
||||
bind(HgConfigToHgConfigDtoMapper.class).to(Mappers.getMapper(HgConfigToHgConfigDtoMapper.class).getClass());
|
||||
bind(HgGlobalConfigDtoToHgConfigMapper.class).to(Mappers.getMapperClass(HgGlobalConfigDtoToHgConfigMapper.class));
|
||||
bind(HgGlobalConfigToHgGlobalConfigDtoMapper.class).to(Mappers.getMapperClass(HgGlobalConfigToHgGlobalConfigDtoMapper.class));
|
||||
bind(HgRepositoryConfigMapper.class).to(Mappers.getMapperClass(HgRepositoryConfigMapper.class));
|
||||
|
||||
bind(HgWorkingCopyFactory.class).to(SimpleHgWorkingCopyFactory.class);
|
||||
}
|
||||
|
||||
@@ -21,13 +21,14 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
package sonia.scm.web;
|
||||
|
||||
|
||||
public class HgVndMediaType {
|
||||
private static final String PREFIX = VndMediaType.PREFIX + "hgConfig";
|
||||
|
||||
public static final String REPO_CONFIG = PREFIX + "-repo" + VndMediaType.SUFFIX;
|
||||
public static final String CONFIG = PREFIX + VndMediaType.SUFFIX;
|
||||
public static final String PACKAGES = PREFIX + "-packages" + VndMediaType.SUFFIX;
|
||||
public static final String INSTALLATIONS = PREFIX + "-installation" + VndMediaType.SUFFIX;
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
import { Repository } from "@scm-manager/ui-types";
|
||||
import { ErrorNotification, InputField, Level, Loading, SubmitButton, Notification } from "@scm-manager/ui-components";
|
||||
import React, { FC, FormEvent, useEffect, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { HgRepositoryConfiguration, useHgRepositoryConfiguration, useUpdateHgRepositoryConfiguration } from "./hooks";
|
||||
|
||||
type Props = {
|
||||
repository: Repository;
|
||||
};
|
||||
|
||||
const HgRepositoryConfigurationForm: FC<Props> = ({ repository }) => {
|
||||
const [t] = useTranslation("plugins");
|
||||
const { isLoading, error, data } = useHgRepositoryConfiguration(repository);
|
||||
const { isLoading: isUpdating, error: updateError, update, updated } = useUpdateHgRepositoryConfiguration();
|
||||
const [configuration, setConfiguration] = useState<HgRepositoryConfiguration | null>(null);
|
||||
useEffect(() => {
|
||||
setConfiguration(data);
|
||||
}, [data]);
|
||||
|
||||
if (error) {
|
||||
return <ErrorNotification error={error} />;
|
||||
}
|
||||
|
||||
if (isLoading || !configuration) {
|
||||
return <Loading />;
|
||||
}
|
||||
|
||||
const encodingChanged = (value: string) => {
|
||||
const encoding = value ? value : undefined;
|
||||
setConfiguration({
|
||||
...configuration,
|
||||
encoding
|
||||
});
|
||||
};
|
||||
|
||||
const submit = (e: FormEvent<HTMLFormElement>) => {
|
||||
e.preventDefault();
|
||||
update(configuration);
|
||||
};
|
||||
|
||||
const readOnly = !configuration._links.update;
|
||||
|
||||
return (
|
||||
<form onSubmit={submit}>
|
||||
<ErrorNotification error={updateError} />
|
||||
{updated ? <Notification type="info">{t("scm-hg-plugin.config.success")}</Notification> : null}
|
||||
<InputField
|
||||
name="encoding"
|
||||
label={t("scm-hg-plugin.config.encoding")}
|
||||
helpText={t("scm-hg-plugin.config.encodingHelpText")}
|
||||
value={configuration.encoding || ""}
|
||||
onChange={encodingChanged}
|
||||
disabled={readOnly}
|
||||
/>
|
||||
{!readOnly ? (
|
||||
<Level right={<SubmitButton loading={isUpdating} label={t("scm-hg-plugin.config.submit")} />} />
|
||||
) : null}
|
||||
</form>
|
||||
);
|
||||
};
|
||||
|
||||
export default HgRepositoryConfigurationForm;
|
||||
86
scm-plugins/scm-hg-plugin/src/main/js/hooks.ts
Normal file
86
scm-plugins/scm-hg-plugin/src/main/js/hooks.ts
Normal file
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import { apiClient } from "@scm-manager/ui-components";
|
||||
import { HalRepresentation, Link, Repository } from "@scm-manager/ui-types";
|
||||
|
||||
export type HgRepositoryConfiguration = HalRepresentation & {
|
||||
encoding?: string;
|
||||
};
|
||||
|
||||
export const useHgRepositoryConfiguration = (repository: Repository) => {
|
||||
const [isLoading, setLoading] = useState(false);
|
||||
const [data, setData] = useState<HgRepositoryConfiguration | null>(null);
|
||||
const [error, setError] = useState<Error | null>(null);
|
||||
const link = (repository._links.configuration as Link)?.href;
|
||||
useEffect(() => {
|
||||
setError(null);
|
||||
if (link) {
|
||||
setLoading(true);
|
||||
apiClient
|
||||
.get(link)
|
||||
.then(response => response.json())
|
||||
.then((config: HgRepositoryConfiguration) => {
|
||||
setData(config);
|
||||
})
|
||||
.catch(e => setError(e))
|
||||
.finally(() => setLoading(false));
|
||||
}
|
||||
}, [link]);
|
||||
|
||||
return {
|
||||
isLoading,
|
||||
error,
|
||||
data
|
||||
};
|
||||
};
|
||||
|
||||
export const useUpdateHgRepositoryConfiguration = () => {
|
||||
const [isLoading, setLoading] = useState(false);
|
||||
const [error, setError] = useState<Error | null>(null);
|
||||
const [updated, setUpdated] = useState(false);
|
||||
|
||||
const update = (configuration: HgRepositoryConfiguration) => {
|
||||
if (!configuration._links.update) {
|
||||
throw new Error("no update link on configuration");
|
||||
}
|
||||
const link = (configuration._links.update as Link).href;
|
||||
setLoading(true);
|
||||
setUpdated(false);
|
||||
setError(null);
|
||||
apiClient
|
||||
.put(link, configuration, "application/vnd.scmm-hgConfig-repo+json;v=2")
|
||||
.then(() => setUpdated(true))
|
||||
.catch(e => setError(e))
|
||||
.finally(() => setLoading(false));
|
||||
};
|
||||
|
||||
return {
|
||||
isLoading,
|
||||
error,
|
||||
update,
|
||||
updated
|
||||
};
|
||||
};
|
||||
@@ -29,6 +29,7 @@ import { ConfigurationBinder as cfgBinder } from "@scm-manager/ui-components";
|
||||
import HgGlobalConfiguration from "./HgGlobalConfiguration";
|
||||
import HgBranchInformation from "./HgBranchInformation";
|
||||
import HgTagInformation from "./HgTagInformation";
|
||||
import HgRepositoryConfigurationForm from "./HgRepositoryConfigurationForm";
|
||||
|
||||
const hgPredicate = (props: any) => {
|
||||
return props.repository && props.repository.type === "hg";
|
||||
@@ -39,6 +40,10 @@ binder.bind("repos.branch-details.information", HgBranchInformation, hgPredicate
|
||||
binder.bind("repos.tag-details.information", HgTagInformation, hgPredicate);
|
||||
binder.bind("repos.repository-avatar", HgAvatar, hgPredicate);
|
||||
|
||||
// bind repository specific configuration
|
||||
|
||||
binder.bind("repo-config.route", HgRepositoryConfigurationForm, hgPredicate);
|
||||
|
||||
// bind global configuration
|
||||
|
||||
cfgBinder.bindGlobal("/hg", "scm-hg-plugin.config.link", "hgConfig", HgGlobalConfiguration);
|
||||
|
||||
@@ -21,7 +21,9 @@
|
||||
"enableHttpPostArgsHelpText": "Aktiviert das experimentelle HttpPostArgs Protokoll von Mercurial. Das HttpPostArgs Protokoll verwendet den Post Request Body anstatt des HTTP Headers um Meta Informationen zu versenden. Dieses Vorgehen reduziert die Header Größe der Mercurial Requests. HttpPostArgs wird seit Mercurial 3.8 unterstützt.",
|
||||
"disabled": "Deaktiviert",
|
||||
"disabledHelpText": "Aktiviert oder deaktiviert das Mercurial Plugin.",
|
||||
"required": "Dieser Konfigurationswert wird benötigt"
|
||||
"required": "Dieser Konfigurationswert wird benötigt",
|
||||
"submit": "Speichern",
|
||||
"success": "Einstellungen wurden erfolgreich geändert"
|
||||
}
|
||||
},
|
||||
"permissions" : {
|
||||
|
||||
@@ -21,7 +21,9 @@
|
||||
"enableHttpPostArgsHelpText": "Enables the experimental HttpPostArgs Protocol of mercurial. The HttpPostArgs Protocol uses the body of post requests to send the meta information instead of http headers. This helps to reduce the header size of mercurial requests. HttpPostArgs is supported since mercurial 3.8.",
|
||||
"disabled": "Disabled",
|
||||
"disabledHelpText": "Enable or disable the Mercurial plugin.",
|
||||
"required": "This configuration value is required"
|
||||
"required": "This configuration value is required",
|
||||
"submit": "Submit",
|
||||
"success": "Configuration changed successfully"
|
||||
}
|
||||
},
|
||||
"permissions" : {
|
||||
|
||||
@@ -34,11 +34,12 @@ import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
import org.mockito.Answers;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import sonia.scm.repository.HgConfig;
|
||||
import sonia.scm.repository.HgGlobalConfig;
|
||||
import sonia.scm.repository.HgRepositoryHandler;
|
||||
import sonia.scm.web.HgVndMediaType;
|
||||
import sonia.scm.web.RestDispatcher;
|
||||
@@ -65,33 +66,41 @@ public class HgConfigResourceTest {
|
||||
@Rule
|
||||
public ShiroRule shiro = new ShiroRule();
|
||||
|
||||
private RestDispatcher dispatcher = new RestDispatcher();
|
||||
|
||||
private final URI baseUri = URI.create("/");
|
||||
private final RestDispatcher dispatcher = new RestDispatcher();
|
||||
|
||||
@InjectMocks
|
||||
private HgConfigDtoToHgConfigMapperImpl dtoToConfigMapper;
|
||||
|
||||
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
|
||||
private ScmPathInfoStore scmPathInfoStore;
|
||||
|
||||
@InjectMocks
|
||||
private HgConfigToHgConfigDtoMapperImpl configToDtoMapper;
|
||||
private HgGlobalConfigDtoToHgConfigMapperImpl dtoToConfigMapper;
|
||||
|
||||
@Mock
|
||||
private HgRepositoryHandler repositoryHandler;
|
||||
|
||||
@Mock
|
||||
private Provider<HgConfigAutoConfigurationResource> autoconfigResource;
|
||||
private Provider<HgGlobalConfigAutoConfigurationResource> autoconfigResource;
|
||||
|
||||
@Mock
|
||||
private Provider<HgRepositoryConfigResource> repositoryConfigResource;
|
||||
|
||||
@Before
|
||||
public void prepareEnvironment() {
|
||||
HgConfig gitConfig = createConfiguration();
|
||||
HgGlobalConfig gitConfig = createConfiguration();
|
||||
when(repositoryHandler.getConfig()).thenReturn(gitConfig);
|
||||
HgConfigResource gitConfigResource =
|
||||
new HgConfigResource(dtoToConfigMapper, configToDtoMapper, repositoryHandler, autoconfigResource);
|
||||
|
||||
HgConfigResource gitConfigResource = new HgConfigResource(
|
||||
dtoToConfigMapper, createConfigToDtoMapper(), repositoryHandler,
|
||||
autoconfigResource, repositoryConfigResource
|
||||
);
|
||||
dispatcher.addSingletonResource(gitConfigResource);
|
||||
when(scmPathInfoStore.get().getApiRestUri()).thenReturn(baseUri);
|
||||
}
|
||||
|
||||
private HgGlobalConfigToHgGlobalConfigDtoMapper createConfigToDtoMapper() {
|
||||
ScmPathInfoStore store = new ScmPathInfoStore();
|
||||
store.set(() -> URI.create("/"));
|
||||
HgConfigLinks links = new HgConfigLinks(store);
|
||||
HgGlobalConfigToHgGlobalConfigDtoMapper mapper = Mappers.getMapper(
|
||||
HgGlobalConfigToHgGlobalConfigDtoMapper.class
|
||||
);
|
||||
mapper.setLinks(links);
|
||||
return mapper;
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -172,8 +181,8 @@ public class HgConfigResourceTest {
|
||||
return response;
|
||||
}
|
||||
|
||||
private HgConfig createConfiguration() {
|
||||
HgConfig config = new HgConfig();
|
||||
private HgGlobalConfig createConfiguration() {
|
||||
HgGlobalConfig config = new HgGlobalConfig();
|
||||
config.setDisabled(false);
|
||||
return config;
|
||||
}
|
||||
|
||||
@@ -1,102 +0,0 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package sonia.scm.api.v2.resources;
|
||||
|
||||
import org.apache.shiro.subject.Subject;
|
||||
import org.apache.shiro.subject.support.SubjectThreadState;
|
||||
import org.apache.shiro.util.ThreadContext;
|
||||
import org.apache.shiro.util.ThreadState;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Answers;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import sonia.scm.repository.HgConfig;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static sonia.scm.api.v2.resources.HgConfigTests.assertEqualsConfiguration;
|
||||
import static sonia.scm.api.v2.resources.HgConfigTests.createConfiguration;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class HgConfigToHgConfigDtoMapperTest {
|
||||
|
||||
private URI baseUri = URI.create("http://example.com/base/");
|
||||
|
||||
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
|
||||
private ScmPathInfoStore scmPathInfoStore;
|
||||
|
||||
@InjectMocks
|
||||
private HgConfigToHgConfigDtoMapperImpl mapper;
|
||||
|
||||
private final Subject subject = mock(Subject.class);
|
||||
private final ThreadState subjectThreadState = new SubjectThreadState(subject);
|
||||
|
||||
private URI expectedBaseUri;
|
||||
|
||||
@Before
|
||||
public void init() {
|
||||
when(scmPathInfoStore.get().getApiRestUri()).thenReturn(baseUri);
|
||||
expectedBaseUri = baseUri.resolve(HgConfigResource.HG_CONFIG_PATH_V2);
|
||||
subjectThreadState.bind();
|
||||
ThreadContext.bind(subject);
|
||||
}
|
||||
|
||||
@After
|
||||
public void unbindSubject() {
|
||||
ThreadContext.unbindSubject();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldMapFields() {
|
||||
HgConfig config = createConfiguration();
|
||||
|
||||
when(subject.isPermitted("configuration:write:hg")).thenReturn(true);
|
||||
HgConfigDto dto = mapper.map(config);
|
||||
|
||||
assertEqualsConfiguration(dto);
|
||||
|
||||
assertEquals(expectedBaseUri.toString(), dto.getLinks().getLinkBy("self").get().getHref());
|
||||
assertEquals(expectedBaseUri.toString(), dto.getLinks().getLinkBy("update").get().getHref());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldMapFieldsWithoutUpdate() {
|
||||
HgConfig config = createConfiguration();
|
||||
|
||||
when(subject.isPermitted("configuration:write:hg")).thenReturn(false);
|
||||
HgConfigDto dto = mapper.map(config);
|
||||
|
||||
assertEquals(expectedBaseUri.toString(), dto.getLinks().getLinkBy("self").get().getHref());
|
||||
assertFalse(dto.getLinks().hasLink("update"));
|
||||
}
|
||||
}
|
||||
@@ -36,7 +36,7 @@ import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import sonia.scm.repository.HgConfig;
|
||||
import sonia.scm.repository.HgGlobalConfig;
|
||||
import sonia.scm.repository.HgRepositoryHandler;
|
||||
import sonia.scm.web.HgVndMediaType;
|
||||
import sonia.scm.web.RestDispatcher;
|
||||
@@ -56,31 +56,34 @@ import static org.mockito.Mockito.when;
|
||||
password = "secret"
|
||||
)
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class HgConfigAutoConfigurationResourceTest {
|
||||
public class HgGlobalConfigAutoConfigurationResourceTest {
|
||||
|
||||
@Rule
|
||||
public ShiroRule shiro = new ShiroRule();
|
||||
|
||||
private RestDispatcher dispatcher = new RestDispatcher();
|
||||
private final RestDispatcher dispatcher = new RestDispatcher();
|
||||
|
||||
@InjectMocks
|
||||
private HgConfigDtoToHgConfigMapperImpl dtoToConfigMapper;
|
||||
private HgGlobalConfigDtoToHgConfigMapperImpl dtoToConfigMapper;
|
||||
|
||||
@Mock
|
||||
private HgRepositoryHandler repositoryHandler;
|
||||
|
||||
@Mock
|
||||
private Provider<HgConfigAutoConfigurationResource> resourceProvider;
|
||||
private Provider<HgGlobalConfigAutoConfigurationResource> resourceProvider;
|
||||
|
||||
@Mock
|
||||
private Provider<HgRepositoryConfigResource> repositoryConfigResource;
|
||||
|
||||
@Before
|
||||
public void prepareEnvironment() {
|
||||
HgConfigAutoConfigurationResource resource =
|
||||
new HgConfigAutoConfigurationResource(dtoToConfigMapper, repositoryHandler);
|
||||
HgGlobalConfigAutoConfigurationResource resource = new HgGlobalConfigAutoConfigurationResource(dtoToConfigMapper, repositoryHandler);
|
||||
|
||||
when(resourceProvider.get()).thenReturn(resource);
|
||||
dispatcher.addSingletonResource(
|
||||
new HgConfigResource(null, null, null,
|
||||
resourceProvider));
|
||||
dispatcher.addSingletonResource(new HgConfigResource(
|
||||
null, null, null,
|
||||
resourceProvider, repositoryConfigResource
|
||||
));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -90,7 +93,7 @@ public class HgConfigAutoConfigurationResourceTest {
|
||||
|
||||
assertEquals(HttpServletResponse.SC_NO_CONTENT, response.getStatus());
|
||||
|
||||
HgConfig actualConfig = captureConfig();
|
||||
HgGlobalConfig actualConfig = captureConfig();
|
||||
assertFalse(actualConfig.isDisabled());
|
||||
}
|
||||
|
||||
@@ -110,7 +113,7 @@ public class HgConfigAutoConfigurationResourceTest {
|
||||
|
||||
assertEquals(HttpServletResponse.SC_NO_CONTENT, response.getStatus());
|
||||
|
||||
HgConfig actualConfig = captureConfig();
|
||||
HgGlobalConfig actualConfig = captureConfig();
|
||||
assertTrue(actualConfig.isDisabled());
|
||||
}
|
||||
|
||||
@@ -137,8 +140,8 @@ public class HgConfigAutoConfigurationResourceTest {
|
||||
return response;
|
||||
}
|
||||
|
||||
private HgConfig captureConfig() {
|
||||
ArgumentCaptor<HgConfig> configCaptor = ArgumentCaptor.forClass(HgConfig.class);
|
||||
private HgGlobalConfig captureConfig() {
|
||||
ArgumentCaptor<HgGlobalConfig> configCaptor = ArgumentCaptor.forClass(HgGlobalConfig.class);
|
||||
verify(repositoryHandler).doAutoConfiguration(configCaptor.capture());
|
||||
return configCaptor.getValue();
|
||||
}
|
||||
@@ -28,21 +28,21 @@ import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import sonia.scm.repository.HgConfig;
|
||||
import sonia.scm.repository.HgGlobalConfig;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class HgConfigDtoToHgConfigMapperTest {
|
||||
public class HgGlobalConfigDtoToHgGlobalConfigMapperTest {
|
||||
|
||||
@InjectMocks
|
||||
private HgConfigDtoToHgConfigMapperImpl mapper;
|
||||
private HgGlobalConfigDtoToHgConfigMapperImpl mapper;
|
||||
|
||||
@Test
|
||||
public void shouldMapFields() {
|
||||
HgConfigDto dto = createDefaultDto();
|
||||
HgConfig config = mapper.map(dto);
|
||||
HgGlobalGlobalConfigDto dto = createDefaultDto();
|
||||
HgGlobalConfig config = mapper.map(dto);
|
||||
|
||||
assertTrue(config.isDisabled());
|
||||
|
||||
@@ -52,8 +52,8 @@ public class HgConfigDtoToHgConfigMapperTest {
|
||||
assertTrue(config.isEnableHttpPostArgs());
|
||||
}
|
||||
|
||||
private HgConfigDto createDefaultDto() {
|
||||
HgConfigDto configDto = new HgConfigDto();
|
||||
private HgGlobalGlobalConfigDto createDefaultDto() {
|
||||
HgGlobalGlobalConfigDto configDto = new HgGlobalGlobalConfigDto();
|
||||
configDto.setDisabled(true);
|
||||
configDto.setEncoding("ABC");
|
||||
configDto.setHgBinary("/etc/hg");
|
||||
@@ -21,7 +21,7 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
package sonia.scm.api.v2.resources;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
@@ -42,20 +42,20 @@ import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
@SubjectAware(configuration = "classpath:sonia/scm/configuration/shiro.ini")
|
||||
public class HgConfigInIndexResourceTest {
|
||||
public class HgGlobalConfigInIndexResourceTest {
|
||||
|
||||
@Rule
|
||||
public final ShiroRule shiroRule = new ShiroRule();
|
||||
|
||||
private final ObjectMapper objectMapper = new ObjectMapper();
|
||||
private final ObjectNode root = objectMapper.createObjectNode();
|
||||
private final HgConfigInIndexResource hgConfigInIndexResource;
|
||||
private final HgGlobalConfigInIndexResource hgGlobalConfigInIndexResource;
|
||||
|
||||
public HgConfigInIndexResourceTest() {
|
||||
public HgGlobalConfigInIndexResourceTest() {
|
||||
root.put("_links", objectMapper.createObjectNode());
|
||||
ScmPathInfoStore pathInfoStore = new ScmPathInfoStore();
|
||||
pathInfoStore.set(() -> URI.create("/"));
|
||||
hgConfigInIndexResource = new HgConfigInIndexResource(Providers.of(pathInfoStore), objectMapper);
|
||||
hgGlobalConfigInIndexResource = new HgGlobalConfigInIndexResource(Providers.of(pathInfoStore), objectMapper);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -63,7 +63,7 @@ public class HgConfigInIndexResourceTest {
|
||||
public void admin() {
|
||||
JsonEnricherContext context = new JsonEnricherContext(URI.create("/index"), MediaType.valueOf(VndMediaType.INDEX), root);
|
||||
|
||||
hgConfigInIndexResource.enrich(context);
|
||||
hgGlobalConfigInIndexResource.enrich(context);
|
||||
|
||||
assertEquals("/v2/config/hg", root.get("_links").get("hgConfig").get("href").asText());
|
||||
}
|
||||
@@ -73,7 +73,7 @@ public class HgConfigInIndexResourceTest {
|
||||
public void user() {
|
||||
JsonEnricherContext context = new JsonEnricherContext(URI.create("/index"), MediaType.valueOf(VndMediaType.INDEX), root);
|
||||
|
||||
hgConfigInIndexResource.enrich(context);
|
||||
hgGlobalConfigInIndexResource.enrich(context);
|
||||
|
||||
assertTrue(root.get("_links").iterator().hasNext());
|
||||
}
|
||||
@@ -82,7 +82,7 @@ public class HgConfigInIndexResourceTest {
|
||||
public void anonymous() {
|
||||
JsonEnricherContext context = new JsonEnricherContext(URI.create("/index"), MediaType.valueOf(VndMediaType.INDEX), root);
|
||||
|
||||
hgConfigInIndexResource.enrich(context);
|
||||
hgGlobalConfigInIndexResource.enrich(context);
|
||||
|
||||
assertFalse(root.get("_links").iterator().hasNext());
|
||||
}
|
||||
@@ -24,18 +24,18 @@
|
||||
|
||||
package sonia.scm.api.v2.resources;
|
||||
|
||||
import sonia.scm.repository.HgConfig;
|
||||
import sonia.scm.repository.HgGlobalConfig;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
class HgConfigTests {
|
||||
class HgGlobalConfigTestUtil {
|
||||
|
||||
private HgConfigTests() {
|
||||
private HgGlobalConfigTestUtil() {
|
||||
}
|
||||
|
||||
static HgConfig createConfiguration() {
|
||||
HgConfig config = new HgConfig();
|
||||
static HgGlobalConfig createConfiguration() {
|
||||
HgGlobalConfig config = new HgGlobalConfig();
|
||||
config.setDisabled(true);
|
||||
|
||||
config.setEncoding("ABC");
|
||||
@@ -45,7 +45,7 @@ class HgConfigTests {
|
||||
return config;
|
||||
}
|
||||
|
||||
static void assertEqualsConfiguration(HgConfigDto dto) {
|
||||
static void assertEqualsConfiguration(HgGlobalGlobalConfigDto dto) {
|
||||
assertTrue(dto.isDisabled());
|
||||
|
||||
assertEquals("ABC", dto.getEncoding());
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package sonia.scm.api.v2.resources;
|
||||
|
||||
import org.apache.shiro.subject.Subject;
|
||||
import org.apache.shiro.util.ThreadContext;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import sonia.scm.repository.HgGlobalConfig;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static sonia.scm.api.v2.resources.HgGlobalConfigTestUtil.assertEqualsConfiguration;
|
||||
import static sonia.scm.api.v2.resources.HgGlobalConfigTestUtil.createConfiguration;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class HgGlobalConfigToHgGlobalConfigDtoMapperTest {
|
||||
|
||||
private final URI baseUri = URI.create("http://example.com/base/");
|
||||
private final URI expectedBaseUri = baseUri.resolve(HgConfigResource.HG_CONFIG_PATH_V2);
|
||||
|
||||
@Mock
|
||||
private Subject subject;
|
||||
|
||||
private HgGlobalConfigToHgGlobalConfigDtoMapper mapper;
|
||||
|
||||
@BeforeEach
|
||||
void init() {
|
||||
ThreadContext.bind(subject);
|
||||
|
||||
ScmPathInfoStore store = new ScmPathInfoStore();
|
||||
store.set(() -> baseUri);
|
||||
|
||||
mapper = Mappers.getMapper(HgGlobalConfigToHgGlobalConfigDtoMapper.class);
|
||||
mapper.setLinks(new HgConfigLinks(store));
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void unbindSubject() {
|
||||
ThreadContext.unbindSubject();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldMapFields() {
|
||||
HgGlobalConfig config = createConfiguration();
|
||||
|
||||
when(subject.isPermitted("configuration:write:hg")).thenReturn(true);
|
||||
HgGlobalGlobalConfigDto dto = mapper.map(config);
|
||||
|
||||
assertEqualsConfiguration(dto);
|
||||
|
||||
assertThat(dto.getLinks().getLinkBy("self")).hasValueSatisfying(
|
||||
link -> assertThat(link.getHref()).isEqualTo(expectedBaseUri.toString())
|
||||
);
|
||||
assertThat(dto.getLinks().getLinkBy("update")).hasValueSatisfying(
|
||||
link -> assertThat(link.getHref()).isEqualTo(expectedBaseUri.toString())
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldMapFieldsWithoutUpdate() {
|
||||
HgGlobalConfig config = createConfiguration();
|
||||
|
||||
when(subject.isPermitted("configuration:write:hg")).thenReturn(false);
|
||||
HgGlobalGlobalConfigDto dto = mapper.map(config);
|
||||
|
||||
assertThat(dto.getLinks().getLinkBy("self")).hasValueSatisfying(
|
||||
link -> assertThat(link.getHref()).isEqualTo(expectedBaseUri.toString())
|
||||
);
|
||||
assertThat(dto.getLinks().hasLink("update")).isFalse();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package sonia.scm.api.v2.resources;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import sonia.scm.repository.Repository;
|
||||
import sonia.scm.repository.RepositoryTestData;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class HgRepositoryConfigEnricherTest {
|
||||
|
||||
private HgRepositoryConfigEnricher enricher;
|
||||
|
||||
@Mock
|
||||
private HalEnricherContext context;
|
||||
|
||||
@Mock
|
||||
private HalAppender appender;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
ScmPathInfoStore store = new ScmPathInfoStore();
|
||||
store.set(() -> URI.create("/"));
|
||||
HgConfigLinks links = new HgConfigLinks(store);
|
||||
enricher = new HgRepositoryConfigEnricher(links);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldEnrichHgRepository() {
|
||||
addRepositoryToContext("hg");
|
||||
enricher.enrich(context, appender);
|
||||
verify(appender).appendLink("configuration", "/v2/config/hg/hitchhiker/HeartOfGold");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldNotEnrichNonHgRepository() {
|
||||
addRepositoryToContext("git");
|
||||
enricher.enrich(context, appender);
|
||||
verify(appender, never()).appendLink(anyString(), anyString());
|
||||
}
|
||||
|
||||
private void addRepositoryToContext(String type) {
|
||||
Repository repository = RepositoryTestData.createHeartOfGold(type);
|
||||
when(context.oneRequireByType(Repository.class)).thenReturn(repository);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package sonia.scm.api.v2.resources;
|
||||
|
||||
|
||||
import org.apache.shiro.subject.Subject;
|
||||
import org.apache.shiro.util.ThreadContext;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Answers;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import sonia.scm.repository.HgRepositoryConfig;
|
||||
import sonia.scm.repository.Repository;
|
||||
import sonia.scm.repository.RepositoryTestData;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class HgRepositoryConfigMapperTest {
|
||||
|
||||
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
|
||||
private HgConfigLinks links;
|
||||
|
||||
@InjectMocks
|
||||
private HgRepositoryConfigMapperImpl mapper;
|
||||
|
||||
@Mock
|
||||
private Subject subject;
|
||||
|
||||
@BeforeEach
|
||||
void setUpSubject() {
|
||||
ThreadContext.bind(subject);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void tearDownSubject() {
|
||||
ThreadContext.unbindSubject();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldMapToDto() {
|
||||
Repository repository = RepositoryTestData.createHeartOfGold("hg");
|
||||
when(links.repository(repository).get()).thenReturn("/hg/config");
|
||||
|
||||
HgRepositoryConfig config = new HgRepositoryConfig();
|
||||
config.setEncoding("UTF-8");
|
||||
|
||||
HgRepositoryConfigDto dto = mapper.map(repository, config);
|
||||
assertThat(dto.getEncoding()).isEqualTo("UTF-8");
|
||||
assertThat(dto.getLinks().getLinkBy("self")).hasValueSatisfying(
|
||||
link -> assertThat(link.getHref()).isEqualTo("/hg/config")
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldAppendUpdateLink() {
|
||||
Repository repository = RepositoryTestData.createHeartOfGold("hg");
|
||||
when(links.repository(repository).get()).thenReturn("/hg/config");
|
||||
when(links.repository(repository).update()).thenReturn("/hg/config/update");
|
||||
when(subject.isPermitted("repository:hg:" + repository.getId())).thenReturn(true);
|
||||
|
||||
HgRepositoryConfigDto dto = mapper.map(repository, new HgRepositoryConfig());
|
||||
assertThat(dto.getLinks().getLinkBy("update")).hasValueSatisfying(
|
||||
link -> assertThat(link.getHref()).isEqualTo("/hg/config/update")
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package sonia.scm.api.v2.resources;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.google.inject.util.Providers;
|
||||
import de.otto.edison.hal.Links;
|
||||
import org.apache.shiro.subject.Subject;
|
||||
import org.apache.shiro.util.ThreadContext;
|
||||
import org.jboss.resteasy.mock.MockHttpRequest;
|
||||
import org.jboss.resteasy.mock.MockHttpResponse;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import sonia.scm.repository.HgRepositoryConfig;
|
||||
import sonia.scm.repository.HgRepositoryConfigStore;
|
||||
import sonia.scm.repository.HgRepositoryHandler;
|
||||
import sonia.scm.repository.NamespaceAndName;
|
||||
import sonia.scm.repository.Repository;
|
||||
import sonia.scm.repository.RepositoryManager;
|
||||
import sonia.scm.repository.RepositoryTestData;
|
||||
import sonia.scm.web.HgVndMediaType;
|
||||
import sonia.scm.web.RestDispatcher;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class HgRepositoryConfigResourceTest {
|
||||
|
||||
private final ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
private RestDispatcher dispatcher;
|
||||
|
||||
@Mock
|
||||
private RepositoryManager repositoryManager;
|
||||
|
||||
@Mock
|
||||
private HgRepositoryConfigStore store;
|
||||
|
||||
@Mock
|
||||
private Subject subject;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
ThreadContext.bind(subject);
|
||||
|
||||
HgRepositoryConfigMapper mapper = createConfigMapper();
|
||||
dispatcher = new RestDispatcher();
|
||||
dispatcher.addSingletonResource(createRootResource(
|
||||
new HgRepositoryConfigResource(repositoryManager, store, mapper)
|
||||
));
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void tearDownSubject() {
|
||||
ThreadContext.unbindSubject();
|
||||
}
|
||||
|
||||
private HgConfigResource createRootResource(HgRepositoryConfigResource resource) {
|
||||
return new HgConfigResource(
|
||||
mock(HgGlobalConfigDtoToHgConfigMapper.class),
|
||||
mock(HgGlobalConfigToHgGlobalConfigDtoMapper.class),
|
||||
mock(HgRepositoryHandler.class),
|
||||
Providers.of(mock(HgGlobalConfigAutoConfigurationResource.class)),
|
||||
Providers.of(resource)
|
||||
);
|
||||
}
|
||||
|
||||
private HgRepositoryConfigMapper createConfigMapper() {
|
||||
ScmPathInfoStore pathInfoStore = new ScmPathInfoStore();
|
||||
pathInfoStore.set(() -> URI.create("/"));
|
||||
HgConfigLinks links = new HgConfigLinks(pathInfoStore);
|
||||
HgRepositoryConfigMapper mapper = Mappers.getMapper(HgRepositoryConfigMapper.class);
|
||||
mapper.setLinks(links);
|
||||
return mapper;
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldGetConfig() throws IOException, URISyntaxException {
|
||||
HgRepositoryConfig config = new HgRepositoryConfig();
|
||||
config.setEncoding("ISO-8859-15");
|
||||
|
||||
Repository repository = RepositoryTestData.createHeartOfGold("hg");
|
||||
when(repositoryManager.get(new NamespaceAndName("hitchhiker", "hog"))).thenReturn(repository);
|
||||
when(store.of(repository)).thenReturn(config);
|
||||
|
||||
MockHttpRequest request = MockHttpRequest.get("/v2/config/hg/hitchhiker/hog");
|
||||
MockHttpResponse response = new MockHttpResponse();
|
||||
dispatcher.invoke(request, response);
|
||||
|
||||
assertThat(response.getStatus()).isEqualTo(HttpServletResponse.SC_OK);
|
||||
|
||||
JsonNode node = objectMapper.readTree(response.getContentAsString());
|
||||
assertThat(node.get("encoding").asText()).isEqualTo("ISO-8859-15");
|
||||
assertThat(node.get("_links").get("self").get("href").asText()).isEqualTo("/v2/config/hg/hitchhiker/HeartOfGold");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldUpdateConfig() throws IOException, URISyntaxException {
|
||||
Repository repository = RepositoryTestData.createHeartOfGold("hg");
|
||||
when(repositoryManager.get(new NamespaceAndName("hitchhiker", "hog"))).thenReturn(repository);
|
||||
|
||||
HgRepositoryConfigDto dto = new HgRepositoryConfigDto(Links.emptyLinks());
|
||||
dto.setEncoding("UTF-8");
|
||||
MockHttpRequest request = MockHttpRequest.put("/v2/config/hg/hitchhiker/hog").contentType(
|
||||
HgVndMediaType.REPO_CONFIG
|
||||
).content(objectMapper.writeValueAsBytes(dto));
|
||||
MockHttpResponse response = new MockHttpResponse();
|
||||
dispatcher.invoke(request, response);
|
||||
|
||||
ArgumentCaptor<HgRepositoryConfig> captor = ArgumentCaptor.forClass(HgRepositoryConfig.class);
|
||||
verify(store).store(eq(repository), captor.capture());
|
||||
|
||||
assertThat(response.getStatus()).isEqualTo(HttpServletResponse.SC_NO_CONTENT);
|
||||
assertThat(captor.getValue().getEncoding()).isEqualTo("UTF-8");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldFailWithInvalidEncoding() throws IOException, URISyntaxException {
|
||||
HgRepositoryConfigDto dto = new HgRepositoryConfigDto(Links.emptyLinks());
|
||||
dto.setEncoding("XA");
|
||||
|
||||
MockHttpRequest request = MockHttpRequest.put("/v2/config/hg/hitchhiker/hog")
|
||||
.contentType(HgVndMediaType.REPO_CONFIG).content(objectMapper.writeValueAsBytes(dto));
|
||||
MockHttpResponse response = new MockHttpResponse();
|
||||
dispatcher.invoke(request, response);
|
||||
|
||||
assertThat(response.getStatus()).isEqualTo(HttpServletResponse.SC_BAD_REQUEST);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -32,7 +32,7 @@ import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import sonia.scm.repository.HgConfig;
|
||||
import sonia.scm.repository.HgGlobalConfig;
|
||||
import sonia.scm.repository.HgVerifier;
|
||||
|
||||
import java.io.File;
|
||||
@@ -57,7 +57,7 @@ class PosixAutoConfiguratorTest {
|
||||
|
||||
PosixAutoConfigurator configurator = create(directory);
|
||||
|
||||
HgConfig config = new HgConfig();
|
||||
HgGlobalConfig config = new HgGlobalConfig();
|
||||
configurator.configure(config);
|
||||
|
||||
assertThat(config.getHgBinary()).isEqualTo(hg.toString());
|
||||
@@ -84,7 +84,7 @@ class PosixAutoConfiguratorTest {
|
||||
verifier, createEnv(def), ImmutableList.of(additional.toAbsolutePath().toString())
|
||||
);
|
||||
|
||||
HgConfig config = new HgConfig();
|
||||
HgGlobalConfig config = new HgGlobalConfig();
|
||||
configurator.configure(config);
|
||||
|
||||
assertThat(config.getHgBinary()).isEqualTo(hg.toString());
|
||||
@@ -109,7 +109,7 @@ class PosixAutoConfiguratorTest {
|
||||
)
|
||||
);
|
||||
|
||||
HgConfig config = new HgConfig();
|
||||
HgGlobalConfig config = new HgGlobalConfig();
|
||||
configurator.configure(config);
|
||||
|
||||
assertThat(config.getHgBinary()).isEqualTo(hg.toString());
|
||||
@@ -119,7 +119,7 @@ class PosixAutoConfiguratorTest {
|
||||
void shouldNotConfigureMercurial(@TempDir Path directory) {
|
||||
PosixAutoConfigurator configurator = create(directory);
|
||||
|
||||
HgConfig config = new HgConfig();
|
||||
HgGlobalConfig config = new HgGlobalConfig();
|
||||
configurator.configure(config);
|
||||
|
||||
assertThat(config.getHgBinary()).isNull();
|
||||
|
||||
@@ -31,7 +31,7 @@ import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import sonia.scm.repository.HgConfig;
|
||||
import sonia.scm.repository.HgGlobalConfig;
|
||||
import sonia.scm.repository.HgVerifier;
|
||||
|
||||
import java.io.File;
|
||||
@@ -129,7 +129,7 @@ class WindowsAutoConfiguratorTest {
|
||||
}
|
||||
|
||||
private String configure(String path) {
|
||||
HgConfig config = new HgConfig();
|
||||
HgGlobalConfig config = new HgGlobalConfig();
|
||||
configurator(path).configure(config);
|
||||
return config.getHgBinary();
|
||||
}
|
||||
|
||||
@@ -42,7 +42,6 @@ import sonia.scm.security.CipherUtil;
|
||||
import sonia.scm.security.Xsrf;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Map;
|
||||
@@ -60,7 +59,7 @@ class DefaultHgEnvironmentBuilderTest {
|
||||
private AccessTokenBuilderFactory accessTokenBuilderFactory;
|
||||
|
||||
@Mock
|
||||
private HgRepositoryHandler repositoryHandler;
|
||||
private HgConfigResolver repositoryConfigResolver;
|
||||
|
||||
@Mock
|
||||
private HookEnvironment hookEnvironment;
|
||||
@@ -71,6 +70,9 @@ class DefaultHgEnvironmentBuilderTest {
|
||||
@InjectMocks
|
||||
private DefaultHgEnvironmentBuilder builder;
|
||||
|
||||
@Mock
|
||||
private HgConfig config;
|
||||
|
||||
private Path directory;
|
||||
|
||||
@BeforeEach
|
||||
@@ -141,14 +143,12 @@ class DefaultHgEnvironmentBuilderTest {
|
||||
|
||||
@Nonnull
|
||||
private Repository prepareForRead(String id) {
|
||||
when(repositoryHandler.getDirectory(id)).thenReturn(directory.resolve("repo").toFile());
|
||||
|
||||
HgConfig config = new HgConfig();
|
||||
when(repositoryHandler.getConfig()).thenReturn(config);
|
||||
|
||||
Repository heartOfGold = RepositoryTestData.createHeartOfGold();
|
||||
heartOfGold.setId(id);
|
||||
|
||||
when(repositoryConfigResolver.resolve(heartOfGold)).thenReturn(config);
|
||||
when(config.getDirectory()).thenReturn(directory.resolve("repo").toFile());
|
||||
|
||||
return heartOfGold;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package sonia.scm.repository;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class HgConfigResolverTest {
|
||||
|
||||
@Mock
|
||||
private HgRepositoryHandler handler;
|
||||
|
||||
@Mock
|
||||
private HgRepositoryConfigStore repositoryConfigStore;
|
||||
|
||||
private HgConfigResolver resolver;
|
||||
|
||||
private Repository heartOfGold = RepositoryTestData.createHeartOfGold("hg");
|
||||
private HgGlobalConfig globalConfig;
|
||||
private HgRepositoryConfig repositoryConfig;
|
||||
|
||||
@BeforeEach
|
||||
void setUpResolver(@TempDir Path directory) {
|
||||
globalConfig = new HgGlobalConfig();
|
||||
repositoryConfig = new HgRepositoryConfig();
|
||||
|
||||
when(handler.getDirectory(heartOfGold.getId())).thenReturn(directory.toFile());
|
||||
when(handler.getConfig()).thenReturn(globalConfig);
|
||||
|
||||
when(repositoryConfigStore.of(heartOfGold)).thenReturn(repositoryConfig);
|
||||
|
||||
resolver = new HgConfigResolver(handler, repositoryConfigStore);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldReturnEncodingFromRepositoryConfig() {
|
||||
globalConfig.setEncoding("ISO-8859-1");
|
||||
repositoryConfig.setEncoding("ISO-8859-15");
|
||||
|
||||
HgConfig config = resolver.resolve(heartOfGold);
|
||||
assertThat(config.getEncoding()).isEqualTo("ISO-8859-15");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldReturnEncodingFromGlobalConfig() {
|
||||
globalConfig.setEncoding("ISO-8859-1");
|
||||
|
||||
HgConfig config = resolver.resolve(heartOfGold);
|
||||
assertThat(config.getEncoding()).isEqualTo("ISO-8859-1");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package sonia.scm.repository;
|
||||
|
||||
import org.apache.shiro.authz.AuthorizationException;
|
||||
import org.apache.shiro.subject.Subject;
|
||||
import org.apache.shiro.util.ThreadContext;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import sonia.scm.store.InMemoryConfigurationStoreFactory;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class HgRepositoryConfigStoreTest {
|
||||
|
||||
@Mock
|
||||
private Subject subject;
|
||||
|
||||
private HgRepositoryConfigStore store;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
ThreadContext.bind(subject);
|
||||
|
||||
store = new HgRepositoryConfigStore(new InMemoryConfigurationStoreFactory());
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void tearDownSubject() {
|
||||
ThreadContext.unbindSubject();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldThrowAuthorizationException() {
|
||||
Repository repository = RepositoryTestData.createHeartOfGold("hg");
|
||||
doThrow(AuthorizationException.class)
|
||||
.when(subject)
|
||||
.checkPermission("repository:hg:" + repository.getId());
|
||||
|
||||
HgRepositoryConfig config = new HgRepositoryConfig();
|
||||
assertThrows(AuthorizationException.class, () -> store.store(repository, config));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldReadAndStore() {
|
||||
Repository repository = RepositoryTestData.createHeartOfGold("hg");
|
||||
HgRepositoryConfig config = store.of(repository);
|
||||
config.setEncoding("ISO-8859-15");
|
||||
store.store(repository, config);
|
||||
|
||||
assertThat(store.of(repository).getEncoding()).isEqualTo("ISO-8859-15");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -63,7 +63,8 @@ class HgRepositoryFactoryTest {
|
||||
handler = HgTestUtil.createHandler(directory.toFile());
|
||||
assumeTrue(handler.isConfigured());
|
||||
|
||||
factory = new HgRepositoryFactory(handler, hookEnvironment, environmentBuilder);
|
||||
HgConfigResolver resolver = new HgConfigResolver(handler);
|
||||
factory = new HgRepositoryFactory(resolver, hookEnvironment, environmentBuilder);
|
||||
heartOfGold = createRepository();
|
||||
}
|
||||
|
||||
|
||||
@@ -85,9 +85,9 @@ public class HgRepositoryHandlerTest extends SimpleRepositoryHandlerTestBase {
|
||||
public void getDirectory() {
|
||||
HgRepositoryHandler repositoryHandler = createHandler(factory, locationResolver);
|
||||
|
||||
HgConfig hgConfig = new HgConfig();
|
||||
hgConfig.setHgBinary("hg");
|
||||
repositoryHandler.setConfig(hgConfig);
|
||||
HgGlobalConfig hgGlobalConfig = new HgGlobalConfig();
|
||||
hgGlobalConfig.setHgBinary("hg");
|
||||
repositoryHandler.setConfig(hgGlobalConfig);
|
||||
|
||||
initRepository();
|
||||
File path = repositoryHandler.getDirectory(repository.getId());
|
||||
|
||||
@@ -41,38 +41,32 @@ import static org.mockito.Mockito.mock;
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public final class HgTestUtil
|
||||
{
|
||||
public final class HgTestUtil {
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*/
|
||||
private HgTestUtil() {}
|
||||
private HgTestUtil() {
|
||||
}
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param handler
|
||||
*/
|
||||
public static void checkForSkip(HgRepositoryHandler handler)
|
||||
{
|
||||
public static void checkForSkip(HgRepositoryHandler handler) {
|
||||
|
||||
// skip tests if hg not in path
|
||||
if (!handler.isConfigured())
|
||||
{
|
||||
if (!handler.isConfigured()) {
|
||||
System.out.println("WARNING could not find hg, skipping test");
|
||||
Assume.assumeTrue(false);
|
||||
}
|
||||
|
||||
if (Boolean.getBoolean("sonia.scm.test.skip.hg"))
|
||||
{
|
||||
if (Boolean.getBoolean("sonia.scm.test.skip.hg")) {
|
||||
System.out.println("WARNING mercurial test are disabled");
|
||||
Assume.assumeTrue(false);
|
||||
}
|
||||
@@ -97,8 +91,9 @@ public final class HgTestUtil
|
||||
}
|
||||
|
||||
public static HgRepositoryFactory createFactory(HgRepositoryHandler handler, File directory) {
|
||||
HgConfigResolver resolver = new HgConfigResolver(handler, repository -> directory);
|
||||
return new HgRepositoryFactory(
|
||||
handler, new HookEnvironment(), new EmptyHgEnvironmentBuilder(), repository -> directory
|
||||
resolver, new HookEnvironment(), new EmptyHgEnvironmentBuilder()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,7 +107,7 @@ class HgVerifierTest {
|
||||
}
|
||||
|
||||
private boolean verify(Path hg) {
|
||||
HgConfig config = new HgConfig();
|
||||
HgGlobalConfig config = new HgGlobalConfig();
|
||||
config.setHgBinary(hg.toString());
|
||||
return verifier.isValid(config);
|
||||
}
|
||||
|
||||
@@ -29,16 +29,15 @@ package sonia.scm.repository.spi;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
|
||||
import sonia.scm.repository.HgConfigResolver;
|
||||
import sonia.scm.repository.HgRepositoryFactory;
|
||||
import sonia.scm.repository.HgRepositoryHandler;
|
||||
import sonia.scm.repository.HgTestUtil;
|
||||
import sonia.scm.repository.RepositoryTestData;
|
||||
import sonia.scm.repository.hooks.HookEnvironment;
|
||||
import sonia.scm.util.MockUtil;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
@@ -66,8 +65,10 @@ public class AbstractHgCommandTestBase extends ZippedRepositoryTestBase
|
||||
this.handler = HgTestUtil.createHandler(tempFolder.newFolder());
|
||||
HgTestUtil.checkForSkip(handler);
|
||||
|
||||
HgConfigResolver resolver = new HgConfigResolver(handler);
|
||||
|
||||
HgRepositoryFactory factory = HgTestUtil.createFactory(handler, repositoryDirectory);
|
||||
cmdContext = new HgCommandContext(handler, factory, RepositoryTestData.createHeartOfGold());
|
||||
cmdContext = new HgCommandContext(resolver, factory, RepositoryTestData.createHeartOfGold());
|
||||
}
|
||||
|
||||
//~--- set methods ----------------------------------------------------------
|
||||
|
||||
@@ -29,6 +29,7 @@ package sonia.scm.repository.spi;
|
||||
import com.aragost.javahg.Changeset;
|
||||
import org.junit.Test;
|
||||
import sonia.scm.repository.ChangesetPagingResult;
|
||||
import sonia.scm.repository.HgConfigResolver;
|
||||
import sonia.scm.repository.HgTestUtil;
|
||||
import sonia.scm.repository.InternalRepositoryException;
|
||||
|
||||
@@ -111,8 +112,9 @@ public class HgIncomingCommandTest extends IncomingOutgoingTestBase
|
||||
}
|
||||
|
||||
private HgIncomingCommand createIncomingCommand() {
|
||||
HgConfigResolver resolver = new HgConfigResolver(handler);
|
||||
return new HgIncomingCommand(
|
||||
new HgCommandContext(handler, HgTestUtil.createFactory(handler, incomingDirectory), incomingRepository),
|
||||
new HgCommandContext(resolver, HgTestUtil.createFactory(handler, incomingDirectory), incomingRepository),
|
||||
handler
|
||||
);
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ import com.aragost.javahg.commands.RemoveCommand;
|
||||
import com.aragost.javahg.commands.RenameCommand;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import sonia.scm.repository.HgConfigResolver;
|
||||
import sonia.scm.repository.HgTestUtil;
|
||||
import sonia.scm.repository.Modifications;
|
||||
|
||||
@@ -44,7 +45,8 @@ public class HgModificationsCommandTest extends IncomingOutgoingTestBase {
|
||||
|
||||
@Before
|
||||
public void init() {
|
||||
HgCommandContext outgoingContext = new HgCommandContext(handler, HgTestUtil.createFactory(handler, outgoingDirectory), outgoingRepository);
|
||||
HgConfigResolver configResolver = new HgConfigResolver(handler);
|
||||
HgCommandContext outgoingContext = new HgCommandContext(configResolver, HgTestUtil.createFactory(handler, outgoingDirectory), outgoingRepository);
|
||||
outgoingModificationsCommand = new HgModificationsCommand(outgoingContext);
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ package sonia.scm.repository.spi;
|
||||
import com.aragost.javahg.Changeset;
|
||||
import org.junit.Test;
|
||||
import sonia.scm.repository.ChangesetPagingResult;
|
||||
import sonia.scm.repository.HgConfigResolver;
|
||||
import sonia.scm.repository.HgTestUtil;
|
||||
import sonia.scm.repository.InternalRepositoryException;
|
||||
|
||||
@@ -107,8 +108,9 @@ public class HgOutgoingCommandTest extends IncomingOutgoingTestBase
|
||||
}
|
||||
|
||||
private HgOutgoingCommand createOutgoingCommand() {
|
||||
HgConfigResolver resolver = new HgConfigResolver(handler);
|
||||
return new HgOutgoingCommand(
|
||||
new HgCommandContext(handler, HgTestUtil.createFactory(handler, outgoingDirectory), outgoingRepository),
|
||||
new HgCommandContext(resolver, HgTestUtil.createFactory(handler, outgoingDirectory), outgoingRepository),
|
||||
handler
|
||||
);
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import sonia.scm.repository.HgConfig;
|
||||
import sonia.scm.repository.HgGlobalConfig;
|
||||
import sonia.scm.repository.HgRepositoryHandler;
|
||||
import sonia.scm.repository.HgTestUtil;
|
||||
|
||||
@@ -54,7 +54,7 @@ class HgVersionCommandTest {
|
||||
|
||||
@Test
|
||||
void shouldReturnUnknownForIOException() {
|
||||
HgVersionCommand command = new HgVersionCommand(new HgConfig(), "/i/dont/know", cmd -> {
|
||||
HgVersionCommand command = new HgVersionCommand(new HgGlobalConfig(), "/i/dont/know", cmd -> {
|
||||
throw new IOException("failed");
|
||||
});
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
import sonia.scm.AbstractTestBase;
|
||||
import sonia.scm.repository.HgConfig;
|
||||
import sonia.scm.repository.HgGlobalConfig;
|
||||
import sonia.scm.repository.HgRepositoryHandler;
|
||||
import sonia.scm.repository.HgTestUtil;
|
||||
import sonia.scm.user.User;
|
||||
@@ -182,7 +182,7 @@ public abstract class IncomingOutgoingTestBase extends AbstractTestBase
|
||||
*/
|
||||
private RepositoryConfiguration createConfig(HgRepositoryHandler handler)
|
||||
{
|
||||
HgConfig cfg = handler.getConfig();
|
||||
HgGlobalConfig cfg = handler.getConfig();
|
||||
RepositoryConfiguration configuration = RepositoryConfiguration.DEFAULT;
|
||||
|
||||
configuration.setHgBin(cfg.getHgBinary());
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
package sonia.scm.web;
|
||||
|
||||
import org.junit.Before;
|
||||
@@ -32,7 +32,7 @@ import org.mockito.Mock;
|
||||
import static org.mockito.Mockito.*;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import sonia.scm.config.ScmConfiguration;
|
||||
import sonia.scm.repository.HgConfig;
|
||||
import sonia.scm.repository.HgGlobalConfig;
|
||||
import sonia.scm.repository.HgRepositoryHandler;
|
||||
import sonia.scm.repository.RepositoryProvider;
|
||||
|
||||
@@ -72,7 +72,7 @@ public class HgPermissionFilterTest {
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
when(hgRepositoryHandler.getConfig()).thenReturn(new HgConfig());
|
||||
when(hgRepositoryHandler.getConfig()).thenReturn(new HgGlobalConfig());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -82,9 +82,9 @@ public class HgPermissionFilterTest {
|
||||
public void testWrapRequestIfRequired() {
|
||||
assertSame(request, filter.wrapRequestIfRequired(request));
|
||||
|
||||
HgConfig hgConfig = new HgConfig();
|
||||
hgConfig.setEnableHttpPostArgs(true);
|
||||
when(hgRepositoryHandler.getConfig()).thenReturn(hgConfig);
|
||||
HgGlobalConfig hgGlobalConfig = new HgGlobalConfig();
|
||||
hgGlobalConfig.setEnableHttpPostArgs(true);
|
||||
when(hgRepositoryHandler.getConfig()).thenReturn(hgGlobalConfig);
|
||||
|
||||
assertThat(filter.wrapRequestIfRequired(request), is(instanceOf(HgServletRequest.class)));
|
||||
}
|
||||
@@ -112,7 +112,7 @@ public class HgPermissionFilterTest {
|
||||
*/
|
||||
@Test
|
||||
public void testIsWriteRequestWithEnabledHttpPostArgs() {
|
||||
HgConfig config = new HgConfig();
|
||||
HgGlobalConfig config = new HgGlobalConfig();
|
||||
config.setEnableHttpPostArgs(true);
|
||||
when(hgRepositoryHandler.getConfig()).thenReturn(config);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user