merge with branch 1.x

This commit is contained in:
Sebastian Sdorra
2017-01-12 19:50:39 +01:00
250 changed files with 16399 additions and 1573 deletions

View File

@@ -43,7 +43,7 @@ import sonia.scm.installer.HgInstallerFactory;
import sonia.scm.installer.HgPackage;
import sonia.scm.installer.HgPackageReader;
import sonia.scm.installer.HgPackages;
import sonia.scm.net.HttpClient;
import sonia.scm.net.ahc.AdvancedHttpClient;
import sonia.scm.repository.HgConfig;
import sonia.scm.repository.HgRepositoryHandler;
@@ -89,8 +89,8 @@ public class HgConfigResource
* @param pkgReader
*/
@Inject
public HgConfigResource(HttpClient client, HgRepositoryHandler handler,
HgPackageReader pkgReader)
public HgConfigResource(AdvancedHttpClient client,
HgRepositoryHandler handler, HgPackageReader pkgReader)
{
this.client = client;
this.handler = handler;
@@ -158,7 +158,7 @@ public class HgConfigResource
if (pkg != null)
{
if (HgInstallerFactory.createInstaller().installPackage(client, handler,
SCMContext.getContext().getBaseDirectory(), pkg))
SCMContext.getContext().getBaseDirectory(), pkg))
{
response = Response.noContent().build();
}
@@ -262,7 +262,7 @@ public class HgConfigResource
@POST
@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
public Response setConfig(@Context UriInfo uriInfo, HgConfig config)
throws IOException
throws IOException
{
handler.setConfig(config);
handler.storeConfig();
@@ -338,7 +338,7 @@ public class HgConfigResource
//~--- fields ---------------------------------------------------------------
/** Field description */
private HttpClient client;
private AdvancedHttpClient client;
/** Field description */
private HgRepositoryHandler handler;

View File

@@ -35,7 +35,6 @@ package sonia.scm.installer;
//~--- non-JDK imports --------------------------------------------------------
import sonia.scm.net.HttpClient;
import sonia.scm.repository.HgConfig;
import sonia.scm.repository.HgRepositoryHandler;
import sonia.scm.util.IOUtil;
@@ -44,6 +43,7 @@ import sonia.scm.util.IOUtil;
import java.io.File;
import java.io.IOException;
import sonia.scm.net.ahc.AdvancedHttpClient;
/**
*
@@ -93,7 +93,7 @@ public abstract class AbstractHgInstaller implements HgInstaller
* @return
*/
@Override
public boolean installPackage(HttpClient client, HgRepositoryHandler handler,
public boolean installPackage(AdvancedHttpClient client, HgRepositoryHandler handler,
File baseDirectory, HgPackage pkg)
{
return new HgPackageInstaller(client, handler, baseDirectory,

View File

@@ -35,7 +35,7 @@ package sonia.scm.installer;
//~--- non-JDK imports --------------------------------------------------------
import sonia.scm.net.HttpClient;
import sonia.scm.net.ahc.AdvancedHttpClient;
import sonia.scm.repository.HgConfig;
import sonia.scm.repository.HgRepositoryHandler;
@@ -78,8 +78,8 @@ public interface HgInstaller
*
* @return
*/
public boolean installPackage(HttpClient client, HgRepositoryHandler handler,
File baseDirectory, HgPackage pkg);
public boolean installPackage(AdvancedHttpClient client,
HgRepositoryHandler handler, File baseDirectory, HgPackage pkg);
/**
* Method description

View File

@@ -40,10 +40,10 @@ import org.slf4j.LoggerFactory;
import sonia.scm.SCMContext;
import sonia.scm.io.ZipUnArchiver;
import sonia.scm.net.HttpClient;
import sonia.scm.repository.HgWindowsPackageFix;
import sonia.scm.net.ahc.AdvancedHttpClient;
import sonia.scm.repository.HgConfig;
import sonia.scm.repository.HgRepositoryHandler;
import sonia.scm.repository.HgWindowsPackageFix;
import sonia.scm.util.IOUtil;
//~--- JDK imports ------------------------------------------------------------
@@ -80,8 +80,8 @@ public class HgPackageInstaller implements Runnable
* @param baseDirectory
* @param pkg
*/
public HgPackageInstaller(HttpClient client, HgRepositoryHandler handler,
File baseDirectory, HgPackage pkg)
public HgPackageInstaller(AdvancedHttpClient client,
HgRepositoryHandler handler, File baseDirectory, HgPackage pkg)
{
this.client = client;
this.handler = handler;
@@ -155,7 +155,7 @@ public class HgPackageInstaller implements Runnable
}
// TODO error handling
input = client.get(pkg.getUrl()).getContent();
input = client.get(pkg.getUrl()).request().contentAsStream();
output = new FileOutputStream(file);
IOUtil.copy(input, output);
}
@@ -265,7 +265,7 @@ public class HgPackageInstaller implements Runnable
private File baseDirectory;
/** Field description */
private HttpClient client;
private AdvancedHttpClient client;
/** Field description */
private HgRepositoryHandler handler;

View File

@@ -36,7 +36,6 @@ package sonia.scm.installer;
//~--- non-JDK imports --------------------------------------------------------
import com.google.inject.Inject;
import com.google.inject.Provider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -44,22 +43,17 @@ import org.slf4j.LoggerFactory;
import sonia.scm.PlatformType;
import sonia.scm.cache.Cache;
import sonia.scm.cache.CacheManager;
import sonia.scm.net.HttpClient;
import sonia.scm.net.HttpResponse;
import sonia.scm.util.IOUtil;
import sonia.scm.net.ahc.AdvancedHttpClient;
import sonia.scm.util.SystemUtil;
import sonia.scm.util.Util;
//~--- JDK imports ------------------------------------------------------------
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.JAXB;
/**
*
* @author Sebastian Sdorra
@@ -85,14 +79,13 @@ public class HgPackageReader
*
*
* @param cacheManager
* @param httpClientProvider
* @param httpClient
*/
@Inject
public HgPackageReader(CacheManager cacheManager,
Provider<HttpClient> httpClientProvider)
public HgPackageReader(CacheManager cacheManager, AdvancedHttpClient httpClient)
{
cache = cacheManager.getCache(CACHENAME);
this.httpClientProvider = httpClientProvider;
this.cache = cacheManager.getCache(CACHENAME);
this.httpClient = httpClient;
}
//~--- get methods ----------------------------------------------------------
@@ -167,7 +160,7 @@ public class HgPackageReader
if (logger.isDebugEnabled())
{
logger.debug("reject package {}, because of wrong platform {}",
pkg.getId(), pkg.getPlatform());
pkg.getId(), pkg.getPlatform());
}
add = false;
@@ -181,7 +174,7 @@ public class HgPackageReader
if (logger.isDebugEnabled())
{
logger.debug("reject package {}, because of wrong arch {}",
pkg.getId(), pkg.getArch());
pkg.getId(), pkg.getArch());
}
add = false;
@@ -218,23 +211,19 @@ public class HgPackageReader
}
HgPackages packages = null;
InputStream input = null;
try
{
HttpResponse response = httpClientProvider.get().get(PACKAGEURL);
input = response.getContent();
packages = JAXB.unmarshal(input, HgPackages.class);
//J-
packages = httpClient.get(PACKAGEURL)
.request()
.contentFromXml(HgPackages.class);
//J+
}
catch (IOException ex)
{
logger.error("could not read HgPackages from ".concat(PACKAGEURL), ex);
}
finally
{
IOUtil.close(input);
}
if (packages == null)
{
@@ -251,5 +240,5 @@ public class HgPackageReader
private final Cache<String, HgPackages> cache;
/** Field description */
private final Provider<HttpClient> httpClientProvider;
private final AdvancedHttpClient httpClient;
}

