private void doMigrate()

in core/src/main/java/jenkins/model/RunIdMigrator.java [192:270]


    private void doMigrate(File dir) {
        idToNumber = new TreeMap<>();
        File[] kids = dir.listFiles();
        // Need to process symlinks first so we can rename to them.
        List<File> kidsList = new ArrayList<>(Arrays.asList(kids));
        Iterator<File> it = kidsList.iterator();
        while (it.hasNext()) {
            File kid = it.next();
            String name = kid.getName();
            try {
                Integer.parseInt(name);
            } catch (NumberFormatException x) {
                LOGGER.log(FINE, "ignoring nonnumeric entry {0}", name);
                continue;
            }
            try {
                if (Util.isSymlink(kid)) {
                    LOGGER.log(FINE, "deleting build number symlink {0} → {1}", new Object[] {name, Util.resolveSymlink(kid)});
                } else if (kid.isDirectory()) {
                    LOGGER.log(FINE, "ignoring build directory {0}", name);
                    continue;
                } else {
                    LOGGER.log(WARNING, "need to delete anomalous file entry {0}", name);
                }
                Util.deleteFile(kid);
                it.remove();
            } catch (Exception x) {
                LOGGER.log(WARNING, "failed to process " + kid, x);
            }
        }
        it = kidsList.iterator();
        while (it.hasNext()) {
            File kid = it.next();
            try {
                String name = kid.getName();
                try {
                    Integer.parseInt(name);
                    LOGGER.log(FINE, "skipping new build dir {0}", name);
                    continue;
                } catch (NumberFormatException x) {
                    // OK, next…
                }
                if (!kid.isDirectory()) {
                    LOGGER.log(FINE, "skipping non-directory {0}", name);
                    continue;
                }
                long timestamp;
                try {
                    synchronized (legacyIdFormatter) {
                        timestamp = legacyIdFormatter.parse(name).getTime();
                    }
                } catch (ParseException x) {
                    LOGGER.log(WARNING, "found unexpected dir {0}", name);
                    continue;
                }
                File buildXml = new File(kid, "build.xml");
                if (!buildXml.isFile()) {
                    LOGGER.log(WARNING, "found no build.xml in {0}", name);
                    continue;
                }
                String xml = FileUtils.readFileToString(buildXml, Charsets.UTF_8);
                Matcher m = NUMBER_ELT.matcher(xml);
                if (!m.find()) {
                    LOGGER.log(WARNING, "could not find <number> in {0}/build.xml", name);
                    continue;
                }
                int number = Integer.parseInt(m.group(1));
                String nl = m.group(2);
                xml = m.replaceFirst("  <id>" + name + "</id>" + nl + "  <timestamp>" + timestamp + "</timestamp>" + nl);
                File newKid = new File(dir, Integer.toString(number));
                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);
            } catch (Exception x) {
                LOGGER.log(WARNING, "failed to process " + kid, x);
            }
        }
    }