diff --git a/changelog.html b/changelog.html
index c627c3c668..db720d8bf4 100644
--- a/changelog.html
+++ b/changelog.html
@@ -94,6 +94,9 @@ Upcoming changes
+ handle job move when buildDir is configured to a custom location.
+ (issue 24825)
diff --git a/core/src/main/java/hudson/model/AbstractItem.java b/core/src/main/java/hudson/model/AbstractItem.java
index 6c670da4c0..ff7c51ffc9 100644
--- a/core/src/main/java/hudson/model/AbstractItem.java
+++ b/core/src/main/java/hudson/model/AbstractItem.java
@@ -42,6 +42,7 @@ import hudson.util.AlternativeUiTextProvider;
import hudson.util.AlternativeUiTextProvider.Message;
import hudson.util.AtomicFileWriter;
import hudson.util.IOUtils;
+import jenkins.model.DirectlyModifiableTopLevelItemGroup;
import jenkins.model.Jenkins;
import org.apache.tools.ant.taskdefs.Copy;
import org.apache.tools.ant.types.FileSet;
@@ -312,6 +313,20 @@ public abstract class AbstractItem extends Actionable implements Item, HttpDelet
}
}
+
+ /**
+ * Notify this item it's been moved to another location, replaced by newItem (might be the same object, but not guaranteed).
+ * This method is executed after the item root directory has been moved to it's new location.
+ *
+ * Derived classes can override this method to add some specific behavior on move, but have to call parent method
+ * so the item is actually setup within it's new parent.
+ *
+ * @see hudson.model.Items#move(AbstractItem, jenkins.model.DirectlyModifiableTopLevelItemGroup)
+ */
+ public void movedTo(DirectlyModifiableTopLevelItemGroup destination, AbstractItem newItem, File destDir) throws IOException {
+ newItem.onLoad(destination, name);
+ }
+
/**
* Gets all the jobs that this {@link Item} contains as descendants.
*/
@@ -696,4 +711,5 @@ public abstract class AbstractItem extends Actionable implements Item, HttpDelet
* Replaceable pronoun of that points to a job. Defaults to "Job"/"Project" depending on the context.
*/
public static final Message PRONOUN = new Message();
+
}
diff --git a/core/src/main/java/hudson/model/Items.java b/core/src/main/java/hudson/model/Items.java
index ca8b54fb77..0358e4471a 100644
--- a/core/src/main/java/hudson/model/Items.java
+++ b/core/src/main/java/hudson/model/Items.java
@@ -381,7 +381,7 @@ public class Items {
FileUtils.moveDirectory(item.getRootDir(), destDir);
oldParent.remove(item);
I newItem = destination.add(item, name);
- newItem.onLoad(destination, name);
+ item.movedTo(destination, newItem, destDir);
ItemListener.fireLocationChange(newItem, oldFullName);
return newItem;
}
diff --git a/core/src/main/java/hudson/model/Job.java b/core/src/main/java/hudson/model/Job.java
index e7aebb77d2..b3e05c6888 100644
--- a/core/src/main/java/hudson/model/Job.java
+++ b/core/src/main/java/hudson/model/Job.java
@@ -63,6 +63,7 @@ import hudson.widgets.HistoryWidget;
import hudson.widgets.HistoryWidget.Adapter;
import hudson.widgets.Widget;
import jenkins.model.BuildDiscarder;
+import jenkins.model.DirectlyModifiableTopLevelItemGroup;
import jenkins.model.Jenkins;
import jenkins.model.ProjectNamingStrategy;
import jenkins.security.HexStringConfidentialKey;
@@ -70,6 +71,7 @@ import jenkins.util.io.OnMaster;
import net.sf.json.JSONException;
import net.sf.json.JSONObject;
+import org.apache.commons.io.FileUtils;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.CategoryAxis;
@@ -628,6 +630,18 @@ public abstract class Job, RunT extends RunasList(sub2a, sub2ap, sub2alpha, sub2b, sub2bp, sub2BRAVO, sub2c, sub2cp, sub2charlie), Items.getAllItems(sub2, Item.class));
}
+ @Issue("JENKINS-24825")
+ @Test public void moveItem() throws Exception {
+ File tmp = Util.createTempDir();
+ r.jenkins.setRawBuildsDir(tmp.getAbsolutePath()+"/${ITEM_FULL_NAME}");
+ MockFolder foo = r.createFolder("foo");
+ MockFolder bar = r.createFolder("bar");
+ FreeStyleProject test = foo.createProject(FreeStyleProject.class, "test");
+ test.scheduleBuild2(0).get();
+ Items.move(test, bar);
+ assertFalse(new File(tmp, "foo/test/1").exists());
+ assertTrue(new File(tmp, "bar/test/1").exists());
+ }
+
}