View File

@@ -48,10 +48,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sonia.scm.config.ScmConfiguration;
import sonia.scm.config.ScmConfigurationChangedEvent;
import sonia.scm.net.HttpClient;
import sonia.scm.net.HttpRequest;
import sonia.scm.net.HttpResponse;
import sonia.scm.util.HttpUtil;
import sonia.scm.util.Util;
@@ -62,6 +59,8 @@ import java.io.IOException;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
import sonia.scm.config.ScmConfigurationChangedEvent;
import sonia.scm.net.ahc.AdvancedHttpClient;
/**
*
@@ -88,16 +87,16 @@ public class HgHookManager
*
* @param configuration
* @param httpServletRequestProvider
* @param httpClientProvider
* @param httpClient
*/
@Inject
public HgHookManager(ScmConfiguration configuration,
Provider<HttpServletRequest> httpServletRequestProvider,
Provider<HttpClient> httpClientProvider)
AdvancedHttpClient httpClient)
{
this.configuration = configuration;
this.httpServletRequestProvider = httpServletRequestProvider;
this.httpClientProvider = httpClientProvider;
this.httpClient = httpClient;
}
//~--- methods --------------------------------------------------------------
@@ -360,20 +359,16 @@ public class HgHookManager
{
url = url.concat("?ping=true");
if (logger.isTraceEnabled())
{
logger.trace("check hook url {}", url);
}
HttpRequest request = new HttpRequest(url);
request.setDisableCertificateValidation(true);
request.setDisableHostnameValidation(true);
request.setIgnoreProxySettings(true);
HttpResponse response = httpClientProvider.get().get(request);
result = response.getStatusCode() == 204;
logger.trace("check hook url {}", url);
//J-
int sc = httpClient.get(url)
.disableHostnameValidation(true)
.disableCertificateValidation(true)
.ignoreProxySettings(true)
.request()
.getStatus();
//J+
result = sc == 204;
}
catch (IOException ex)
{
@@ -398,7 +393,7 @@ public class HgHookManager
private volatile String hookUrl;
/** Field description */
private Provider<HttpClient> httpClientProvider;
private AdvancedHttpClient httpClient;
/** Field description */
private Provider<HttpServletRequest> httpServletRequestProvider;

View File

@@ -89,7 +89,7 @@ public class HgRepositoryHandler
/** Field description */
public static final String RESOURCE_VERSION =
"/sonia/scm/version/scm-hg-plugin";
"sonia/scm/version/scm-hg-plugin";
/** Field description */
public static final String TYPE_DISPLAYNAME = "Mercurial";

View File

@@ -0,0 +1,155 @@
/**
* Copyright (c) 2014, Sebastian Sdorra All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer. 2. Redistributions in
* binary form must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution. 3. Neither the name of SCM-Manager;
* nor the names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* http://bitbucket.org/sdorra/scm-manager
*
*/
package sonia.scm.repository.api;
//~--- non-JDK imports --------------------------------------------------------
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableList.Builder;
import sonia.scm.repository.Changeset;
import sonia.scm.repository.spi.HookChangesetProvider;
import sonia.scm.repository.spi.HookChangesetRequest;
import sonia.scm.repository.spi.javahg.AbstractChangesetCommand;
import sonia.scm.util.Util;
//~--- JDK imports ------------------------------------------------------------
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Mercurial hook branch provider implementation.
*
* @author Sebastian Sdorra
*/
public class HgHookBranchProvider implements HookBranchProvider
{
private static final Logger logger = LoggerFactory.getLogger(HgHookBranchProvider.class);
private static final HookChangesetRequest REQUEST =
new HookChangesetRequest();
//~--- constructors ---------------------------------------------------------
/**
* Constructs a new instance.
*
*
* @param changesetProvider changeset provider
*/
public HgHookBranchProvider(HookChangesetProvider changesetProvider)
{
this.changesetProvider = changesetProvider;
}
//~--- get methods ----------------------------------------------------------
@Override
public List<String> getCreatedOrModified()
{
if (createdOrModified == null)
{
collect();
}
return createdOrModified;
}
@Override
public List<String> getDeletedOrClosed()
{
if (deletedOrClosed == null)
{
collect();
}
return deletedOrClosed;
}
//~--- methods --------------------------------------------------------------
private List<String> appendBranches(Builder<String> builder, Changeset c)
{
List<String> branches = c.getBranches();
if (Util.isEmpty(branches))
{
builder.add(AbstractChangesetCommand.BRANCH_DEFAULT);
}
else
{
builder.addAll(branches);
}
return branches;
}
private Iterable<Changeset> changesets()
{
return changesetProvider.handleRequest(REQUEST).getChangesets();
}
private void collect()
{
Builder<String> createdOrModifiedBuilder = ImmutableList.builder();
Builder<String> deletedOrClosedBuilder = ImmutableList.builder();
logger.trace("collecting branches from hook changesets");
for (Changeset c : changesets())
{
if (c.getProperty(AbstractChangesetCommand.PROPERTY_CLOSE) != null)
{
appendBranches(deletedOrClosedBuilder, c);
}
else
{
appendBranches(createdOrModifiedBuilder, c);
}
}
createdOrModified = createdOrModifiedBuilder.build();
deletedOrClosed = deletedOrClosedBuilder.build();
}
//~--- fields ---------------------------------------------------------------
private final HookChangesetProvider changesetProvider;
private List<String> createdOrModified;
private List<String> deletedOrClosed;
}

View File

@@ -0,0 +1,107 @@
/**
* *
* Copyright (c) 2015, Sebastian Sdorra
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of SCM-Manager; nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* https://bitbucket.org/sdorra/scm-manager
*
*/
package sonia.scm.repository.api;
import com.google.common.collect.ImmutableList;
import java.util.Collections;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sonia.scm.repository.Changeset;
import sonia.scm.repository.Tag;
import sonia.scm.repository.spi.HookChangesetProvider;
import sonia.scm.repository.spi.HookChangesetRequest;
import sonia.scm.repository.spi.HookChangesetResponse;
/**
* Mercurial tag provider implementation.
*
* @author Sebastian Sdorra
* @since 1.50
*/
public class HgHookTagProvider implements HookTagProvider {
private static final Logger logger = LoggerFactory.getLogger(HgHookTagProvider.class);
private static final HookChangesetRequest REQUEST = new HookChangesetRequest();
private final HookChangesetProvider changesetProvider;
private List<Tag> createdTags;
private final List<Tag> deletedTags = Collections.emptyList();
/**
* Constructs a new instance.
*
* @param changesetProvider changeset provider
*/
public HgHookTagProvider(HookChangesetProvider changesetProvider) {
this.changesetProvider = changesetProvider;
}
@Override
public List<Tag> getCreatedTags() {
if (createdTags == null) {
collect();
}
return createdTags;
}
@Override
public List<Tag> getDeletedTags() {
logger.warn("detecting deleted tags with mercurial is currently not supported");
return deletedTags;
}
private void collect() {
ImmutableList.Builder<Tag> createdTagsBuilder = ImmutableList.builder();
logger.trace("collecting tags from hook changesets");
HookChangesetResponse response = changesetProvider.handleRequest(REQUEST);
for ( Changeset c : response.getChangesets() ){
appendTags(createdTagsBuilder, c);
}
createdTags = createdTagsBuilder.build();
}
private void appendTags(ImmutableList.Builder<Tag> tags, Changeset c){
List<String> tagNames = c.getTags();
if (tagNames != null){
for ( String tagName : tagNames ){
logger.trace("found tag {} at changeset {}", tagName, c.getId());
tags.add(new Tag(tagName, c.getId()));
}
}
}
}

View File

@@ -30,10 +30,13 @@
*/
package sonia.scm.repository.spi;
//~--- non-JDK imports --------------------------------------------------------
import com.aragost.javahg.Changeset;
import com.google.common.base.Function;
import com.google.common.collect.Lists;
@@ -92,7 +95,15 @@ public class HgBranchesCommand extends AbstractCommand
@Override
public Branch apply(com.aragost.javahg.commands.Branch hgBranch)
{
return new Branch(hgBranch.getName());
String node = null;
Changeset changeset = hgBranch.getBranchTip();
if (changeset != null)
{
node = changeset.getNode();
}
return new Branch(hgBranch.getName(), node);
}
});

