提交 aad6e4c6 编写于 作者: I imod

only deactivate plugins with cycle dependencies instead of failing to launch Jenkins

上级 d0c9ee65
......@@ -28,10 +28,12 @@ import hudson.init.InitMilestone;
import hudson.init.InitStrategy;
import hudson.init.InitializerFinder;
import hudson.model.AbstractModelObject;
import hudson.model.AdministrativeMonitor;
import hudson.model.Descriptor;
import hudson.model.Failure;
import hudson.model.UpdateCenter;
import hudson.model.UpdateSite;
import hudson.model.UpdateSite.Data;
import hudson.util.CyclicGraphDetector;
import hudson.util.CyclicGraphDetector.CycleDetectedException;
import hudson.util.FormValidation;
......@@ -243,6 +245,18 @@ public abstract class PluginManager extends AbstractModelObject {
r.add(p);
}
}
@Override
protected void reactOnCycle(PluginWrapper q, List<PluginWrapper> cycle)
throws hudson.util.CyclicGraphDetector.CycleDetectedException {
LOGGER.log(Level.SEVERE, "found cycle in plugin dependencies: (root="+q+", deactivating all involved) "+Util.join(cycle," -> "));
for (PluginWrapper pluginWrapper : cycle) {
pluginWrapper.setHasCycleDependency(true);
failedPlugins.add(new FailedPlugin(pluginWrapper.getShortName(), new CycleDetectedException(cycle)));
}
}
};
cgd.run(getPlugins());
......@@ -810,4 +824,32 @@ public abstract class PluginManager extends AbstractModelObject {
/*package*/ static final class PluginInstanceStore {
final Map<PluginWrapper,Plugin> store = new Hashtable<PluginWrapper,Plugin>();
}
/**
* {@link AdministrativeMonitor} that checks if there's Jenkins update.
*/
@Extension
public static final class PluginCycleDependenciesMonitor extends AdministrativeMonitor {
private transient volatile boolean isActive = false;
private transient volatile List<String> pluginsWithCycle;
public boolean isActivated() {
if(pluginsWithCycle == null){
pluginsWithCycle = new ArrayList<String>();
for (PluginWrapper p : Jenkins.getInstance().getPluginManager().getPlugins()) {
if(p.hasCycleDependency()){
pluginsWithCycle.add(p.getShortName());
isActive = true;
}
}
}
return true;
}
public List<String> getPluginsWithCycle() {
return pluginsWithCycle;
}
}
}
......@@ -125,6 +125,8 @@ public class PluginWrapper implements Comparable<PluginWrapper> {
* The snapshot of <tt>disableFile.exists()</tt> as of the start up.
*/
private final boolean active;
private boolean hasCycleDependency = false;
private final List<Dependency> dependencies;
private final List<Dependency> optionalDependencies;
......@@ -276,6 +278,8 @@ public class PluginWrapper implements Comparable<PluginWrapper> {
return null;
}
@Override
public String toString() {
......@@ -379,9 +383,17 @@ public class PluginWrapper implements Comparable<PluginWrapper> {
* Returns true if this plugin is enabled for this session.
*/
public boolean isActive() {
return active;
return active && !hasCycleDependency();
}
public boolean hasCycleDependency(){
return hasCycleDependency;
}
public void setHasCycleDependency(boolean hasCycle){
hasCycleDependency = hasCycle;
}
public boolean isBundled() {
return isBundled;
}
......
......@@ -23,8 +23,9 @@ public abstract class CyclicGraphDetector<N> {
private final List<N> topologicalOrder = new ArrayList<N>();
public void run(Iterable<? extends N> allNodes) throws CycleDetectedException {
for (N n : allNodes)
for (N n : allNodes){
visit(n);
}
}
/**
......@@ -62,8 +63,18 @@ public abstract class CyclicGraphDetector<N> {
private void detectedCycle(N q) throws CycleDetectedException {
int i = path.indexOf(q);
path.push(q);
throw new CycleDetectedException(path.subList(i, path.size()));
reactOnCycle(q, path.subList(i, path.size()));
}
/**
* React on detected cycles - default implementation throws an exception.
* @param q
* @param cycle
* @throws CycleDetectedException
*/
protected void reactOnCycle(N q, List<N> cycle) throws CycleDetectedException{
throw new CycleDetectedException(cycle);
}
public static final class CycleDetectedException extends Exception {
public final List cycle;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册