mirror of
https://github.com/jenkinsci/jenkins.git
synced 2026-11-05 08:05:56 +00:00
only deactivate plugins with cycle dependencies instead of failing to launch Jenkins
This commit is contained in:
1 parent
d0c9ee6588
commit
aad6e4c66c
3 files changed
+68
-3
No files matched your search
@@ -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;
|
||||
|
||||
Reference in new issue
Block a user