/** Inverse of {@link #doMigrate}. */ private void unmigrateBuildsDir(File builds) throws Exception { File mapFile = new File(builds, MAP_FILE); if (!mapFile.isFile()) { System.err.println(builds + " does not look to have been migrated yet; skipping"); return; } for (File build : builds.listFiles()) { int number; try { number = Integer.parseInt(build.getName()); } catch (NumberFormatException x) { continue; } File buildXml = new File(build, "build.xml"); if (!buildXml.isFile()) { System.err.println(buildXml + " did not exist"); continue; } String xml = FileUtils.readFileToString(buildXml, Charsets.UTF_8); Matcher m = TIMESTAMP_ELT.matcher(xml); if (!m.find()) { System.err.println(buildXml + " did not contain <timestamp> as expected"); continue; } long timestamp = Long.parseLong(m.group(1)); String nl = m.group(2); xml = m.replaceFirst(" <number>" + number + "</number>" + nl); m = ID_ELT.matcher(xml); String id; if (m.find()) { id = m.group(1); xml = m.replaceFirst(""); } else { // Post-migration build. We give it a new ID based on its timestamp. id = legacyIdFormatter.format(new Date(timestamp)); } FileUtils.write(buildXml, xml, Charsets.UTF_8); if (!build.renameTo(new File(builds, id))) { System.err.println(build + " could not be renamed"); } Util.createSymlink(builds, id, Integer.toString(number), StreamTaskListener.fromStderr()); } Util.deleteFile(mapFile); System.err.println(builds + " has been restored to its original format"); }
@Override public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener) throws InterruptedException { Result criteriaResult = CloneWorkspaceUtil.getResultForCriteria(criteria); String realIncludeGlob; // Default to **/* if no glob is specified. if (workspaceGlob.length() == 0) { realIncludeGlob = "**/*"; } else { try { realIncludeGlob = build.getEnvironment(listener).expand(workspaceGlob); } catch (IOException e) { // We couldn't get an environment for some reason, so we'll just use the original. realIncludeGlob = workspaceGlob; } } String realExcludeGlob = null; // Default to empty if no glob is specified. if (Util.fixNull(workspaceExcludeGlob).length() != 0) { try { realExcludeGlob = build.getEnvironment(listener).expand(workspaceExcludeGlob); } catch (IOException e) { // We couldn't get an environment for some reason, so we'll just use the original. realExcludeGlob = workspaceExcludeGlob; } } if (build.getResult().isBetterOrEqualTo(criteriaResult)) { listener.getLogger().println(Messages.CloneWorkspacePublisher_ArchivingWorkspace()); FilePath ws = build.getWorkspace(); if (ws == null) { // #3330: slave down? return true; } try { String includeMsg = ws.validateAntFileMask(realIncludeGlob); String excludeMsg = null; if (realExcludeGlob != null) { ws.validateAntFileMask(realExcludeGlob); } // This means we found something. if ((includeMsg == null) && (excludeMsg == null)) { DirScanner globScanner = new DirScanner.Glob(realIncludeGlob, realExcludeGlob); build.addAction(snapshot(build, ws, globScanner, listener, archiveMethod)); // Find the next most recent build meeting this criteria with an archived snapshot. AbstractBuild<?, ?> previousArchivedBuild = CloneWorkspaceUtil.getMostRecentBuildForCriteriaWithSnapshot( build.getPreviousBuild(), criteria); if (previousArchivedBuild != null) { listener .getLogger() .println( Messages.CloneWorkspacePublisher_DeletingOld( previousArchivedBuild.getDisplayName())); try { File oldWss = new File( previousArchivedBuild.getRootDir(), CloneWorkspaceUtil.getFileNameForMethod(archiveMethod)); Util.deleteFile(oldWss); } catch (IOException e) { e.printStackTrace(listener.error(e.getMessage())); } } return true; } else { listener .getLogger() .println(Messages.CloneWorkspacePublisher_NoMatchFound(realIncludeGlob, includeMsg)); return true; } } catch (IOException e) { Util.displayIOException(e, listener); e.printStackTrace( listener.error(Messages.CloneWorkspacePublisher_FailedToArchive(realIncludeGlob))); return true; } catch (InterruptedException e) { e.printStackTrace( listener.error(Messages.CloneWorkspacePublisher_FailedToArchive(realIncludeGlob))); return true; } } else { listener.getLogger().println(Messages.CloneWorkspacePublisher_CriteriaNotMet(criteriaResult)); return true; } }
private void doMigrate(File dir) { idToNumber = new TreeMap<String, Integer>(); File[] kids = dir.listFiles(); // Need to process symlinks first so we can rename to them. List<File> kidsList = new ArrayList<File>(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); } } }