From 4a75e058bafd3cd98832a2a129c9f23c71d26f55 Mon Sep 17 00:00:00 2001 From: Jesse Glick Date: Tue, 27 Jan 2015 16:09:48 -0500 Subject: [PATCH] [JENKINS-26519] Attempting to improve diagnostics in case rename fails. (cherry picked from commit 0633beef0868c59a7e853731aee5f5c0745fa3fc) --- .../java/jenkins/model/RunIdMigrator.java | 51 +++++++++++++++---- .../java/jenkins/model/RunIdMigratorTest.java | 14 +++++ 2 files changed, 56 insertions(+), 9 deletions(-) diff --git a/core/src/main/java/jenkins/model/RunIdMigrator.java b/core/src/main/java/jenkins/model/RunIdMigrator.java index 7d375c79a5..a8b97f16e5 100644 --- a/core/src/main/java/jenkins/model/RunIdMigrator.java +++ b/core/src/main/java/jenkins/model/RunIdMigrator.java @@ -34,6 +34,9 @@ import hudson.util.StreamTaskListener; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; +import java.lang.reflect.Array; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.net.URISyntaxException; import java.net.URL; import java.text.DateFormat; @@ -206,11 +209,8 @@ public final class RunIdMigrator { } try { Integer.parseInt(name); - if (kid.delete()) { - LOGGER.log(FINE, "deleted build number symlink {0} → {1}", new Object[] {name, link}); - } else { - LOGGER.log(WARNING, "could not delete build number symlink {0} → {1}", new Object[] {name, link}); - } + LOGGER.log(FINE, "deleting build number symlink {0} → {1}", new Object[] {name, link}); + Util.deleteFile(kid); } catch (NumberFormatException x) { LOGGER.log(FINE, "skipping other symlink {0} → {1}", new Object[] {name, link}); } @@ -259,10 +259,7 @@ public final class RunIdMigrator { String nl = m.group(2); xml = m.replaceFirst(" " + name + "" + nl + " " + timestamp + "" + nl); File newKid = new File(dir, Integer.toString(number)); - if (!kid.renameTo(newKid)) { - LOGGER.log(WARNING, "failed to rename {0} to {1}", new Object[] {name, number}); - continue; - } + move(kid, newKid); FileUtils.writeStringToFile(new File(newKid, "build.xml"), xml, Charsets.UTF_8); LOGGER.log(FINE, "fully processed {0} → {1}", new Object[] {name, number}); idToNumber.put(name, number); @@ -272,6 +269,42 @@ public final class RunIdMigrator { } } + /** + * Tries to move/rename a file from one path to another. + * Uses {@link java.nio.file.Files#move} when available. + * Does not use {@link java.nio.file.StandardCopyOption#REPLACE_EXISTING} or any other options. + * TODO candidate for moving to {@link Util} + */ + static void move(File src, File dest) throws IOException { + Class pathC; + try { + pathC = Class.forName("java.nio.file.Path"); + } catch (ClassNotFoundException x) { + // Java 6, do our best + if (dest.exists()) { + throw new IOException(dest + " already exists"); + } + if (src.renameTo(dest)) { + return; + } + throw new IOException("could not move " + src + " to " + dest); + } + try { + Method toPath = File.class.getMethod("toPath"); + Class copyOptionAC = Class.forName("[Ljava.nio.file.CopyOption;"); + Class.forName("java.nio.file.Files").getMethod("move", pathC, pathC, copyOptionAC).invoke(null, toPath.invoke(src), toPath.invoke(dest), Array.newInstance(copyOptionAC.getComponentType(), 0)); + } catch (InvocationTargetException x) { + Throwable cause = x.getCause(); + if (cause instanceof IOException) { + throw (IOException) cause; + } else { + throw new IOException(cause); + } + } catch (Exception x) { + throw new IOException(x); + } + } + /** * Look up a historical run by ID. * @param id a nonnumeric ID which may be a valid {@link Run#getId} diff --git a/core/src/test/java/jenkins/model/RunIdMigratorTest.java b/core/src/test/java/jenkins/model/RunIdMigratorTest.java index 2d4d784968..ce5c6d89e6 100644 --- a/core/src/test/java/jenkins/model/RunIdMigratorTest.java +++ b/core/src/test/java/jenkins/model/RunIdMigratorTest.java @@ -27,6 +27,7 @@ package jenkins.model; import hudson.Util; import hudson.util.StreamTaskListener; import java.io.File; +import java.io.IOException; import java.nio.charset.Charset; import java.util.Map; import java.util.TimeZone; @@ -173,4 +174,17 @@ public class RunIdMigratorTest { return m.toString(); } + @Test public void move() throws Exception { + File src = tmp.newFile(); + File dest = new File(tmp.getRoot(), "dest"); + RunIdMigrator.move(src, dest); + File dest2 = tmp.newFile(); + try { + RunIdMigrator.move(dest, dest2); + fail(); + } catch (IOException x) { + System.err.println("Got expected move exception: " + x); + } + } + }