<commit_before>--- commands.py
+++ commands.py
@@ -58,6 +58,8 @@
 
 
 def reallyrmtree(path):
+    if os.path.isfile(os.path.join(path, 'asm-all-4.0.jar')): #Check if asm exists, indicating the libs folder, if so, don't delete it
+        return
     if not sys.platform.startswith('win'):
         if os.path.exists(path):
             shutil.rmtree(path)
@@ -584,6 +586,9 @@
         self.has_astyle_cfg = False
         if os.path.isfile(self.astyleconf):
             self.has_astyle_cfg = True
+            
+        #FML Entries
+        self.srcshared = os.path.normpath(os.path.join(self.dirsrc, 'common'))
 
     def creatergcfg(self, reobf=False, keep_lvt=False, keep_generics=False, rg_update=False):
         """Create the files necessary for RetroGuard"""
@@ -781,7 +786,8 @@
         testlk = {CLIENT: self.testclient, SERVER: self.testserver}
 
         if not os.path.exists(os.path.join(srclk[side], os.path.normpath(testlk[side] + '.java'))):
-            return False
+            if not os.path.exists(os.path.join(self.srcshared, os.path.normpath(testlk[side] + '.java'))):
+                return False
         return True
 
     def checkbins(self, side):
@@ -1029,6 +1035,10 @@
         pathsrclk = {CLIENT: self.srcclient, SERVER: self.srcserver}
         pathlog = {CLIENT: self.clientrecomplog, SERVER: self.serverrecomplog}
 
+        if side == SERVER: #Disable server because FML recombines it into client
+            self.logger.info('Server side recompiling skipped, this is normal')
+            return
+        
         if not os.path.exists(pathbinlk[side]):
             os.makedirs(pathbinlk[side])
 
@@ -1041,6 +1051,7 @@
             all_files = True
             append_pattern = False
         pkglist = filterdirs(pathsrclk[side], '*.java', append_pattern=append_pattern, all_files=all_files)