View File

@@ -36,7 +36,9 @@ package sonia.scm.repository.spi;
import sonia.scm.repository.HgHookManager;
import sonia.scm.repository.HgRepositoryHandler;
import sonia.scm.repository.RepositoryHookType;
import sonia.scm.repository.api.HgHookBranchProvider;
import sonia.scm.repository.api.HgHookMessageProvider;
import sonia.scm.repository.api.HookBranchProvider;
import sonia.scm.repository.api.HookFeature;
import sonia.scm.repository.api.HookMessageProvider;
@@ -44,29 +46,31 @@ import sonia.scm.repository.api.HookMessageProvider;
import java.util.EnumSet;
import java.util.Set;
import sonia.scm.repository.api.HgHookTagProvider;
import sonia.scm.repository.api.HookTagProvider;
/**
*
* Mercurial implementation of {@link HookContextProvider}.
*
* @author Sebastian Sdorra
*/
public class HgHookContextProvider extends HookContextProvider
{
/** Field description */
private static final Set<HookFeature> SUPPORTED_FEATURES =
EnumSet.of(HookFeature.CHANGESET_PROVIDER, HookFeature.MESSAGE_PROVIDER);
EnumSet.of(HookFeature.CHANGESET_PROVIDER, HookFeature.MESSAGE_PROVIDER,
HookFeature.BRANCH_PROVIDER, HookFeature.TAG_PROVIDER);
//~--- constructors ---------------------------------------------------------
/**
* Constructs ...
* Constructs a new instance.
*
*
* @param handler
* @param repositoryName
* @param hookManager
* @param startRev
* @param type
* @param handler mercurial repository handler
* @param repositoryName name of changed repository
* @param hookManager mercurial hook manager
* @param startRev start revision
* @param type type of hook
*/
public HgHookContextProvider(HgRepositoryHandler handler,
String repositoryName, HgHookManager hookManager, String startRev,
@@ -78,24 +82,34 @@ public class HgHookContextProvider extends HookContextProvider
//~--- get methods ----------------------------------------------------------
/**
* Method description
*
*
* @return
*/
@Override
public HookBranchProvider getBranchProvider()
{
if (hookBranchProvider == null)
{
hookBranchProvider = new HgHookBranchProvider(hookChangesetProvider);
}
return hookBranchProvider;
}
@Override
public HookTagProvider getTagProvider()
{
if (hookTagProvider == null)
{
hookTagProvider = new HgHookTagProvider(hookChangesetProvider);
}
return hookTagProvider;
}
@Override
public HookChangesetProvider getChangesetProvider()
{
return hookChangesetProvider;
}
/**
* Method description
*
*
* @return
*/
public HgHookMessageProvider getHgMessageProvider()
{
if (hgMessageProvider == null)
@@ -106,12 +120,6 @@ public class HgHookContextProvider extends HookContextProvider
return hgMessageProvider;
}
/**
* Method description
*
*
* @return
*/
@Override
public Set<HookFeature> getSupportedFeatures()
{
@@ -120,12 +128,6 @@ public class HgHookContextProvider extends HookContextProvider
//~--- methods --------------------------------------------------------------
/**
* Method description
*
*
* @return
*/
@Override
protected HookMessageProvider createMessageProvider()
{
@@ -134,9 +136,11 @@ public class HgHookContextProvider extends HookContextProvider
//~--- fields ---------------------------------------------------------------
/** Field description */
private final HgHookChangesetProvider hookChangesetProvider;
private HgHookMessageProvider hgMessageProvider;
/** Field description */
private HgHookChangesetProvider hookChangesetProvider;
private HgHookBranchProvider hookBranchProvider;
private HgHookTagProvider hookTagProvider;
}

View File

@@ -30,6 +30,7 @@
*/
package sonia.scm.repository.spi.javahg;
//~--- non-JDK imports --------------------------------------------------------
@@ -63,7 +64,7 @@ public abstract class AbstractChangesetCommand extends AbstractCommand
{
/** Field description */
private static final String BRANCH_DEFAULT = "default";
public static final String BRANCH_DEFAULT = "default";
/**
* Character sequence that indicate the begin and end of the
@@ -87,6 +88,9 @@ public abstract class AbstractChangesetCommand extends AbstractCommand
private static final String NULL_ID =
"0000000000000000000000000000000000000000";
/** changeset property for closed branch */
public static final String PROPERTY_CLOSE = "hg.close";
/** changeset property for parent1 revision */
private static final String PROPERTY_PARENT1_REVISION = "hg.p1.rev";
@@ -114,12 +118,80 @@ public abstract class AbstractChangesetCommand extends AbstractCommand
//~--- methods --------------------------------------------------------------
/**
* Method description
*
*
* @param stream
*
* @return
*/
protected List<Integer> loadRevisionsFromStream(HgInputStream stream)
{
List<Integer> revisions = Lists.newArrayList();
//~--- get methods ----------------------------------------------------------
try
{
while (stream.peek() != -1)
{
int rev = stream.revisionUpTo(' ');
if (rev >= 0)
{
revisions.add(rev);
}
}
}
catch (IOException ex)
{
throw new RuntimeIOException(ex);
}
//~--- methods --------------------------------------------------------------
return revisions;
}
/**
* Method description
*
*
* @param in
*
* @return
*/
protected List<Changeset> readListFromStream(HgInputStream in)
{
List<Changeset> changesets = Lists.newArrayList();
try
{
boolean found = in.find(CHANGESET_PATTERN);
if (found)
{
while (!in.match(CHANGESET_PATTERN))
{
Changeset cset = createFromInputStream(in);
if (cset != null)
{
changesets.add(cset);
}
}
Utils.consumeAll(in);
}
// If the pattern is not found there is no changsets
}
catch (IOException e)
{
throw new RuntimeIOException(e);
}
return changesets;
}
/**
* Method description
@@ -168,7 +240,16 @@ public abstract class AbstractChangesetCommand extends AbstractCommand
changeset.getParents().add(p2);
}
in.mustMatch(' '); // skip space part of {parents}
// skip space part of {parents}
in.mustMatch(' ');
// read extras
String extraLine = in.textUpTo('\n');
if (extraLine.contains("close=1"))
{
changeset.getProperties().put(PROPERTY_CLOSE, "true");
}
Modifications modifications = changeset.getModifications();
@@ -204,39 +285,6 @@ public abstract class AbstractChangesetCommand extends AbstractCommand
return changeset;
}
/**
* Method description
*
*
* @param stream
*
* @return
*/
protected List<Integer> loadRevisionsFromStream(HgInputStream stream)
{
List<Integer> revisions = Lists.newArrayList();
try
{
while (stream.peek() != -1)
{
int rev = stream.revisionUpTo(' ');
if (rev >= 0)
{
revisions.add(rev);
}
}
}
catch (IOException ex)
{
throw new RuntimeIOException(ex);
}
return revisions;
}
/**
* Method description
*
@@ -268,48 +316,6 @@ public abstract class AbstractChangesetCommand extends AbstractCommand
return in.nextAsText(40);
}
/**
* Method description
*
*
* @param in
*
* @return
*/
protected List<Changeset> readListFromStream(HgInputStream in)
{
List<Changeset> changesets = Lists.newArrayList();
try
{
boolean found = in.find(CHANGESET_PATTERN);
if (found)
{
while (!in.match(CHANGESET_PATTERN))
{
Changeset cset = createFromInputStream(in);
if (cset != null)
{
changesets.add(cset);
}
}
Utils.consumeAll(in);
}
// If the pattern is not found there is no changsets
}
catch (IOException e)
{
throw new RuntimeIOException(e);
}
return changesets;
}
//~--- get methods ----------------------------------------------------------
/**

View File

@@ -35,6 +35,7 @@ package sonia.scm.web;
//~--- non-JDK imports --------------------------------------------------------
import com.google.common.base.Stopwatch;
import com.google.common.base.Strings;
import com.google.inject.Inject;
import com.google.inject.Singleton;
@@ -130,6 +131,7 @@ public class HgCGIServlet extends HttpServlet
this.hookManager = hookManager;
this.requestListenerUtil = requestListenerUtil;
this.exceptionHandler = new HgCGIExceptionHandler();
this.command = HgPythonScript.HGWEB.getFile(SCMContext.getContext());
}
//~--- methods --------------------------------------------------------------
@@ -143,7 +145,7 @@ public class HgCGIServlet extends HttpServlet
@Override
public void init() throws ServletException
{
command = HgPythonScript.HGWEB.getFile(SCMContext.getContext());
super.init();
}
@@ -184,7 +186,11 @@ public class HgCGIServlet extends HttpServlet
{
handleRequest(request, response, repository);
}
catch (Exception ex)
catch (ServletException ex)
{
exceptionHandler.handleException(request, response, ex);
}
catch (IOException ex)
{
exceptionHandler.handleException(request, response, ex);
}
@@ -241,7 +247,9 @@ public class HgCGIServlet extends HttpServlet
{
if (requestListenerUtil.callListeners(request, response, repository))
{
Stopwatch sw = Stopwatch.createStarted();
process(request, response, repository);
logger.debug("mercurial request finished in {}", sw.stop());
}
else if (logger.isDebugEnabled())
{
@@ -358,26 +366,26 @@ public class HgCGIServlet extends HttpServlet
//~--- fields ---------------------------------------------------------------
/** Field description */
private CGIExecutorFactory cgiExecutorFactory;
private final CGIExecutorFactory cgiExecutorFactory;
/** Field description */
private File command;
private final File command;
/** Field description */
private ScmConfiguration configuration;
private final ScmConfiguration configuration;
/** Field description */
private HgCGIExceptionHandler exceptionHandler;
private final HgCGIExceptionHandler exceptionHandler;
/** Field description */
private HgRepositoryHandler handler;
private final HgRepositoryHandler handler;
/** Field description */
private HgHookManager hookManager;
private final HgHookManager hookManager;
/** Field description */
private RepositoryProvider repositoryProvider;
private final RepositoryProvider repositoryProvider;
/** Field description */
private RepositoryRequestListenerUtil requestListenerUtil;
private final RepositoryRequestListenerUtil requestListenerUtil;
}

View File

@@ -35,6 +35,7 @@ package sonia.scm.web;
//~--- non-JDK imports --------------------------------------------------------
import com.google.common.collect.ImmutableSet;
import com.google.inject.Inject;
import sonia.scm.Priority;
@@ -46,22 +47,27 @@ import sonia.scm.web.filter.ProviderPermissionFilter;
//~--- JDK imports ------------------------------------------------------------
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
/**
*
* Permission filter for mercurial repositories.
*
* @author Sebastian Sdorra
*/
@Priority(Filters.PRIORITY_AUTHORIZATION)
@WebElement(value = HgServletModule.MAPPING_HG)
public class HgPermissionFilter extends ProviderPermissionFilter
{
private static final Set<String> READ_METHODS = ImmutableSet.of("GET", "HEAD", "OPTIONS", "TRACE");
/**
* Constructs ...
* Constructs a new instance.
*
* @param configuration
* @param repositoryProvider
* @param configuration scm configuration
* @param repositoryProvider repository provider
*/
@Inject
public HgPermissionFilter(ScmConfiguration configuration,
@@ -72,17 +78,9 @@ public class HgPermissionFilter extends ProviderPermissionFilter
//~--- get methods ----------------------------------------------------------
/**
* Method description
*
*
* @param request
*
* @return
*/
@Override
protected boolean isWriteRequest(HttpServletRequest request)
{
return !request.getMethod().equalsIgnoreCase("GET");
return !READ_METHODS.contains(request.getMethod());
}
}

View File

@@ -0,0 +1,84 @@
/**
* Copyright (c) 2010, Sebastian Sdorra All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer. 2. Redistributions in
* binary form must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution. 3. Neither the name of SCM-Manager;
* nor the names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* http://bitbucket.org/sdorra/scm-manager
*
*/
package sonia.scm.web;
//~--- non-JDK imports --------------------------------------------------------
import com.google.common.annotations.VisibleForTesting;
import sonia.scm.plugin.Extension;
//~--- JDK imports ------------------------------------------------------------
import java.nio.charset.Charset;
/**
*
* @author Sebastian Sdorra <s.sdorra@gmail.com>
* @since 1.45
*/
@Extension
public class HgUserAgentProvider implements UserAgentProvider
{
/** mercurial seems to use system encoding */
@VisibleForTesting
static UserAgent HG = UserAgent.builder("Mercurial").browser(
false).basicAuthenticationCharset(
Charset.defaultCharset()).build();
/** Field description */
private static final String PREFIX = "mercurial";
//~--- methods --------------------------------------------------------------
/**
* Method description
*
*
* @param userAgentString
*
* @return
*/
@Override
public UserAgent parseUserAgent(String userAgentString)
{
UserAgent ua = null;
if (userAgentString.startsWith(PREFIX))
{
ua = HG;
}
return ua;
}
}

View File

@@ -1,5 +1,5 @@
header = "%{pattern}"
changeset = "{rev}:{node}{author}\n{date|hgdate}\n{branch}\n{parents}{tags}{file_adds}{file_mods}{file_dels}\n{desc}\0"
changeset = "{rev}:{node}{author}\n{date|hgdate}\n{branch}\n{parents}{join(extras,',')}\n{tags}{file_adds}{file_mods}{file_dels}\n{desc}\0"
tag = "t {tag}\n"
file_add = "a {file_add}\n"
file_mod = "m {file_mod}\n"

View File

@@ -0,0 +1,104 @@
/***
* Copyright (c) 2015, Sebastian Sdorra
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of SCM-Manager; nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* https://bitbucket.org/sdorra/scm-manager
*
*/
package sonia.scm.repository.api;
import com.google.common.collect.Lists;
import java.util.List;
import org.junit.Test;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
import static org.hamcrest.Matchers.*;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;
import sonia.scm.repository.Changeset;
import sonia.scm.repository.Tag;
import sonia.scm.repository.spi.HookChangesetProvider;
import sonia.scm.repository.spi.HookChangesetRequest;
import sonia.scm.repository.spi.HookChangesetResponse;
/**
* Unit tests for {@link HgHookTagProvider}.
*
* @author Sebastian Sdorra
*/
@RunWith(MockitoJUnitRunner.class)
public class HgHookTagProviderTest {
@Mock
private HookChangesetProvider changesetProvider;
@InjectMocks
private HgHookTagProvider tagProvider;
/**
* Tests {@link HgHookTagProvider#getDeletedTags()}.
*/
@Test
public void testGetDeletedTags() {
prepareChangesets(new Changeset("1", Long.MIN_VALUE, null));
assertThat(tagProvider.getDeletedTags(), empty());
}
/**
* Tests {@link HgHookTagProvider#getCreatedTags()}.
*/
@Test
public void testGetCreatedTags(){
Changeset c1 = new Changeset("1", Long.MIN_VALUE, null);
c1.getTags().add("1.0.0");
Changeset c2 = new Changeset("2", Long.MIN_VALUE, null);
c2.getTags().add("2.0.0");
Changeset c3 = new Changeset("3", Long.MIN_VALUE, null);
prepareChangesets(c1, c2, c3);
List<Tag> tags = tagProvider.getCreatedTags();
assertNotNull(tags);
assertEquals(2, tags.size());
Tag t1 = tags.get(0);
assertEquals("1", t1.getRevision());
assertEquals("1.0.0", t1.getName());
Tag t2 = tags.get(1);
assertEquals("2", t2.getRevision());
assertEquals("2.0.0", t2.getName());
}
private void prepareChangesets(Changeset... changesets){
List<Changeset> list = Lists.newArrayList(changesets);
HookChangesetResponse response = new HookChangesetResponse(list);
when(changesetProvider.handleRequest(Mockito.any(HookChangesetRequest.class))).thenReturn(response);
}
}

View File

@@ -0,0 +1,57 @@
/**
* Copyright (c) 2014, Sebastian Sdorra
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of SCM-Manager; nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* http://bitbucket.org/sdorra/scm-manager
*
*/
package sonia.scm.repository.client.spi;
import com.aragost.javahg.Repository;
import java.io.IOException;
/**
* Mercurial implementation of the {@link AddCommand}.
*
* @author Sebastian Sdorra
*/
public final class HgAddCommand implements AddCommand
{
private final Repository repository;
HgAddCommand(Repository repository)
{
this.repository = repository;
}
@Override
public void add(String path) throws IOException
{
com.aragost.javahg.commands.AddCommand.on(repository).execute(path);
}
}

View File

@@ -0,0 +1,59 @@
/**
* Copyright (c) 2014, Sebastian Sdorra
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of SCM-Manager; nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* http://bitbucket.org/sdorra/scm-manager
*
*/
package sonia.scm.repository.client.spi;
import com.aragost.javahg.Repository;
import java.io.IOException;
import sonia.scm.repository.Branch;
/**
* Mercurial implementation of the {@link BranchCommand}.
*
* @author Sebastian Sdorra
*/
public class HgBranchCommand implements BranchCommand
{
private final Repository repository;
HgBranchCommand(Repository repository)
{
this.repository = repository;
}
@Override
public Branch branch(String name) throws IOException
{
com.aragost.javahg.commands.BranchCommand.on(repository).set(name);
return new Branch(name, repository.tip().getNode());
}
}

View File

@@ -0,0 +1,79 @@
/**
* Copyright (c) 2014, Sebastian Sdorra
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of SCM-Manager; nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* http://bitbucket.org/sdorra/scm-manager
*
*/
package sonia.scm.repository.client.spi;
import com.aragost.javahg.Repository;
import com.google.common.collect.Lists;
import java.io.IOException;
import sonia.scm.repository.Changeset;
import sonia.scm.repository.Modifications;
import sonia.scm.repository.Person;
/**
* Mercurial implementation of the {@link CommitCommand}.
*
* @author Sebastian Sdorra
*/
public class HgCommitCommand implements CommitCommand
{
private final Repository repository;
HgCommitCommand(Repository repository)
{
this.repository = repository;
}
@Override
public Changeset commit(CommitRequest request) throws IOException
{
com.aragost.javahg.Changeset c = com.aragost.javahg.commands.CommitCommand
.on(repository)
.user(request.getAuthor().toString())
.message(request.getMessage())
.execute();
Changeset changeset = new Changeset(
c.getNode(),
c.getTimestamp().getDate().getTime(),
Person.toPerson(c.getUser()),
c.getMessage()
);
changeset.setBranches(Lists.newArrayList(c.getBranch()));
changeset.setTags(c.tags());
changeset.setModifications(
new Modifications(c.getAddedFiles(), c.getModifiedFiles(), c.getDeletedFiles())
);
return changeset;
}
}

View File

@@ -0,0 +1,61 @@
/**
* Copyright (c) 2014, Sebastian Sdorra
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of SCM-Manager; nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* http://bitbucket.org/sdorra/scm-manager
*
*/
package sonia.scm.repository.client.spi;
import com.aragost.javahg.Repository;
import java.io.IOException;
/**
* Mercurial implementation of the {@link PushCommand}.
*
* @author Sebastian Sdorra
*/
public class HgPushCommand implements PushCommand
{
private final Repository repository;
private final String url;
HgPushCommand(Repository repository, String url)
{
this.repository = repository;
this.url = url;
}
@Override
public void push() throws IOException
{
com.aragost.javahg.commands.PushCommand cmd = com.aragost.javahg.commands.PushCommand.on(repository);
cmd.cmdAppend("--new-branch");
cmd.execute(url);
}
}

View File

@@ -0,0 +1,57 @@
/**
* Copyright (c) 2014, Sebastian Sdorra
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of SCM-Manager; nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* http://bitbucket.org/sdorra/scm-manager
*
*/
package sonia.scm.repository.client.spi;
import com.aragost.javahg.Repository;
import java.io.IOException;
/**
* Mercurial implementation of the {@link RemoveCommand}.
*
* @author Sebastian Sdorra
*/
public class HgRemoveCommand implements RemoveCommand
{
private final Repository repository;
HgRemoveCommand(Repository repository)
{
this.repository = repository;
}
@Override
public void remove(String path) throws IOException
{
com.aragost.javahg.commands.RemoveCommand.on(repository).execute(path);
}
}

View File

@@ -0,0 +1,122 @@
/**
* Copyright (c) 2014, Sebastian Sdorra
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of SCM-Manager; nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* http://bitbucket.org/sdorra/scm-manager
*
*/
package sonia.scm.repository.client.spi;
import com.aragost.javahg.Repository;
import com.aragost.javahg.RepositoryConfiguration;
import com.aragost.javahg.commands.PullCommand;
import com.google.common.base.Strings;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import sonia.scm.io.INIConfiguration;
import sonia.scm.io.INIConfigurationWriter;
import sonia.scm.io.INISection;
import sonia.scm.util.IOUtil;
/**
* Mercurial implementation of the {@link RepositoryClientFactoryProvider}.
*
* @author Sebastian Sdorra
*/
public class HgRepositoryClientFactoryProvider implements RepositoryClientFactoryProvider
{
private static final String TYPE = "hg";
@Override
public RepositoryClientProvider create(File main, File workingCopy) throws IOException
{
return create(main.toURI().toString(), null, null, workingCopy);
}
@Override
public RepositoryClientProvider create(String url, String username, String password, File workingCopy)
throws IOException
{
RepositoryConfiguration configuration = new RepositoryConfiguration();
String binary = IOUtil.search("hg");
if (Strings.isNullOrEmpty(binary)){
throw new IOException("could not find mercurial binary (hg)");
}
configuration.setHgBin(binary);
File hgrc = null;
if (!Strings.isNullOrEmpty(username))
{
hgrc = createHgrc(url, username, password);
configuration.setHgrcPath(hgrc.getAbsolutePath());
}
Repository repository = Repository.create(configuration, workingCopy);
PullCommand.on(repository).execute(url);
return new HgRepositoryClientProvider(repository, hgrc, url);
}
private File createHgrc(String url, String username, String password) throws IOException
{
URL repositoryUrl = new URL(url);
INIConfiguration hgConfig = new INIConfiguration();
INISection pathSection = new INISection("paths");
pathSection.setParameter(repositoryUrl.getHost(), url);
hgConfig.addSection(pathSection);
String prefix = repositoryUrl.getHost() + ".";
INISection authSection = new INISection("auth");
authSection.setParameter(
prefix + "prefix",
repositoryUrl.getHost() + ":" + repositoryUrl.getPort() + repositoryUrl.getPath()
);
authSection.setParameter(prefix + "schemes", repositoryUrl.getProtocol());
authSection.setParameter(prefix + "username", username);
if (!Strings.isNullOrEmpty(password))
{
authSection.setParameter(prefix + "password", password);
}
hgConfig.addSection(authSection);
File hgrc = File.createTempFile("hgrc", ".temp");
INIConfigurationWriter writer = new INIConfigurationWriter();
writer.write(hgConfig, hgrc);
return hgrc;
}
@Override
public String getType()
{
return TYPE;
}
}

View File

@@ -0,0 +1,114 @@
/**
* Copyright (c) 2014, Sebastian Sdorra
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of SCM-Manager; nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* http://bitbucket.org/sdorra/scm-manager
*
*/
package sonia.scm.repository.client.spi;
import com.aragost.javahg.Repository;
import com.google.common.collect.ImmutableSet;
import java.io.File;
import java.io.IOException;
import java.util.Set;
import sonia.scm.repository.client.api.ClientCommand;
/**
* Mercurial implementation of the {@link RepositoryClientProvider}.
*
* @author Sebastian Sdorra
*/
public class HgRepositoryClientProvider extends RepositoryClientProvider
{
private static final Set<ClientCommand> SUPPORTED_COMMANDS = ImmutableSet.of(
ClientCommand.ADD, ClientCommand.REMOVE, ClientCommand.COMMIT,
ClientCommand.TAG, ClientCommand.BANCH, ClientCommand.PUSH
);
private final Repository repository;
private final File hgrc;
private final String url;
HgRepositoryClientProvider(Repository repository, File hgrc, String url)
{
this.repository = repository;
this.hgrc = hgrc;
this.url = url;
}
@Override
public Set<ClientCommand> getSupportedClientCommands()
{
return SUPPORTED_COMMANDS;
}
@Override
public AddCommand getAddCommand()
{
return new HgAddCommand(repository);
}
@Override
public RemoveCommand getRemoveCommand()
{
return new HgRemoveCommand(repository);
}
@Override
public CommitCommand getCommitCommand()
{
return new HgCommitCommand(repository);
}
@Override
public TagCommand getTagCommand()
{
return new HgTagCommand(repository);
}
@Override
public BranchCommand getBranchCommand()
{
return new HgBranchCommand(repository);
}
@Override
public PushCommand getPushCommand()
{
return new HgPushCommand(repository, url);
}
@Override
public void close() throws IOException
{
if ( hgrc != null && hgrc.exists() && ! hgrc.delete() ){
throw new IOException("failed to remove hgrc file ".concat(hgrc.getPath()));
}
repository.close();
}
}

View File

@@ -0,0 +1,64 @@
/**
* Copyright (c) 2014, Sebastian Sdorra
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of SCM-Manager; nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* http://bitbucket.org/sdorra/scm-manager
*
*/
package sonia.scm.repository.client.spi;
import com.aragost.javahg.Repository;
import com.google.common.base.Strings;
import java.io.IOException;
import sonia.scm.repository.Tag;
/**
* Mercurial implementation of the {@link TagCommand}.
*
* @author Sebastian Sdorra
*/
public class HgTagCommand implements TagCommand
{
private final Repository repository;
HgTagCommand(Repository repository)
{
this.repository = repository;
}
@Override
public Tag tag(TagRequest request) throws IOException
{
String rev = request.getRevision();
if ( Strings.isNullOrEmpty(rev) ){
rev = repository.tip().getNode();
}
com.aragost.javahg.commands.TagCommand.on(repository).rev(rev).execute(request.getName());
return new Tag(request.getName(), rev);
}
}

View File

@@ -0,0 +1,88 @@
/**
* Copyright (c) 2014, Sebastian Sdorra
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of SCM-Manager; nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* http://bitbucket.org/sdorra/scm-manager
*
*/
package sonia.scm.web;
import javax.servlet.http.HttpServletRequest;
import org.junit.Test;
import static org.junit.Assert.*;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import static org.mockito.Mockito.*;
import org.mockito.runners.MockitoJUnitRunner;
import sonia.scm.config.ScmConfiguration;
import sonia.scm.repository.RepositoryProvider;
/**
* Unit tests for {@link HgPermissionFilter}.
*
* @author Sebastian Sdorra
*/
@RunWith(MockitoJUnitRunner.class)
public class HgPermissionFilterTest {
@Mock
private HttpServletRequest request;
@Mock
private ScmConfiguration configuration;
@Mock
private RepositoryProvider repositoryProvider;
@InjectMocks
private HgPermissionFilter filter;
/**
* Tests {@link HgPermissionFilter#isWriteRequest(HttpServletRequest)}.
*/
@Test
public void testIsWriteRequest() {
// read methods
assertFalse(isWriteRequest("GET"));
assertFalse(isWriteRequest("HEAD"));
assertFalse(isWriteRequest("TRACE"));
assertFalse(isWriteRequest("OPTIONS"));
// write methods
assertTrue(isWriteRequest("POST"));
assertTrue(isWriteRequest("PUT"));
assertTrue(isWriteRequest("DELETE"));
assertTrue(isWriteRequest("KA"));
}
private boolean isWriteRequest(String method) {
when(request.getMethod()).thenReturn(method);
return filter.isWriteRequest(request);
}
}

View File

@@ -0,0 +1,91 @@
/**
* Copyright (c) 2010, Sebastian Sdorra All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer. 2. Redistributions in
* binary form must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution. 3. Neither the name of SCM-Manager;
* nor the names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* http://bitbucket.org/sdorra/scm-manager
*
*/
package sonia.scm.web;
//~--- non-JDK imports --------------------------------------------------------
import com.google.common.base.Strings;
import org.junit.Test;
import static org.junit.Assert.*;
//~--- JDK imports ------------------------------------------------------------
import java.util.Locale;
/**
*
* @author Sebastian Sdorra <sebastian.sdorra@triology.de>
*/
public class HgUserAgentProviderTest
{
/** Field description */
private static final String UA_1 = "mercurial/proto-1.0";
/** Field description */
private static final String UA_2 =
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.124 Safari/537.36";
//~--- methods --------------------------------------------------------------
/**
* Method description
*
*/
@Test
public void testParseUserAgent()
{
assertEquals(HgUserAgentProvider.HG, parse(UA_1));
assertNull(parse(UA_2));
}
/**
* Method description
*
*
* @param v
*
* @return
*/
private UserAgent parse(String v)
{
return provider.parseUserAgent(
Strings.nullToEmpty(v).toLowerCase(Locale.ENGLISH));
}
//~--- fields ---------------------------------------------------------------
/** Field description */
private final HgUserAgentProvider provider = new HgUserAgentProvider();
}

View File

@@ -0,0 +1 @@
sonia.scm.repository.client.spi.HgRepositoryClientFactoryProvider