mirror of
https://github.com/scm-manager/scm-manager.git
synced 2026-02-23 06:50:49 +01:00
merge with branch issue-873
This commit is contained in:
@@ -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;
|
||||
|
||||
import sonia.scm.event.Event;
|
||||
|
||||
/**
|
||||
* Event which causes clearing of repository cache.
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
* @since 1.50
|
||||
*/
|
||||
@Event
|
||||
public class ClearRepositoryCacheEvent {
|
||||
|
||||
private final Repository repository;
|
||||
|
||||
/**
|
||||
* Constructs a new instance.
|
||||
*
|
||||
* @param repository repository
|
||||
*/
|
||||
public ClearRepositoryCacheEvent(Repository repository) {
|
||||
this.repository = repository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns repository.
|
||||
*
|
||||
* @return repository
|
||||
*/
|
||||
public Repository getRepository() {
|
||||
return repository;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -37,6 +37,8 @@ package sonia.scm.repository.api;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
@@ -69,6 +71,8 @@ import sonia.scm.security.ScmSecurityException;
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.util.Set;
|
||||
import sonia.scm.event.ScmEventBus;
|
||||
import sonia.scm.repository.ClearRepositoryCacheEvent;
|
||||
|
||||
/**
|
||||
* The {@link RepositoryServiceFactory} is the entrypoint of the repository api.
|
||||
@@ -172,6 +176,9 @@ public final class RepositoryServiceFactory
|
||||
|
||||
repositoryManager.addHook(cch);
|
||||
repositoryManager.addListener(cch);
|
||||
|
||||
// register cache clear hook for incoming events
|
||||
ScmEventBus.getInstance().register(cch);
|
||||
}
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
@@ -310,46 +317,60 @@ public final class RepositoryServiceFactory
|
||||
//~--- inner classes --------------------------------------------------------
|
||||
|
||||
/**
|
||||
* TODO find a more elegant way
|
||||
*
|
||||
*
|
||||
* @version Enter version here..., 12/06/16
|
||||
* @author Enter your name here...
|
||||
* Hook and listener to clear all relevant repository caches.
|
||||
*/
|
||||
private static class CacheClearHook extends PostReceiveRepositoryHook
|
||||
implements RepositoryListener
|
||||
{
|
||||
|
||||
private final Set<Cache<?, ?>> caches = Sets.newHashSet();
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
* Constructs a new instance and collect all repository relevant
|
||||
* caches from the {@link CacheManager}.
|
||||
*
|
||||
*
|
||||
* @param cacheManager
|
||||
* @param cacheManager cache manager
|
||||
*/
|
||||
public CacheClearHook(CacheManager cacheManager)
|
||||
{
|
||||
this.blameCache =
|
||||
cacheManager.getCache(BlameCommandBuilder.CacheKey.class,
|
||||
BlameResult.class, BlameCommandBuilder.CACHE_NAME);
|
||||
this.browseCache =
|
||||
cacheManager.getCache(BrowseCommandBuilder.CacheKey.class,
|
||||
BrowserResult.class, BrowseCommandBuilder.CACHE_NAME);
|
||||
this.logCache = cacheManager.getCache(LogCommandBuilder.CacheKey.class,
|
||||
ChangesetPagingResult.class, LogCommandBuilder.CACHE_NAME);
|
||||
this.tagsCache = cacheManager.getCache(TagsCommandBuilder.CacheKey.class,
|
||||
Tags.class, TagsCommandBuilder.CACHE_NAME);
|
||||
this.branchesCache =
|
||||
cacheManager.getCache(BranchesCommandBuilder.CacheKey.class,
|
||||
Branches.class, BranchesCommandBuilder.CACHE_NAME);
|
||||
this.caches.add(cacheManager.getCache(
|
||||
BlameCommandBuilder.CacheKey.class,
|
||||
BlameResult.class, BlameCommandBuilder.CACHE_NAME)
|
||||
);
|
||||
this.caches.add(cacheManager.getCache(
|
||||
BrowseCommandBuilder.CacheKey.class,
|
||||
BrowserResult.class, BrowseCommandBuilder.CACHE_NAME)
|
||||
);
|
||||
this.caches.add(cacheManager.getCache(
|
||||
LogCommandBuilder.CacheKey.class,
|
||||
ChangesetPagingResult.class, LogCommandBuilder.CACHE_NAME)
|
||||
);
|
||||
this.caches.add(cacheManager.getCache(
|
||||
TagsCommandBuilder.CacheKey.class,
|
||||
Tags.class, TagsCommandBuilder.CACHE_NAME)
|
||||
);
|
||||
this.caches.add(cacheManager.getCache(
|
||||
BranchesCommandBuilder.CacheKey.class,
|
||||
Branches.class, BranchesCommandBuilder.CACHE_NAME)
|
||||
);
|
||||
}
|
||||
|
||||
//~--- methods ------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
* Clear caches on explicit repository cache clear event.
|
||||
*
|
||||
* @param event clear event
|
||||
*/
|
||||
@Subscribe
|
||||
public void onEvent(ClearRepositoryCacheEvent event) {
|
||||
clearCaches(event.getRepository().getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear caches on repository push.
|
||||
*
|
||||
*
|
||||
* @param event
|
||||
* @param event hook event
|
||||
*/
|
||||
@Override
|
||||
public void onEvent(RepositoryHookEvent event)
|
||||
@@ -365,11 +386,10 @@ public final class RepositoryServiceFactory
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
* Clear caches on repository delete event.
|
||||
*
|
||||
*
|
||||
* @param repository
|
||||
* @param event
|
||||
* @param repository changed repository
|
||||
* @param event repository event
|
||||
*/
|
||||
@Override
|
||||
public void onEvent(Repository repository, HandlerEvent event)
|
||||
@@ -379,13 +399,7 @@ public final class RepositoryServiceFactory
|
||||
clearCaches(repository.getId());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param repositoryId
|
||||
*/
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void clearCaches(final String repositoryId)
|
||||
{
|
||||
@@ -394,32 +408,11 @@ public final class RepositoryServiceFactory
|
||||
logger.debug("clear caches for repository id {}", repositoryId);
|
||||
}
|
||||
|
||||
RepositoryCacheKeyFilter filter =
|
||||
new RepositoryCacheKeyFilter(repositoryId);
|
||||
|
||||
blameCache.removeAll(filter);
|
||||
browseCache.removeAll(filter);
|
||||
logCache.removeAll(filter);
|
||||
tagsCache.removeAll(filter);
|
||||
branchesCache.removeAll(filter);
|
||||
RepositoryCacheKeyFilter filter = new RepositoryCacheKeyFilter(repositoryId);
|
||||
for (Cache<?,?> cache : caches) {
|
||||
cache.removeAll(filter);
|
||||
}
|
||||
}
|
||||
|
||||
//~--- fields -------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private Cache<BlameCommandBuilder.CacheKey, BlameResult> blameCache;
|
||||
|
||||
/** Field description */
|
||||
private Cache<BranchesCommandBuilder.CacheKey, Branches> branchesCache;
|
||||
|
||||
/** Field description */
|
||||
private Cache<BrowseCommandBuilder.CacheKey, BrowserResult> browseCache;
|
||||
|
||||
/** Field description */
|
||||
private Cache<LogCommandBuilder.CacheKey, ChangesetPagingResult> logCache;
|
||||
|
||||
/** Field description */
|
||||
private Cache<TagsCommandBuilder.CacheKey, Tags> tagsCache;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Constants for Git.
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
* @since 1.50
|
||||
*/
|
||||
public final class GitConstants {
|
||||
|
||||
/**
|
||||
* Default branch repository property.
|
||||
*/
|
||||
public static final String PROPERTY_DEFAULT_BRANCH = "git.default-branch";
|
||||
|
||||
private GitConstants() {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/**
|
||||
* 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;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Objects;
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import sonia.scm.EagerSingleton;
|
||||
import sonia.scm.HandlerEvent;
|
||||
import sonia.scm.event.ScmEventBus;
|
||||
import sonia.scm.plugin.ext.Extension;
|
||||
|
||||
/**
|
||||
* Repository listener which handles git related repository events.
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
* @since 1.50
|
||||
*/
|
||||
@Extension
|
||||
@EagerSingleton
|
||||
public class GitRepositoryModifyListener {
|
||||
|
||||
/**
|
||||
* the logger for GitRepositoryModifyListener
|
||||
*/
|
||||
private static final Logger logger = LoggerFactory.getLogger(GitRepositoryModifyListener.class);
|
||||
|
||||
/**
|
||||
* Receives {@link RepositoryModificationEvent} and fires a {@link ClearRepositoryCacheEvent} if
|
||||
* the default branch of a git repository was modified.
|
||||
*
|
||||
* @param event repository modification event
|
||||
*/
|
||||
@Subscribe
|
||||
public void handleEvent(RepositoryModificationEvent event){
|
||||
Repository repository = event.getItem();
|
||||
|
||||
if ( isModifyEvent(event) &&
|
||||
isGitRepository(event.getItem()) &&
|
||||
hasDefaultBranchChanged(event.getItemBeforeModification(), repository))
|
||||
{
|
||||
logger.info("git default branch of repository {} has changed, sending clear cache event", repository.getId());
|
||||
sendClearRepositoryCacheEvent(repository);
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
protected void sendClearRepositoryCacheEvent(Repository repository) {
|
||||
ScmEventBus.getInstance().post(new ClearRepositoryCacheEvent(repository));
|
||||
}
|
||||
|
||||
private boolean isModifyEvent(RepositoryEvent event) {
|
||||
return event.getEventType() == HandlerEvent.MODIFY;
|
||||
}
|
||||
|
||||
private boolean isGitRepository(Repository repository) {
|
||||
return GitRepositoryHandler.TYPE_NAME.equals(repository.getType());
|
||||
}
|
||||
|
||||
private boolean hasDefaultBranchChanged(Repository old, Repository current) {
|
||||
return !Objects.equal(
|
||||
old.getProperty(GitConstants.PROPERTY_DEFAULT_BRANCH),
|
||||
current.getProperty(GitConstants.PROPERTY_DEFAULT_BRANCH)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -34,11 +34,18 @@ package sonia.scm.repository.spi;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Strings;
|
||||
import org.eclipse.jgit.lib.Repository;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.io.IOException;
|
||||
import org.eclipse.jgit.lib.ObjectId;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import sonia.scm.repository.GitConstants;
|
||||
import sonia.scm.repository.GitUtil;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -46,6 +53,11 @@ import java.io.IOException;
|
||||
*/
|
||||
public class AbstractGitCommand
|
||||
{
|
||||
|
||||
/**
|
||||
* the logger for AbstractGitCommand
|
||||
*/
|
||||
private static final Logger logger = LoggerFactory.getLogger(AbstractGitCommand.class);
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
@@ -54,7 +66,6 @@ public class AbstractGitCommand
|
||||
*
|
||||
* @param context
|
||||
* @param repository
|
||||
* @param repositoryDirectory
|
||||
*/
|
||||
protected AbstractGitCommand(GitContext context,
|
||||
sonia.scm.repository.Repository repository)
|
||||
@@ -77,6 +88,38 @@ public class AbstractGitCommand
|
||||
{
|
||||
return context.open();
|
||||
}
|
||||
|
||||
protected ObjectId getCommitOrDefault(Repository gitRepository, String requestedCommit) throws IOException {
|
||||
ObjectId commit;
|
||||
if ( Strings.isNullOrEmpty(requestedCommit) ) {
|
||||
commit = getDefaultBranch(gitRepository);
|
||||
} else {
|
||||
commit = gitRepository.resolve(requestedCommit);
|
||||
}
|
||||
return commit;
|
||||
}
|
||||
|
||||
protected ObjectId getBranchOrDefault(Repository gitRepository, String requestedBranch) throws IOException {
|
||||
ObjectId head;
|
||||
if ( Strings.isNullOrEmpty(requestedBranch) ) {
|
||||
head = getDefaultBranch(gitRepository);
|
||||
} else {
|
||||
head = GitUtil.getBranchId(gitRepository, requestedBranch);
|
||||
}
|
||||
return head;
|
||||
}
|
||||
|
||||
protected ObjectId getDefaultBranch(Repository gitRepository) throws IOException {
|
||||
ObjectId head;
|
||||
String defaultBranchName = repository.getProperty(GitConstants.PROPERTY_DEFAULT_BRANCH);
|
||||
if (!Strings.isNullOrEmpty(defaultBranchName)) {
|
||||
head = GitUtil.getBranchId(gitRepository, defaultBranchName);
|
||||
} else {
|
||||
logger.trace("no default branch configured, use repository head as default");
|
||||
head = GitUtil.getRepositoryHead(gitRepository);
|
||||
}
|
||||
return head;
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -138,7 +138,7 @@ public abstract class AbstractGitIncomingOutgoingCommand
|
||||
|
||||
GitUtil.fetch(git, handler.getDirectory(remoteRepository), remoteRepository);
|
||||
|
||||
ObjectId localId = GitUtil.getRepositoryHead(git.getRepository());
|
||||
ObjectId localId = getDefaultBranch(git.getRepository());
|
||||
ObjectId remoteId = null;
|
||||
|
||||
Ref remoteBranch = getRemoteBranch(git.getRepository(), localId,
|
||||
|
||||
@@ -124,7 +124,7 @@ public class GitBlameCommand extends AbstractGitCommand implements BlameCommand
|
||||
|
||||
blame.setFilePath(request.getPath());
|
||||
|
||||
ObjectId revId = GitUtil.getRevisionId(gr, request.getRevision());
|
||||
ObjectId revId = getCommitOrDefault(gr, request.getRevision());
|
||||
|
||||
blame.setStartCommit(revId);
|
||||
|
||||
|
||||
@@ -45,7 +45,6 @@ import org.eclipse.jgit.lib.ObjectLoader;
|
||||
import org.eclipse.jgit.revwalk.RevCommit;
|
||||
import org.eclipse.jgit.revwalk.RevTree;
|
||||
import org.eclipse.jgit.revwalk.RevWalk;
|
||||
import org.eclipse.jgit.submodule.SubmoduleWalk;
|
||||
import org.eclipse.jgit.treewalk.TreeWalk;
|
||||
import org.eclipse.jgit.treewalk.filter.AndTreeFilter;
|
||||
import org.eclipse.jgit.treewalk.filter.PathFilter;
|
||||
@@ -72,7 +71,6 @@ import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -96,11 +94,8 @@ public class GitBrowseCommand extends AbstractGitCommand
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param context
|
||||
* @param repository
|
||||
* @param repositoryDirectory
|
||||
*/
|
||||
public GitBrowseCommand(GitContext context, Repository repository)
|
||||
{
|
||||
@@ -124,18 +119,15 @@ public class GitBrowseCommand extends AbstractGitCommand
|
||||
public BrowserResult getBrowserResult(BrowseCommandRequest request)
|
||||
throws IOException, RepositoryException
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("try to create browse result for {}", request);
|
||||
}
|
||||
logger.debug("try to create browse result for {}", request);
|
||||
|
||||
BrowserResult result = null;
|
||||
BrowserResult result;
|
||||
org.eclipse.jgit.lib.Repository repo = open();
|
||||
ObjectId revId = null;
|
||||
ObjectId revId;
|
||||
|
||||
if (Util.isEmpty(request.getRevision()))
|
||||
{
|
||||
revId = GitUtil.getRepositoryHead(repo);
|
||||
revId = getDefaultBranch(repo);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -34,6 +34,7 @@ package sonia.scm.repository.spi;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import org.eclipse.jgit.lib.Constants;
|
||||
import org.eclipse.jgit.lib.ObjectId;
|
||||
import org.eclipse.jgit.lib.ObjectLoader;
|
||||
@@ -78,7 +79,6 @@ public class GitCatCommand extends AbstractGitCommand implements CatCommand
|
||||
*
|
||||
* @param context
|
||||
* @param repository
|
||||
* @param repositoryDirectory
|
||||
*/
|
||||
public GitCatCommand(GitContext context,
|
||||
sonia.scm.repository.Repository repository)
|
||||
@@ -102,17 +102,11 @@ public class GitCatCommand extends AbstractGitCommand implements CatCommand
|
||||
public void getCatResult(CatCommandRequest request, OutputStream output)
|
||||
throws IOException, RepositoryException
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("try to read content for {}", request);
|
||||
}
|
||||
|
||||
org.eclipse.jgit.lib.Repository repo = null;
|
||||
|
||||
repo = open();
|
||||
|
||||
ObjectId revId = GitUtil.getRevisionId(repo, request.getRevision());
|
||||
logger.debug("try to read content for {}", request);
|
||||
|
||||
org.eclipse.jgit.lib.Repository repo = open();
|
||||
|
||||
ObjectId revId = getCommitOrDefault(repo, request.getRevision());
|
||||
getContent(repo, revId, request.getPath(), output);
|
||||
}
|
||||
|
||||
|
||||
@@ -79,7 +79,6 @@ public class GitDiffCommand extends AbstractGitCommand implements DiffCommand
|
||||
*
|
||||
* @param context
|
||||
* @param repository
|
||||
* @param repositoryDirectory
|
||||
*/
|
||||
public GitDiffCommand(GitContext context, Repository repository)
|
||||
{
|
||||
|
||||
@@ -220,17 +220,8 @@ public class GitLogCommand extends AbstractGitCommand implements LogCommand
|
||||
AndTreeFilter.create(
|
||||
PathFilter.create(request.getPath()), TreeFilter.ANY_DIFF));
|
||||
}
|
||||
|
||||
ObjectId head = null;
|
||||
|
||||
if (!Strings.isNullOrEmpty(request.getBranch()))
|
||||
{
|
||||
head = GitUtil.getBranchId(gr, request.getBranch());
|
||||
}
|
||||
else
|
||||
{
|
||||
head = GitUtil.getRepositoryHead(gr);
|
||||
}
|
||||
|
||||
ObjectId head = getBranchOrDefault(gr, request.getBranch());
|
||||
|
||||
if (head != null)
|
||||
{
|
||||
|
||||
@@ -90,6 +90,93 @@ Sonia.git.ConfigPanel = Ext.extend(Sonia.config.SimpleConfigForm, {
|
||||
|
||||
Ext.reg("gitConfigPanel", Sonia.git.ConfigPanel);
|
||||
|
||||
// add default branch chooser to settings panel
|
||||
Sonia.git.GitSettingsFormPanel = Ext.extend(Sonia.repository.SettingsFormPanel, {
|
||||
|
||||
defaultBranchText: 'Default Branch',
|
||||
defaultBranchHelpText: 'The default branch which is show first on source or commit view.',
|
||||
|
||||
modifyDefaultConfig: function(config){
|
||||
if (this.item) {
|
||||
var position = -1;
|
||||
for ( var i=0; i<config.items.length; i++ ) {
|
||||
var field = config.items[i];
|
||||
if (field.name === 'public') {
|
||||
position = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var defaultBranchComboxBox = {
|
||||
fieldLabel: this.defaultBranchText,
|
||||
name: 'defaultBranch',
|
||||
repositoryId: this.item.id,
|
||||
value: this.getDefaultBranch(this.item),
|
||||
useNameAsValue: true,
|
||||
xtype: 'repositoryBranchComboBox',
|
||||
helpText: this.defaultBranchHelpText
|
||||
};
|
||||
|
||||
if (position >= 0) {
|
||||
config.items.splice(position, 0, defaultBranchComboxBox);
|
||||
} else {
|
||||
config.items.push(defaultBranchComboxBox);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
getDefaultBranch: function(item){
|
||||
if (item.properties) {
|
||||
for ( var i=0; i<item.properties.length; i++ ) {
|
||||
var prop = item.properties[i];
|
||||
if (prop.key === 'git.default-branch') {
|
||||
return prop.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
|
||||
setDefaultBranch: function(item, defaultBranch){
|
||||
if (!item.properties) {
|
||||
item.properties = [{
|
||||
key: 'git.default-branch',
|
||||
value: defaultBranch
|
||||
}];
|
||||
} else {
|
||||
|
||||
var found = false;
|
||||
for ( var i=0; i<item.properties.length; i++ ) {
|
||||
var prop = item.properties[i];
|
||||
if (prop.key === 'git.default-branch') {
|
||||
prop.value = defaultBranch;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
item.properties.push({
|
||||
key: 'git.default-branch',
|
||||
value: defaultBranch
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
prepareUpdate: function(item) {
|
||||
if (item.defaultBranch) {
|
||||
var defaultBranch = item.defaultBranch;
|
||||
delete item.defaultBranch;
|
||||
this.setDefaultBranch(item, defaultBranch);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
Ext.reg("gitSettingsForm", Sonia.git.GitSettingsFormPanel);
|
||||
|
||||
|
||||
// i18n
|
||||
|
||||
if ( i18n && i18n.country === 'de' ){
|
||||
@@ -107,9 +194,21 @@ if ( i18n && i18n.country === 'de' ){
|
||||
Die Seite muss neu geladen werden wenn dieser Wert geändert wird.'
|
||||
|
||||
});
|
||||
|
||||
Ext.override(Sonia.git.GitSettingsFormPanel, {
|
||||
|
||||
// labels
|
||||
defaultBranchText: 'Standard Branch',
|
||||
|
||||
// helpTexts
|
||||
defaultBranchHelpText: 'Der Standard Branch wird für die Source und Commit Ansicht verwendet, \n\
|
||||
wenn kein anderer Branch eingestellt wurde.'
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
// register information panel
|
||||
|
||||
initCallbacks.push(function(main){
|
||||
@@ -117,6 +216,9 @@ initCallbacks.push(function(main){
|
||||
checkoutTemplate: 'git clone <a href="{0}" target="_blank">{0}</a>',
|
||||
xtype: 'repositoryExtendedInfoPanel'
|
||||
});
|
||||
main.registerSettingsForm('git', {
|
||||
xtype: 'gitSettingsForm'
|
||||
});
|
||||
});
|
||||
|
||||
// register panel
|
||||
|
||||
@@ -0,0 +1,163 @@
|
||||
/**
|
||||
* 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;
|
||||
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Before;
|
||||
import sonia.scm.HandlerEvent;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link GitRepositoryModifyListener}.
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public class GitRepositoryModifyListenerTest {
|
||||
|
||||
private GitRepositoryModifyTestListener repositoryModifyListener;
|
||||
|
||||
/**
|
||||
* Set up test object.
|
||||
*/
|
||||
@Before
|
||||
public void setUpObjectUnderTest(){
|
||||
repositoryModifyListener = new GitRepositoryModifyTestListener();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests happy path.
|
||||
*/
|
||||
@Test
|
||||
public void testHandleEvent() {
|
||||
Repository old = RepositoryTestData.createHeartOfGold("git");
|
||||
old.setProperty(GitConstants.PROPERTY_DEFAULT_BRANCH, "master");
|
||||
Repository current = RepositoryTestData.createHeartOfGold("git");
|
||||
current.setProperty(GitConstants.PROPERTY_DEFAULT_BRANCH, "develop");
|
||||
|
||||
RepositoryModificationEvent event = new RepositoryModificationEvent(current, old, HandlerEvent.MODIFY);
|
||||
repositoryModifyListener.handleEvent(event);
|
||||
|
||||
assertNotNull(repositoryModifyListener.repository);
|
||||
assertSame(current, repositoryModifyListener.repository);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests with new default branch.
|
||||
*/
|
||||
@Test
|
||||
public void testWithNewDefaultBranch() {
|
||||
Repository old = RepositoryTestData.createHeartOfGold("git");
|
||||
Repository current = RepositoryTestData.createHeartOfGold("git");
|
||||
current.setProperty(GitConstants.PROPERTY_DEFAULT_BRANCH, "develop");
|
||||
|
||||
RepositoryModificationEvent event = new RepositoryModificationEvent(current, old, HandlerEvent.MODIFY);
|
||||
repositoryModifyListener.handleEvent(event);
|
||||
|
||||
assertNotNull(repositoryModifyListener.repository);
|
||||
assertSame(current, repositoryModifyListener.repository);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests with non git repositories.
|
||||
*/
|
||||
@Test
|
||||
public void testNonGitRepository(){
|
||||
Repository old = RepositoryTestData.createHeartOfGold("hg");
|
||||
old.setProperty(GitConstants.PROPERTY_DEFAULT_BRANCH, "master");
|
||||
Repository current = RepositoryTestData.createHeartOfGold("hg");
|
||||
current.setProperty(GitConstants.PROPERTY_DEFAULT_BRANCH, "develop");
|
||||
|
||||
RepositoryModificationEvent event = new RepositoryModificationEvent(current, old, HandlerEvent.MODIFY);
|
||||
repositoryModifyListener.handleEvent(event);
|
||||
|
||||
assertNull(repositoryModifyListener.repository);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests without default branch.
|
||||
*/
|
||||
@Test
|
||||
public void testWithoutDefaultBranch(){
|
||||
Repository old = RepositoryTestData.createHeartOfGold("git");
|
||||
Repository current = RepositoryTestData.createHeartOfGold("git");
|
||||
|
||||
RepositoryModificationEvent event = new RepositoryModificationEvent(current, old, HandlerEvent.MODIFY);
|
||||
repositoryModifyListener.handleEvent(event);
|
||||
|
||||
assertNull(repositoryModifyListener.repository);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests with non modify event.
|
||||
*/
|
||||
@Test
|
||||
public void testNonModifyEvent(){
|
||||
Repository old = RepositoryTestData.createHeartOfGold("git");
|
||||
old.setProperty(GitConstants.PROPERTY_DEFAULT_BRANCH, "master");
|
||||
Repository current = RepositoryTestData.createHeartOfGold("git");
|
||||
current.setProperty(GitConstants.PROPERTY_DEFAULT_BRANCH, "develop");
|
||||
|
||||
RepositoryModificationEvent event = new RepositoryModificationEvent(current, old, HandlerEvent.CREATE);
|
||||
repositoryModifyListener.handleEvent(event);
|
||||
|
||||
assertNull(repositoryModifyListener.repository);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests with non git repositories.
|
||||
*/
|
||||
@Test
|
||||
public void testNoModification(){
|
||||
Repository old = RepositoryTestData.createHeartOfGold("git");
|
||||
old.setProperty(GitConstants.PROPERTY_DEFAULT_BRANCH, "master");
|
||||
Repository current = RepositoryTestData.createHeartOfGold("git");
|
||||
current.setProperty(GitConstants.PROPERTY_DEFAULT_BRANCH, "master");
|
||||
|
||||
RepositoryModificationEvent event = new RepositoryModificationEvent(current, old, HandlerEvent.MODIFY);
|
||||
repositoryModifyListener.handleEvent(event);
|
||||
|
||||
assertNull(repositoryModifyListener.repository);
|
||||
}
|
||||
|
||||
private static class GitRepositoryModifyTestListener extends GitRepositoryModifyListener {
|
||||
|
||||
private Repository repository;
|
||||
|
||||
@Override
|
||||
protected void sendClearRepositoryCacheEvent(Repository repository) {
|
||||
this.repository = repository;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -45,14 +45,42 @@ import static org.junit.Assert.*;
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.io.IOException;
|
||||
import sonia.scm.repository.GitConstants;
|
||||
|
||||
/**
|
||||
*
|
||||
* Unit tests for {@link GitBlameCommand}.
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public class GitBlameCommandTest extends AbstractGitCommandTestBase
|
||||
{
|
||||
|
||||
/**
|
||||
* Tests blame command with default branch.
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws RepositoryException
|
||||
*/
|
||||
@Test
|
||||
public void testDefaultBranch() throws IOException, RepositoryException {
|
||||
// without default branch, the repository head should be used
|
||||
BlameCommandRequest request = new BlameCommandRequest();
|
||||
request.setPath("a.txt");
|
||||
|
||||
BlameResult result = createCommand().getBlameResult(request);
|
||||
assertNotNull(result);
|
||||
assertEquals(2, result.getTotal());
|
||||
assertEquals("435df2f061add3589cb326cc64be9b9c3897ceca", result.getLine(0).getRevision());
|
||||
assertEquals("fcd0ef1831e4002ac43ea539f4094334c79ea9ec", result.getLine(1).getRevision());
|
||||
|
||||
// set default branch and test again
|
||||
repository.setProperty(GitConstants.PROPERTY_DEFAULT_BRANCH, "test-branch");
|
||||
result = createCommand().getBlameResult(request);
|
||||
assertNotNull(result);
|
||||
assertEquals(1, result.getTotal());
|
||||
assertEquals("3f76a12f08a6ba0dc988c68b7f0b2cd190efc3c4", result.getLine(0).getRevision());
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
|
||||
@@ -48,13 +48,51 @@ import static org.junit.Assert.*;
|
||||
import java.io.IOException;
|
||||
|
||||
import java.util.List;
|
||||
import sonia.scm.repository.GitConstants;
|
||||
|
||||
/**
|
||||
*
|
||||
* Unit tests for {@link GitBrowseCommand}.
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public class GitBrowseCommandTest extends AbstractGitCommandTestBase
|
||||
{
|
||||
|
||||
/**
|
||||
* Test browse command with default branch.
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws RepositoryException
|
||||
*/
|
||||
@Test
|
||||
public void testDefaultBranch() throws IOException, RepositoryException {
|
||||
// without default branch, the repository head should be used
|
||||
BrowserResult result = createCommand().getBrowserResult(new BrowseCommandRequest());
|
||||
assertNotNull(result);
|
||||
|
||||
List<FileObject> foList = result.getFiles();
|
||||
assertNotNull(foList);
|
||||
assertFalse(foList.isEmpty());
|
||||
assertEquals(4, foList.size());
|
||||
|
||||
assertEquals("a.txt", foList.get(0).getName());
|
||||
assertEquals("b.txt", foList.get(1).getName());
|
||||
assertEquals("c", foList.get(2).getName());
|
||||
assertEquals("f.txt", foList.get(3).getName());
|
||||
|
||||
// set default branch and fetch again
|
||||
repository.setProperty(GitConstants.PROPERTY_DEFAULT_BRANCH, "test-branch");
|
||||
result = createCommand().getBrowserResult(new BrowseCommandRequest());
|
||||
assertNotNull(result);
|
||||
|
||||
foList = result.getFiles();
|
||||
assertNotNull(foList);
|
||||
assertFalse(foList.isEmpty());
|
||||
assertEquals(2, foList.size());
|
||||
|
||||
assertEquals("a.txt", foList.get(0).getName());
|
||||
assertEquals("c", foList.get(1).getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
|
||||
@@ -44,14 +44,36 @@ import static org.junit.Assert.*;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import sonia.scm.repository.GitConstants;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link GitCatCommand}.
|
||||
*
|
||||
* TODO add not found test
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public class GitCatCommandTest extends AbstractGitCommandTestBase
|
||||
{
|
||||
|
||||
/**
|
||||
* Tests cat command with default branch.
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws RepositoryException
|
||||
*/
|
||||
@Test
|
||||
public void testDefaultBranch() throws IOException, RepositoryException {
|
||||
// without default branch, the repository head should be used
|
||||
CatCommandRequest request = new CatCommandRequest();
|
||||
request.setPath("a.txt");
|
||||
|
||||
assertEquals("a\nline for blame", execute(request));
|
||||
|
||||
// set default branch for repository and check again
|
||||
repository.setProperty(GitConstants.PROPERTY_DEFAULT_BRANCH, "test-branch");
|
||||
assertEquals("a and b", execute(request));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
|
||||
@@ -49,14 +49,48 @@ import static org.junit.Assert.*;
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.io.IOException;
|
||||
import org.eclipse.jgit.api.errors.GitAPIException;
|
||||
import sonia.scm.repository.GitConstants;
|
||||
|
||||
/**
|
||||
*
|
||||
* Unit tests for {@link GitLogCommand}.
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public class GitLogCommandTest extends AbstractGitCommandTestBase
|
||||
{
|
||||
|
||||
/**
|
||||
* Tests log command with the usage of a default branch.
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws GitAPIException
|
||||
* @throws RepositoryException
|
||||
*/
|
||||
@Test
|
||||
public void testGetDefaultBranch() throws IOException, GitAPIException, RepositoryException {
|
||||
// without default branch, the repository head should be used
|
||||
ChangesetPagingResult result = createCommand().getChangesets(new LogCommandRequest());
|
||||
|
||||
assertNotNull(result);
|
||||
assertEquals(4, result.getTotal());
|
||||
assertEquals("fcd0ef1831e4002ac43ea539f4094334c79ea9ec", result.getChangesets().get(0).getId());
|
||||
assertEquals("86a6645eceefe8b9a247db5eb16e3d89a7e6e6d1", result.getChangesets().get(1).getId());
|
||||
assertEquals("592d797cd36432e591416e8b2b98154f4f163411", result.getChangesets().get(2).getId());
|
||||
assertEquals("435df2f061add3589cb326cc64be9b9c3897ceca", result.getChangesets().get(3).getId());
|
||||
|
||||
// set default branch and fetch again
|
||||
repository.setProperty(GitConstants.PROPERTY_DEFAULT_BRANCH, "test-branch");
|
||||
|
||||
result = createCommand().getChangesets(new LogCommandRequest());
|
||||
|
||||
assertNotNull(result);
|
||||
assertEquals(3, result.getTotal());
|
||||
assertEquals("3f76a12f08a6ba0dc988c68b7f0b2cd190efc3c4", result.getChangesets().get(0).getId());
|
||||
assertEquals("592d797cd36432e591416e8b2b98154f4f163411", result.getChangesets().get(1).getId());
|
||||
assertEquals("435df2f061add3589cb326cc64be9b9c3897ceca", result.getChangesets().get(2).getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
|
||||
@@ -51,7 +51,8 @@ import static org.junit.Assert.assertNotNull;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
*
|
||||
* Unit tests for {@link OutgoingCommand}.
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public class GitOutgoingCommandTest extends AbstractRemoteCommandTestBase
|
||||
|
||||
@@ -115,6 +115,8 @@
|
||||
|
||||
<!-- sonia.repository -->
|
||||
<script type="text/javascript" src="resources/js/repository/sonia.repository.js"></script>
|
||||
<script type="text/javascript" src="resources/js/repository/sonia.repository.branchcombobox.js"></script>
|
||||
<script type="text/javascript" src="resources/js/repository/sonia.repository.tagcombobox.js"></script>
|
||||
<script type="text/javascript" src="resources/js/repository/sonia.repository.grid.js"></script>
|
||||
<script type="text/javascript" src="resources/js/repository/sonia.repository.infopanel.js"></script>
|
||||
<script type="text/javascript" src="resources/js/repository/sonia.repository.extendedinfopanel.js"></script>
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
/* *
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
Sonia.repository.BranchComboBox = Ext.extend(Ext.form.ComboBox, {
|
||||
|
||||
repositoryId: null,
|
||||
useNameAsValue: false,
|
||||
|
||||
initComponent: function(){
|
||||
var branchStore = new Sonia.rest.JsonStore({
|
||||
proxy: new Ext.data.HttpProxy({
|
||||
url: restUrl + 'repositories/' + this.repositoryId + '/branches.json',
|
||||
method: 'GET',
|
||||
disableCaching: false
|
||||
}),
|
||||
root: 'branch',
|
||||
idProperty: 'name',
|
||||
fields: ['name', 'revision']
|
||||
});
|
||||
|
||||
var config = {
|
||||
displayField: 'name',
|
||||
valueField: this.useNameAsValue ? 'name' : 'revision',
|
||||
typeAhead: false,
|
||||
editable: false,
|
||||
triggerAction: 'all',
|
||||
store: branchStore
|
||||
};
|
||||
|
||||
Ext.apply(this, Ext.apply(this.initialConfig, config));
|
||||
Sonia.repository.BranchComboBox.superclass.initComponent.apply(this, arguments);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
// register xtype
|
||||
Ext.reg('repositoryBranchComboBox', Sonia.repository.BranchComboBox);
|
||||
@@ -120,33 +120,14 @@ Sonia.repository.ChangesetViewerPanel = Ext.extend(Ext.Panel, {
|
||||
},
|
||||
|
||||
createTopToolbar: function(){
|
||||
var branchStore = new Sonia.rest.JsonStore({
|
||||
proxy: new Ext.data.HttpProxy({
|
||||
url: restUrl + 'repositories/' + this.repository.id + '/branches.json',
|
||||
method: 'GET',
|
||||
disableCaching: false
|
||||
}),
|
||||
root: 'branch',
|
||||
idProperty: 'name',
|
||||
fields: [ 'name' ],
|
||||
sortInfo: {
|
||||
field: 'name'
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
xtype: 'toolbar',
|
||||
items: [
|
||||
this.repository.name,
|
||||
'->',
|
||||
'Branches:', ' ',{
|
||||
xtype: 'combo',
|
||||
valueField: 'name',
|
||||
displayField: 'name',
|
||||
typeAhead: false,
|
||||
editable: false,
|
||||
triggerAction: 'all',
|
||||
store: branchStore,
|
||||
xtype: 'repositoryBranchComboBox',
|
||||
repositoryId: this.repository.id,
|
||||
listeners: {
|
||||
select: {
|
||||
fn: this.selectBranch,
|
||||
|
||||
@@ -61,8 +61,15 @@ Sonia.repository.FormPanel = Ext.extend(Sonia.rest.FormPanel,{
|
||||
Sonia.repository.FormPanel.superclass.initComponent.apply(this, arguments);
|
||||
},
|
||||
|
||||
prepareUpdate: function(item) {
|
||||
|
||||
},
|
||||
|
||||
update: function(item){
|
||||
item = Ext.apply( this.item, item );
|
||||
// allow plugins to modify item
|
||||
this.prepareUpdate(item);
|
||||
|
||||
if ( debug ){
|
||||
console.debug( 'update repository: ' + item.name );
|
||||
}
|
||||
|
||||
@@ -432,21 +432,22 @@ Sonia.repository.Grid = Ext.extend(Sonia.rest.Grid, {
|
||||
var infoPanel = main.getInfoPanel(item.type);
|
||||
infoPanel.item = item;
|
||||
|
||||
var settingsForm = main.getSettingsForm(item.type);
|
||||
settingsForm.item = item;
|
||||
settingsForm.onUpdate = {
|
||||
fn: this.reload,
|
||||
scope: this
|
||||
};
|
||||
settingsForm.onCreate = {
|
||||
fn: this.reload,
|
||||
scope: this
|
||||
};
|
||||
|
||||
var panels = [infoPanel];
|
||||
|
||||
if ( owner ){
|
||||
panels.push({
|
||||
item: item,
|
||||
xtype: 'repositorySettingsForm',
|
||||
onUpdate: {
|
||||
fn: this.reload,
|
||||
scope: this
|
||||
},
|
||||
onCreate: {
|
||||
fn: this.reload,
|
||||
scope: this
|
||||
}
|
||||
},{
|
||||
panels.push(
|
||||
settingsForm, {
|
||||
item: item,
|
||||
xtype: 'repositoryPermissionsForm',
|
||||
listeners: {
|
||||
|
||||
@@ -159,26 +159,10 @@ Sonia.repository.RepositoryBrowser = Ext.extend(Ext.grid.GridPanel, {
|
||||
|
||||
branches = true;
|
||||
|
||||
var branchStore = new Sonia.rest.JsonStore({
|
||||
proxy: new Ext.data.HttpProxy({
|
||||
url: restUrl + 'repositories/' + this.repository.id + '/branches.json',
|
||||
method: 'GET',
|
||||
disableCaching: false
|
||||
}),
|
||||
root: 'branch',
|
||||
idProperty: 'name',
|
||||
fields: [ 'name', 'revision' ]
|
||||
});
|
||||
|
||||
items.push('->','Branches:', ' ',{
|
||||
id: 'branchComboBox',
|
||||
xtype: 'combo',
|
||||
valueField: 'revision',
|
||||
displayField: 'name',
|
||||
typeAhead: false,
|
||||
editable: false,
|
||||
triggerAction: 'all',
|
||||
store: branchStore,
|
||||
xtype: 'repositoryBranchComboBox',
|
||||
repositoryId: this.repository.id,
|
||||
listeners: {
|
||||
select: {
|
||||
fn: this.selectBranch,
|
||||
@@ -191,17 +175,6 @@ Sonia.repository.RepositoryBrowser = Ext.extend(Ext.grid.GridPanel, {
|
||||
|
||||
if ( type && type.supportedCommands && type.supportedCommands.indexOf('TAGS') >= 0){
|
||||
|
||||
var tagStore = new Sonia.rest.JsonStore({
|
||||
proxy: new Ext.data.HttpProxy({
|
||||
url: restUrl + 'repositories/' + this.repository.id + '/tags.json',
|
||||
method: 'GET',
|
||||
disableCaching: false
|
||||
}),
|
||||
root: 'tag',
|
||||
idProperty: 'name',
|
||||
fields: [ 'name', 'revision' ]
|
||||
});
|
||||
|
||||
if (branches){
|
||||
items.push(' ');
|
||||
} else {
|
||||
@@ -210,13 +183,8 @@ Sonia.repository.RepositoryBrowser = Ext.extend(Ext.grid.GridPanel, {
|
||||
|
||||
items.push('Tags:', ' ',{
|
||||
id: 'tagComboBox',
|
||||
xtype: 'combo',
|
||||
valueField: 'revision',
|
||||
displayField: 'name',
|
||||
typeAhead: false,
|
||||
editable: false,
|
||||
triggerAction: 'all',
|
||||
store: tagStore,
|
||||
xtype: 'repositoryTagComboBox',
|
||||
repositoryId: this.repository.id,
|
||||
listeners: {
|
||||
select: {
|
||||
fn: this.selectTag,
|
||||
|
||||
@@ -78,9 +78,15 @@ Sonia.repository.SettingsFormPanel = Ext.extend(Sonia.repository.FormPanel, {
|
||||
helpText: this.publicHelpText
|
||||
}]
|
||||
};
|
||||
|
||||
this.modifyDefaultConfig(config);
|
||||
|
||||
Ext.apply(this, Ext.apply(this.initialConfig, config));
|
||||
Sonia.repository.SettingsFormPanel.superclass.initComponent.apply(this, arguments);
|
||||
},
|
||||
|
||||
modifyDefaultConfig: function(config){
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
/* *
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
Sonia.repository.TagComboBox = Ext.extend(Ext.form.ComboBox, {
|
||||
|
||||
repositoryId: null,
|
||||
|
||||
initComponent: function(){
|
||||
var tagStore = new Sonia.rest.JsonStore({
|
||||
proxy: new Ext.data.HttpProxy({
|
||||
url: restUrl + 'repositories/' + this.repositoryId + '/tags.json',
|
||||
method: 'GET',
|
||||
disableCaching: false
|
||||
}),
|
||||
root: 'tag',
|
||||
idProperty: 'name',
|
||||
fields: [ 'name', 'revision' ]
|
||||
});
|
||||
|
||||
var config = {
|
||||
valueField: 'revision',
|
||||
displayField: 'name',
|
||||
typeAhead: false,
|
||||
editable: false,
|
||||
triggerAction: 'all',
|
||||
store: tagStore
|
||||
};
|
||||
|
||||
Ext.apply(this, Ext.apply(this.initialConfig, config));
|
||||
Sonia.repository.TagComboBox.superclass.initComponent.apply(this, arguments);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
// register xtype
|
||||
Ext.reg('repositoryTagComboBox', Sonia.repository.TagComboBox);
|
||||
@@ -78,6 +78,7 @@ Sonia.scm.Main = Ext.extend(Ext.util.Observable, {
|
||||
mainTabPanel: null,
|
||||
|
||||
infoPanels: [],
|
||||
settingsForm: [],
|
||||
scripts: [],
|
||||
stylesheets: [],
|
||||
|
||||
@@ -96,6 +97,23 @@ Sonia.scm.Main = Ext.extend(Ext.util.Observable, {
|
||||
this.infoPanels[type] = panel;
|
||||
},
|
||||
|
||||
registerSettingsForm: function(type, form){
|
||||
this.settingsForm[type] = form;
|
||||
},
|
||||
|
||||
getSettingsForm: function(type){
|
||||
var rp = null;
|
||||
var panel = this.settingsForm[type];
|
||||
if ( ! panel ){
|
||||
rp = {
|
||||
xtype: 'repositorySettingsForm'
|
||||
};
|
||||
} else {
|
||||
rp = Sonia.util.clone( panel );
|
||||
}
|
||||
return rp;
|
||||
},
|
||||
|
||||
getInfoPanel: function(type){
|
||||
var rp = null;
|
||||
var panel = this.infoPanels[type];
|
||||
|
||||
Reference in New Issue
Block a user