+        pkglist = pkglist + filterdirs(self.srcshared, '*.java', append_pattern=append_pattern, all_files=all_files) #FML, Add Common folder
         dirs = ' '.join(pkglist)
         classpath = os.pathsep.join(cplk[side])
         forkcmd = self.cmdrecomp.format(classpath=classpath, sourcepath=pathsrclk[side], outpath=pathbinlk[side],
@@ -1062,7 +1073,7 @@
             raise
 
     def startserver(self):
-        classpath = [self.binserver] + self.cpathserver
+        classpath = [self.binserver, self.srcshared] + self.cpathserver
         classpath = [os.path.join('..', p) for p in classpath]
         classpath = os.pathsep.join(classpath)
         os.chdir(self.dirjars)
@@ -1070,7 +1081,7 @@
         self.runmc(forkcmd)
 
     def startclient(self):
-        classpath = [self.binclient] + self.cpathclient
+        classpath = [self.binclient, self.srcshared] + self.cpathclient
         classpath = [os.path.join('..', p) for p in classpath]
         classpath = os.pathsep.join(classpath)
         natives = os.path.join('..', self.dirnatives)
@@ -1197,20 +1208,20 @@
         with open(self.csvmethods, 'rb') as fh:
             methodsreader = csv.DictReader(fh)
             for row in methodsreader:
-                if int(row['side']) == side:
+                if int(row['side']) == side or int(row['side']) == 2:
                     if row['name'] != row['searge']:
                         names['methods'][row['searge']] = row['name']
         with open(self.csvfields, 'rb') as fh:
             fieldsreader = csv.DictReader(fh)
             for row in fieldsreader:
-                if int(row['side']) == side:
+                if int(row['side']) == side or int(row['side']) == 2:
                     if row['name'] != row['searge']:
                         names['fields'][row['searge']] = row['name']
         if self.has_param_csv:
             with open(self.csvparams, 'rb') as fh:
                 paramsreader = csv.DictReader(fh)
                 for row in paramsreader:
-                    if int(row['side']) == side:
+                    if int(row['side']) == side or int(row['side']) == 2:
                         names['params'][row['param']] = row['name']
 
         regexps = {
@@ -1240,6 +1251,11 @@
 
         # HINT: We pathwalk the sources
         for path, _, filelist in os.walk(pathsrclk[side], followlinks=True):
+            for cur_file in fnmatch.filter(filelist, '*.java'):
+                updatefile(os.path.normpath(os.path.join(path, cur_file)))
+                
+        # FML, copy of the above, for the common folder
+        for path, _, filelist in os.walk(self.srcshared, followlinks=True):
             for cur_file in fnmatch.filter(filelist, '*.java'):
                 updatefile(os.path.normpath(os.path.join(path, cur_file)))
         return True
@@ -1322,12 +1338,14 @@
         pathsrclk = {CLIENT: self.srcclient, SERVER: self.srcserver}
 
         strip_comments(pathsrclk[side])
+        strip_comments(self.srcshared)
 
     def process_cleanup(self, side):
         """Do lots of random cleanups including stripping comments, trailing whitespace and extra blank lines"""
         pathsrclk = {CLIENT: self.srcclient, SERVER: self.srcserver}
 
         src_cleanup(pathsrclk[side], fix_imports=True, fix_unicode=True, fix_charval=True, fix_pi=True, fix_round=False)
+        src_cleanup(self.srcshared, fix_imports=True, fix_unicode=True, fix_charval=True, fix_pi=True, fix_round=False)
 
     def process_javadoc(self, side):
         """Add CSV descriptions to methods and fields as javadoc"""
@@ -1336,6 +1354,21 @@
         if not self.has_doc_csv:
             self.logger.warning('!! javadoc disabled due to no csvs !!')
             return False
+            
+        #FML Recall this function on the common folder
+        #Potential bug: If this is called without a subsiquent rename call, will cause double comments
+        if pathsrclk[side] != self.srcshared:
+            if side == CLIENT:
+                tmp = self.srcclient
+                self.srcclient = self.srcshared
+                self.process_javadoc(side)
+                self.srcclient = tmp
+            else:
+                tmp = self.srcserver
+                self.srcserver = self.srcshared
+                self.process_javadoc(side)
+                self.srcserver = tmp
+                
 
         #HINT: We read the relevant CSVs
         methodsreader = csv.DictReader(open(self.csvmethods, 'r'))
@@ -1344,13 +1377,13 @@
         methods = {}
         for row in methodsreader:
             #HINT: Only include methods that have a non-empty description
-            if int(row['side']) == side and row['desc']:
+            if (int(row['side']) == side or int(row['side']) == 2) and row['desc']:
                 methods[row['searge']] = row['desc'].replace('*/', '* /')
 
         fields = {}
         for row in fieldsreader:
             #HINT: Only include fields that have a non-empty description
-            if int(row['side']) == side and row['desc']:
+            if (int(row['side']) == side or int(row['side']) == 2) and row['desc']:
                 fields[row['searge']] = row['desc'].replace('*/', '* /')
 
         regexps = {
@@ -1422,12 +1455,13 @@
 
         # HINT: We create the list of source directories based on the list of packages
         pkglist = filterdirs(pathsrclk[side], '*.java', append_pattern=True)
+        pkglist = pkglist + filterdirs(self.srcshared, '*.java', append_pattern=True) #FML, Add Common folder
         dirs = ' '.join(pkglist)
         forkcmd = self.cmdastyle.format(classes=dirs, conffile=self.astyleconf)
         self.runcmd(forkcmd)
         return True
 
-    def gathermd5s(self, side, reobf=False):
+    def gathermd5s(self, side, reobf=False, skip_fml=False):
         if not reobf:
             md5lk = {CLIENT: self.md5client, SERVER: self.md5server}
         else:
@@ -1442,6 +1476,9 @@
                     class_path = ''
                 else:
                     class_path += '/'
+                if skip_fml:
+                    if class_path.startswith('cpw/'):
+                        continue
                 for class_file in fnmatch.filter(filelist, '*.class'):
                     class_name = class_path + os.path.splitext(class_file)[0]
                     bin_file = os.path.normpath(os.path.join(path, class_file))
@@ -1594,6 +1631,9 @@
                 sys.exit(1)
 
         for entry in newfiles:
+            if 'commands.py' in entry[0]: #FML, Disable updating of Commands.py
+                print 'Update to runtime/commands.py found, but disbled due to using fml'
+                continue
             if entry[3] == 'U':
                 self.logger.info('Retrieving file from server : %s', entry[0])
                 cur_file = os.path.normpath(entry[0])
@@ -1614,6 +1654,9 @@
         md5reoblk = {CLIENT: self.md5reobfclient, SERVER: self.md5reobfserver}
         outpathlk = {CLIENT: self.srcmodclient, SERVER: self.srcmodserver}
         src = {CLIENT: self.srcclient, SERVER: self.srcserver}
+        
+        if side == SERVER: #Noop out server side stuff
+            return
 
         # HINT: We need a table for the old md5 and the new ones
         md5table = {}
@@ -1656,3 +1699,6 @@
                 except IOError:
                     self.logger.error('* File %s copy failed', in_class)
 
+def commands_sanity_check():
+    print 'Commands patch applied successfully'
+    <commit_msg>Makes GetModSrc check the common folder when attempting to extract source files<commit_after>--- commands.py
+++ commands.py
@@ -58,6 +58,8 @@
 
 
 def reallyrmtree(path):
+    if os.path.isfile(os.path.join(path, 'asm-all-4.0.jar')): #Check if asm exists, indicating the libs folder, if so, don't delete it
+        return
     if not sys.platform.startswith('win'):
         if os.path.exists(path):
             shutil.rmtree(path)
@@ -584,6 +586,9 @@
         self.has_astyle_cfg = False
         if os.path.isfile(self.astyleconf):
             self.has_astyle_cfg = True
+            
+        #FML Entries
+        self.srcshared = os.path.normpath(os.path.join(self.dirsrc, 'common'))
 
     def creatergcfg(self, reobf=False, keep_lvt=False, keep_generics=False, rg_update=False):
         """Create the files necessary for RetroGuard"""
@@ -781,7 +786,8 @@
         testlk = {CLIENT: self.testclient, SERVER: self.testserver}
 
         if not os.path.exists(os.path.join(srclk[side], os.path.normpath(testlk[side] + '.java'))):
-            return False
+            if not os.path.exists(os.path.join(self.srcshared, os.path.normpath(testlk[side] + '.java'))):
+                return False
         return True
 
     def checkbins(self, side):
@@ -1029,6 +1035,10 @@
         pathsrclk = {CLIENT: self.srcclient, SERVER: self.srcserver}
         pathlog = {CLIENT: self.clientrecomplog, SERVER: self.serverrecomplog}
 
+        if side == SERVER: #Disable server because FML recombines it into client
+            self.logger.info('Server side recompiling skipped, this is normal')
+            return
+        
         if not os.path.exists(pathbinlk[side]):
             os.makedirs(pathbinlk[side])
 
@@ -1041,6 +1051,7 @@
             all_files = True
             append_pattern = False
         pkglist = filterdirs(pathsrclk[side], '*.java', append_pattern=append_pattern, all_files=all_files)
+        pkglist = pkglist + filterdirs(self.srcshared, '*.java', append_pattern=append_pattern, all_files=all_files) #FML, Add Common folder
         dirs = ' '.join(pkglist)
         classpath = os.pathsep.join(cplk[side])
         forkcmd = self.cmdrecomp.format(classpath=classpath, sourcepath=pathsrclk[side], outpath=pathbinlk[side],
@@ -1062,7 +1073,7 @@
             raise
 
     def startserver(self):
-        classpath = [self.binserver] + self.cpathserver
+        classpath = [self.binserver, self.srcshared] + self.cpathserver
         classpath = [os.path.join('..', p) for p in classpath]
         classpath = os.pathsep.join(classpath)
         os.chdir(self.dirjars)
@@ -1070,7 +1081,7 @@
         self.runmc(forkcmd)
 
     def startclient(self):
-        classpath = [self.binclient] + self.cpathclient
+        classpath = [self.binclient, self.srcshared] + self.cpathclient
         classpath = [os.path.join('..', p) for p in classpath]
         classpath = os.pathsep.join(classpath)
         natives = os.path.join('..', self.dirnatives)
@@ -1197,20 +1208,20 @@
         with open(self.csvmethods, 'rb') as fh:
             methodsreader = csv.DictReader(fh)
             for row in methodsreader:
-                if int(row['side']) == side:
+                if int(row['side']) == side or int(row['side']) == 2:
                     if row['name'] != row['searge']:
                         names['methods'][row['searge']] = row['name']
         with open(self.csvfields, 'rb') as fh:
             fieldsreader = csv.DictReader(fh)
             for row in fieldsreader:
-                if int(row['side']) == side:
+                if int(row['side']) == side or int(row['side']) == 2:
                     if row['name'] != row['searge']:
                         names['fields'][row['searge']] = row['name']
         if self.has_param_csv:
             with open(self.csvparams, 'rb') as fh:
                 paramsreader = csv.DictReader(fh)
                 for row in paramsreader:
-                    if int(row['side']) == side:
+                    if int(row['side']) == side or int(row['side']) == 2:
                         names['params'][row['param']] = row['name']
 
         regexps = {
@@ -1240,6 +1251,11 @@
 
         # HINT: We pathwalk the sources
         for path, _, filelist in os.walk(pathsrclk[side], followlinks=True):
+            for cur_file in fnmatch.filter(filelist, '*.java'):
+                updatefile(os.path.normpath(os.path.join(path, cur_file)))
+                
+        # FML, copy of the above, for the common folder
+        for path, _, filelist in os.walk(self.srcshared, followlinks=True):
             for cur_file in fnmatch.filter(filelist, '*.java'):
                 updatefile(os.path.normpath(os.path.join(path, cur_file)))
         return True
@@ -1322,12 +1338,14 @@
         pathsrclk = {CLIENT: self.srcclient, SERVER: self.srcserver}
 
         strip_comments(pathsrclk[side])
+        strip_comments(self.srcshared)
 
     def process_cleanup(self, side):
         """Do lots of random cleanups including stripping comments, trailing whitespace and extra blank lines"""
         pathsrclk = {CLIENT: self.srcclient, SERVER: self.srcserver}
 
         src_cleanup(pathsrclk[side], fix_imports=True, fix_unicode=True, fix_charval=True, fix_pi=True, fix_round=False)
+        src_cleanup(self.srcshared, fix_imports=True, fix_unicode=True, fix_charval=True, fix_pi=True, fix_round=False)
 
     def process_javadoc(self, side):
         """Add CSV descriptions to methods and fields as javadoc"""
@@ -1336,6 +1354,21 @@
         if not self.has_doc_csv:
             self.logger.warning('!! javadoc disabled due to no csvs !!')
             return False
+            
+        #FML Recall this function on the common folder
+        #Potential bug: If this is called without a subsiquent rename call, will cause double comments
+        if pathsrclk[side] != self.srcshared:
+            if side == CLIENT:
+                tmp = self.srcclient
+                self.srcclient = self.srcshared
+                self.process_javadoc(side)
+                self.srcclient = tmp
+            else:
+                tmp = self.srcserver
+                self.srcserver = self.srcshared
+                self.process_javadoc(side)
+                self.srcserver = tmp
+                
 
         #HINT: We read the relevant CSVs
         methodsreader = csv.DictReader(open(self.csvmethods, 'r'))
@@ -1344,13 +1377,13 @@
         methods = {}
         for row in methodsreader:
             #HINT: Only include methods that have a non-empty description
-            if int(row['side']) == side and row['desc']:
+            if (int(row['side']) == side or int(row['side']) == 2) and row['desc']:
                 methods[row['searge']] = row['desc'].replace('*/', '* /')
 
         fields = {}
         for row in fieldsreader:
             #HINT: Only include fields that have a non-empty description
-            if int(row['side']) == side and row['desc']:
+            if (int(row['side']) == side or int(row['side']) == 2) and row['desc']:
                 fields[row['searge']] = row['desc'].replace('*/', '* /')
 
         regexps = {
@@ -1422,12 +1455,13 @@
 
         # HINT: We create the list of source directories based on the list of packages
         pkglist = filterdirs(pathsrclk[side], '*.java', append_pattern=True)
+        pkglist = pkglist + filterdirs(self.srcshared, '*.java', append_pattern=True) #FML, Add Common folder
         dirs = ' '.join(pkglist)
         forkcmd = self.cmdastyle.format(classes=dirs, conffile=self.astyleconf)
         self.runcmd(forkcmd)
         return True
 
-    def gathermd5s(self, side, reobf=False):
+    def gathermd5s(self, side, reobf=False, skip_fml=False):
         if not reobf:
             md5lk = {CLIENT: self.md5client, SERVER: self.md5server}
         else:
@@ -1442,6 +1476,9 @@
                     class_path = ''
                 else:
                     class_path += '/'
+                if skip_fml:
+                    if class_path.startswith('cpw/'):
+                        continue
                 for class_file in fnmatch.filter(filelist, '*.class'):
                     class_name = class_path + os.path.splitext(class_file)[0]
                     bin_file = os.path.normpath(os.path.join(path, class_file))
@@ -1594,6 +1631,9 @@
                 sys.exit(1)
 
         for entry in newfiles:
+            if 'commands.py' in entry[0]: #FML, Disable updating of Commands.py
+                print 'Update to runtime/commands.py found, but disbled due to using fml'
+                continue
             if entry[3] == 'U':
                 self.logger.info('Retrieving file from server : %s', entry[0])
                 cur_file = os.path.normpath(entry[0])
@@ -1614,6 +1654,9 @@
         md5reoblk = {CLIENT: self.md5reobfclient, SERVER: self.md5reobfserver}
         outpathlk = {CLIENT: self.srcmodclient, SERVER: self.srcmodserver}
         src = {CLIENT: self.srcclient, SERVER: self.srcserver}
+        
+        if side == SERVER: #Noop out server side stuff
+            return
 
         # HINT: We need a table for the old md5 and the new ones
         md5table = {}
@@ -1646,6 +1689,7 @@
         # HINT: We extract the source files for the modified class files
         for in_class in trgclasses:
             src_file = os.path.normpath(os.path.join(src[side], in_class + '.java'))
+            cmn_file = os.path.normpath(os.path.join(self.srcshared, in_class + '.java'))
             dest_file = os.path.normpath(os.path.join(outpathlk[side], in_class + '.java'))
             if os.path.isfile(src_file):
                 if not os.path.exists(os.path.dirname(dest_file)):
@@ -1655,4 +1699,15 @@
                     self.logger.info('> Outputted %s to %s', in_class.ljust(35), outpathlk[side])
                 except IOError:
                     self.logger.error('* File %s copy failed', in_class)
-
+            elif os.path.isfile(cmn_file):
+                if not os.path.exists(os.path.dirname(dest_file)):
+                    os.makedirs(os.path.dirname(dest_file))
+                try:
+                    shutil.copyfile(cmn_file, dest_file)
+                    self.logger.info('> Outputted %s to %s', in_class.ljust(35), outpathlk[side])
+                except IOError:
+                    self.logger.error('* File %s copy failed', in_class)
+
+def commands_sanity_check():
+    print 'Commands patch applied successfully'
+    
{'fraction_non_alphanumeric': 0.1337814616395431, 'fraction_numerical': 0.020570100070757102, 'mean_word_length': 2.1009246199655225, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7169648', 'n_tokens_mistral': 6504, 'n_tokens_neox': 6078, 'n_words': 1410}