From e0f001acce44277a1e4eb0ccf79b801aa25ed216 Mon Sep 17 00:00:00 2001 From: Thomas Guillemard Date: Wed, 26 Oct 2016 17:34:06 +0200 Subject: Rework saving system to improve saving time (Fix #35) --- .../java/cuchaz/enigma/mapping/ClassMapping.java | 36 +++++++++++++ src/main/java/cuchaz/enigma/mapping/Mappings.java | 16 ++++++ .../enigma/mapping/MappingsEnigmaReader.java | 1 + .../enigma/mapping/MappingsEnigmaWriter.java | 62 ++++++++++++++++------ 4 files changed, 100 insertions(+), 15 deletions(-) (limited to 'src/main/java') diff --git a/src/main/java/cuchaz/enigma/mapping/ClassMapping.java b/src/main/java/cuchaz/enigma/mapping/ClassMapping.java index 36b35f73..923c8ece 100644 --- a/src/main/java/cuchaz/enigma/mapping/ClassMapping.java +++ b/src/main/java/cuchaz/enigma/mapping/ClassMapping.java @@ -22,12 +22,14 @@ public class ClassMapping implements Comparable { private String m_obfFullName; private String m_obfSimpleName; private String m_deobfName; + private String m_previousDeobfName; private Map m_innerClassesByObfSimple; private Map m_innerClassesByDeobf; private Map m_fieldsByObf; private Map m_fieldsByDeobf; private Map m_methodsByObf; private Map m_methodsByDeobf; + private boolean isDirty; public ClassMapping(String obfFullName) { this(obfFullName, null); @@ -37,6 +39,7 @@ public class ClassMapping implements Comparable { m_obfFullName = obfFullName; ClassEntry classEntry = new ClassEntry(obfFullName); m_obfSimpleName = classEntry.isInnerClass() ? classEntry.getInnermostClassName() : classEntry.getSimpleName(); + m_previousDeobfName = null; m_deobfName = NameValidator.validateClassName(deobfName, false); m_innerClassesByObfSimple = Maps.newHashMap(); m_innerClassesByDeobf = Maps.newHashMap(); @@ -44,6 +47,7 @@ public class ClassMapping implements Comparable { m_fieldsByDeobf = Maps.newHashMap(); m_methodsByObf = Maps.newHashMap(); m_methodsByDeobf = Maps.newHashMap(); + isDirty = true; } public String getObfFullName() { @@ -54,12 +58,18 @@ public class ClassMapping implements Comparable { return m_obfSimpleName; } + public String getPreviousDeobfName() { + return m_previousDeobfName; + } + public String getDeobfName() { return m_deobfName; } public void setDeobfName(String val) { + m_previousDeobfName = m_deobfName; m_deobfName = NameValidator.validateClassName(val, false); + this.isDirty = true; } //// INNER CLASSES //////// @@ -81,6 +91,7 @@ public class ClassMapping implements Comparable { } m_innerClassesByDeobf.put(classMapping.getDeobfName(), classMapping); } + this.isDirty = true; } public void removeInnerClassMapping(ClassMapping classMapping) { @@ -90,6 +101,7 @@ public class ClassMapping implements Comparable { boolean deobfWasRemoved = m_innerClassesByDeobf.remove(classMapping.getDeobfName()) != null; assert (deobfWasRemoved); } + this.isDirty = true; } public ClassMapping getOrCreateInnerClass(ClassEntry obfInnerClass) { @@ -98,6 +110,7 @@ public class ClassMapping implements Comparable { classMapping = new ClassMapping(obfInnerClass.getName()); boolean wasAdded = m_innerClassesByObfSimple.put(classMapping.getObfSimpleName(), classMapping) == null; assert (wasAdded); + this.isDirty = true; } return classMapping; } @@ -141,6 +154,7 @@ public class ClassMapping implements Comparable { boolean wasAdded = m_innerClassesByDeobf.put(deobfName, classMapping) == null; assert (wasAdded); } + this.isDirty = true; } public boolean hasInnerClassByObfSimple(String obfSimpleName) { @@ -181,6 +195,7 @@ public class ClassMapping implements Comparable { boolean deobfWasAdded = m_fieldsByDeobf.put(deobfKey, fieldMapping) == null; assert (deobfWasAdded); assert (m_fieldsByObf.size() == m_fieldsByDeobf.size()); + this.isDirty = true; } public void removeFieldMapping(FieldMapping fieldMapping) { @@ -190,6 +205,7 @@ public class ClassMapping implements Comparable { boolean deobfWasRemoved = m_fieldsByDeobf.remove(getFieldKey(fieldMapping.getDeobfName(), fieldMapping.getObfType())) != null; assert (deobfWasRemoved); } + this.isDirty = true; } public FieldMapping getFieldByObf(String obfName, Type obfType) { @@ -243,6 +259,7 @@ public class ClassMapping implements Comparable { boolean wasAdded = m_fieldsByDeobf.put(getFieldKey(deobfName, obfType), fieldMapping) == null; assert (wasAdded); } + this.isDirty = true; } public void setFieldObfNameAndType(String oldObfName, Type obfType, String newObfName, Type newObfType) { @@ -253,6 +270,7 @@ public class ClassMapping implements Comparable { fieldMapping.setObfType(newObfType); boolean obfWasAdded = m_fieldsByObf.put(getFieldKey(newObfName, newObfType), fieldMapping) == null; assert(obfWasAdded); + this.isDirty = true; } //// METHODS //////// @@ -285,6 +303,7 @@ public class ClassMapping implements Comparable { boolean deobfWasAdded = m_methodsByDeobf.put(deobfKey, methodMapping) == null; assert (deobfWasAdded); } + this.isDirty = true; assert (m_methodsByObf.size() >= m_methodsByDeobf.size()); } @@ -295,6 +314,7 @@ public class ClassMapping implements Comparable { boolean deobfWasRemoved = m_methodsByDeobf.remove(getMethodKey(methodMapping.getDeobfName(), methodMapping.getObfSignature())) != null; assert (deobfWasRemoved); } + this.isDirty = true; } public MethodMapping getMethodByObf(String obfName, Signature obfSignature) { @@ -328,6 +348,7 @@ public class ClassMapping implements Comparable { boolean wasAdded = m_methodsByDeobf.put(getMethodKey(deobfName, obfSignature), methodMapping) == null; assert (wasAdded); } + this.isDirty = true; } public void setMethodObfNameAndSignature(String oldObfName, Signature obfSignature, String newObfName, Signature newObfSignature) { @@ -338,6 +359,7 @@ public class ClassMapping implements Comparable { methodMapping.setObfSignature(newObfSignature); boolean obfWasAdded = m_methodsByObf.put(getMethodKey(newObfName, newObfSignature), methodMapping) == null; assert(obfWasAdded); + this.isDirty = true; } //// ARGUMENTS //////// @@ -349,16 +371,19 @@ public class ClassMapping implements Comparable { methodMapping = createMethodMapping(obfMethodName, obfMethodSignature); } methodMapping.setArgumentName(argumentIndex, argumentName); + this.isDirty = true; } public void removeArgumentName(String obfMethodName, Signature obfMethodSignature, int argumentIndex) { m_methodsByObf.get(getMethodKey(obfMethodName, obfMethodSignature)).removeArgumentName(argumentIndex); + this.isDirty = true; } private MethodMapping createMethodMapping(String obfName, Signature obfSignature) { MethodMapping methodMapping = new MethodMapping(obfName, obfSignature); boolean wasAdded = m_methodsByObf.put(getMethodKey(obfName, obfSignature), methodMapping) == null; assert (wasAdded); + this.isDirty = true; return methodMapping; } @@ -441,6 +466,7 @@ public class ClassMapping implements Comparable { m_obfFullName = newObfClassName; return true; } + this.isDirty = true; return false; } @@ -456,4 +482,14 @@ public class ClassMapping implements Comparable { public ClassEntry getObfEntry() { return new ClassEntry(m_obfFullName); } + + public boolean isDirty() + { + return isDirty; + } + + public void resetDirty() + { + this.isDirty = false; + } } diff --git a/src/main/java/cuchaz/enigma/mapping/Mappings.java b/src/main/java/cuchaz/enigma/mapping/Mappings.java index 7061be79..912a57ab 100644 --- a/src/main/java/cuchaz/enigma/mapping/Mappings.java +++ b/src/main/java/cuchaz/enigma/mapping/Mappings.java @@ -30,6 +30,7 @@ public class Mappings { protected Map classesByObf; protected Map classesByDeobf; private final FormatType originMapping; + private Mappings previousState; public Mappings() { @@ -40,6 +41,7 @@ public class Mappings { this.originMapping = originMapping; this.classesByObf = Maps.newHashMap(); this.classesByDeobf = Maps.newHashMap(); + this.previousState = null; } public Collection classes() { @@ -204,9 +206,19 @@ public class Mappings { return originMapping; } + public void savePreviousState() + { + this.previousState = new Mappings(this.originMapping); + this.previousState.classesByDeobf = Maps.newHashMap(this.classesByDeobf); + this.previousState.classesByObf = Maps.newHashMap(this.classesByObf); + classesByDeobf.values().forEach(ClassMapping::resetDirty); + classesByObf.values().forEach(ClassMapping::resetDirty); + } + public void saveEnigmaMappings(File file, boolean isDirectoryFormat) throws IOException { new MappingsEnigmaWriter().write(file, this, isDirectoryFormat); + this.savePreviousState(); } public void saveSRGMappings(File file) throws IOException @@ -214,6 +226,10 @@ public class Mappings { new MappingsSRGWriter().write(file, this); } + public Mappings getPreviousState() { + return previousState; + } + public enum FormatType { ENIGMA_FILE, ENIGMA_DIRECTORY, SRG_FILE diff --git a/src/main/java/cuchaz/enigma/mapping/MappingsEnigmaReader.java b/src/main/java/cuchaz/enigma/mapping/MappingsEnigmaReader.java index 74c5340c..93276a63 100644 --- a/src/main/java/cuchaz/enigma/mapping/MappingsEnigmaReader.java +++ b/src/main/java/cuchaz/enigma/mapping/MappingsEnigmaReader.java @@ -37,6 +37,7 @@ public class MappingsEnigmaReader else if (file.isDirectory()) readDirectory(mappings, file.getAbsoluteFile()); } + mappings.savePreviousState(); } else throw new IOException("Cannot access directory" + directory.getAbsolutePath()); diff --git a/src/main/java/cuchaz/enigma/mapping/MappingsEnigmaWriter.java b/src/main/java/cuchaz/enigma/mapping/MappingsEnigmaWriter.java index ba0720a0..e1763d0a 100644 --- a/src/main/java/cuchaz/enigma/mapping/MappingsEnigmaWriter.java +++ b/src/main/java/cuchaz/enigma/mapping/MappingsEnigmaWriter.java @@ -30,24 +30,14 @@ public class MappingsEnigmaWriter { writeAsDirectory(out, mappings); } - private void deleteDir(File file) { - File[] contents = file.listFiles(); - if (contents != null) { - for (File f : contents) { - deleteDir(f); - } - } - file.delete(); - } - public void writeAsDirectory(File target, Mappings mappings) throws IOException { - //TODO: Know what have changes during write to not rewrite all the things - deleteDir(target); if (!target.exists() && !target.mkdirs()) - throw new IOException("Cannot create mapping directory!"); - + throw new IOException("Cannot create mapping directory!"); for (ClassMapping classMapping : sorted(mappings.classes())) { + if (!classMapping.isDirty()) + continue; + this.deletePreviousClassMapping(target, classMapping); File obFile = new File(target, classMapping.getObfFullName() + ".mapping"); File result; if (classMapping.getDeobfName() == null) @@ -68,8 +58,50 @@ public class MappingsEnigmaWriter { outputWriter.close(); } + // Remove dropped mappings + List droppedClassMappings = new ArrayList<>(mappings.getPreviousState().classes()); + List classMappings = new ArrayList<>(mappings.classes()); + droppedClassMappings.removeAll(classMappings); + for (ClassMapping classMapping : droppedClassMappings) + { + File obFile = new File(target, classMapping.getObfFullName() + ".mapping"); + File result; + if (classMapping.getDeobfName() == null) + result = obFile; + else + { + // Make sure that old version of the file doesn't exist + if (obFile.exists()) + obFile.delete(); + result = new File(target, classMapping.getDeobfName() + ".mapping"); + } + if (result.exists()) + result.delete(); + } } - + + private void deletePreviousClassMapping(File target, ClassMapping classMapping) { + File prevFile = null; + // Deob rename + if (classMapping.getDeobfName() != null && classMapping.getPreviousDeobfName() != null && !classMapping.getPreviousDeobfName().equals(classMapping.getDeobfName())) + { + prevFile = new File(target, classMapping.getPreviousDeobfName() + ".mapping"); + } + // Deob to ob rename + else if (classMapping.getDeobfName() == null && classMapping.getPreviousDeobfName() != null) + { + prevFile = new File(target, classMapping.getPreviousDeobfName() + ".mapping"); + } + // Ob to Deob rename + else if (classMapping.getDeobfName() != null && classMapping.getPreviousDeobfName() == null) + { + prevFile = new File(target, classMapping.getObfFullName() + ".mapping"); + } + + if (prevFile != null && prevFile.exists()) + prevFile.delete(); + } + public void write(PrintWriter out, Mappings mappings) throws IOException { for (ClassMapping classMapping : sorted(mappings.classes())) { write(out, classMapping, 0); -- cgit v1.2.3