def easypatch_content(df, content, loc, **kwargs): file = raws.rawfile(path=loc, content=content) return easypatch_file(df, file, **kwargs)
def easypatch_tokens(df, tokens, loc, **kwargs): file = raws.rawfile(path=loc, tokens=tokens) return easypatch_file(df, file, **kwargs)
def easypatch_filepath(df, path, loc=None, root=None, **kwargs): file = raws.rawfile(path=path, loc=loc, root=root) return easypatch_file(df, file, **kwargs)
def diff(df, paths): # Get all the files in the mods newfiles = [] for path in paths: if os.path.isfile(path) and path.endswith('.txt'): with open(path, 'rb') as rfilestream: rfiles = (raws.rawfile(rfile=rfilestream, path=path), ) elif os.path.isdir(path): rfiles = raws.dir(path=path).files.values() else: return pydwarf.failure('Failed to load raws from path %s.' % path) newfiles.append(rfiles) operations = {} conflicts = 0 currentfiletokensdict = {} for newfilelist in newfiles: for newfile in newfilelist: pydwarf.log.info('Handling diff for file %s...' % newfile.header) # Get list of tokens for current file (And don't do it for the same file twice) currentfiletokens = None if newfile.header in currentfiletokensdict: currentfiletokens = currentfiletokensdict[newfile.header] elif newfile.header in df.files: currentfiletokens = list(df.getfile(newfile.header)) currentfiletokensdict[newfile.header] = currentfiletokens # Do a diff if currentfiletokens: newfiletokens = list(newfile.tokens()) diff = difflib.SequenceMatcher(None, currentfiletokens, newfiletokens) if newfile.header not in operations: operations[newfile.header] = { 'insert': [], 'delete': [], 'replace': [], 'equal': [] } for item in diff.get_opcodes(): if item[0] != 'equals': op = item[0] operations[newfile.header][op].append( diffrecord(currentfiletokens, newfiletokens, newfile.path, *item)) # File doesn't exist yet, don't bother with a diff else: pydwarf.log.debug('File didn\'t exist yet, adding...') df.add(newfile) for fileheader, fileops in operations.iteritems(): # Do some handling for potentially conflicting replacements for i in xrange(0, len(fileops['replace'])): irecord = fileops['replace'][i] if not irecord.ignore: for j in xrange(i + 1, len(fileops['replace'])): jrecord = fileops['replace'][j] # Replacements overlap? if (jrecord.bpath is not irecord.bpath) and ( irecord.afrom <= jrecord.auntil and jrecord.afrom <= irecord.auntil): jrecord.ignore = True if not raws.helpers.tokensequal( irecord.btokens(), jrecord.btokens()): # Replacements aren't identical (this means there's a conflict) if not irecord.conflicts: irecord.conflicts = [] irecord.conflicts.append(jrecord) # Make replacements (insertions) for record in fileops['replace']: if not record.ignore: if record.conflicts is None: tokens = record.btokens() else: # Handle conflicts pydwarf.log.error( 'Encountered potentially conflicting changes in %s, block replaced by %d input files.' % (fileheader, len(record.conflicts) + 1)) tokens = [] lasttoken = None for conflict in record.conflicts + [record]: conflict.blower.prefix = '\n<<<diff from %s;%s' % ( conflict.bpath, conflict.blower.prefix if conflict.blower.prefix else '') for token in conflict.btokens(): lasttoken = token tokens.append(token) lasttoken.suffix = '%s\n>>>\n' % ( lasttoken.suffix if lasttoken.suffix else '') tokens[ 0].prefix = '\n<<<<<<diff potential conflict! block modified by %d files %s;\n%s' % ( len(record.conflicts) + 1, ', '.join([r.bpath for r in record.conflicts] + [record.bpath]), tokens[0].prefix if tokens[0].prefix else '') lasttoken.suffix = '%s\n>>>>>>\n\n' % ( lasttoken.suffix if lasttoken.suffix else '') conflicts += 1 tokens = record.alower.add( tokens=raws.helpers.copytokens(tokens)) # Make insertions for record in fileops['insert']: record.alower.add(raws.helpers.copytokens(tokens=record.btokens())) # Make deletions for record in fileops['delete']: for token in record.atokens(): token.remove() # Make replacements (deletions) for record in fileops['replace']: for token in record.atokens(): token.remove() if conflicts == 0: return pydwarf.success('Merged %d mods without conflicts.' % len(paths)) else: return pydwarf.failure( 'Merged %d mods with %d conflicts. Recommended you search in outputted raws for text like "<<<<<<diff potential conflict!" and resolve manually.' % (len(paths), conflicts))
def addfile(df, filename): with open('%s/%s' % (rawsdir, filename), 'rb') as rawfile: df.add(raws.rawfile(path='raw/objects/%s' % filename, file=rawfile)) return pydwarf.success('Added file "%s".' % filename)
def diff(df, paths): # Get all the files in the mods newfiles = [] for path in paths: if os.path.isfile(path) and path.endswith('.txt'): with open(path, 'rb') as rfilestream: rfiles = (raws.rawfile(rfile=rfilestream, path=path),) elif os.path.isdir(path): rfiles = raws.dir(path=path).files.values() else: return pydwarf.failure('Failed to load raws from path %s.' % path) newfiles.append(rfiles) operations = {} conflicts = 0 currentfiletokensdict = {} for newfilelist in newfiles: for newfile in newfilelist: pydwarf.log.info('Handling diff for file %s...' % newfile.header) # Get list of tokens for current file (And don't do it for the same file twice) currentfiletokens = None if newfile.header in currentfiletokensdict: currentfiletokens = currentfiletokensdict[newfile.header] elif newfile.header in df.files: currentfiletokens = list(df.getfile(newfile.header)) currentfiletokensdict[newfile.header] = currentfiletokens # Do a diff if currentfiletokens: newfiletokens = list(newfile.tokens()) diff = difflib.SequenceMatcher(None, currentfiletokens, newfiletokens) if newfile.header not in operations: operations[newfile.header] = {'insert': [], 'delete': [], 'replace': [], 'equal': []} for item in diff.get_opcodes(): if item[0] != 'equals': op = item[0] operations[newfile.header][op].append(diffrecord(currentfiletokens, newfiletokens, newfile.path, *item)) # File doesn't exist yet, don't bother with a diff else: pydwarf.log.debug('File didn\'t exist yet, adding...') df.add(newfile) for fileheader, fileops in operations.iteritems(): # Do some handling for potentially conflicting replacements for i in xrange(0, len(fileops['replace'])): irecord = fileops['replace'][i] if not irecord.ignore: for j in xrange(i+1, len(fileops['replace'])): jrecord = fileops['replace'][j] # Replacements overlap? if (jrecord.bpath is not irecord.bpath) and (irecord.afrom <= jrecord.auntil and jrecord.afrom <= irecord.auntil): jrecord.ignore = True if not raws.helpers.tokensequal(irecord.btokens(), jrecord.btokens()): # Replacements aren't identical (this means there's a conflict) if not irecord.conflicts: irecord.conflicts = [] irecord.conflicts.append(jrecord) # Make replacements (insertions) for record in fileops['replace']: if not record.ignore: if record.conflicts is None: tokens = record.btokens() else: # Handle conflicts pydwarf.log.error('Encountered potentially conflicting changes in %s, block replaced by %d input files.' % (fileheader, len(record.conflicts)+1)) tokens = [] lasttoken = None for conflict in record.conflicts + [record]: conflict.blower.prefix = '\n<<<diff from %s;%s' % (conflict.bpath, conflict.blower.prefix if conflict.blower.prefix else '') for token in conflict.btokens(): lasttoken = token tokens.append(token) lasttoken.suffix = '%s\n>>>\n' % (lasttoken.suffix if lasttoken.suffix else '') tokens[0].prefix = '\n<<<<<<diff potential conflict! block modified by %d files %s;\n%s' % (len(record.conflicts)+1, ', '.join([r.bpath for r in record.conflicts] + [record.bpath]), tokens[0].prefix if tokens[0].prefix else '') lasttoken.suffix = '%s\n>>>>>>\n\n' % (lasttoken.suffix if lasttoken.suffix else '') conflicts += 1 tokens = record.alower.add(tokens=raws.helpers.copytokens(tokens)) # Make insertions for record in fileops['insert']: record.alower.add(raws.helpers.copytokens(tokens=record.btokens())) # Make deletions for record in fileops['delete']: for token in record.atokens(): token.remove() # Make replacements (deletions) for record in fileops['replace']: for token in record.atokens(): token.remove() if conflicts == 0: return pydwarf.success('Merged %d mods without conflicts.' % len(paths)) else: return pydwarf.failure('Merged %d mods with %d conflicts. Recommended you search in outputted raws for text like "<<<<<<diff potential conflict!" and resolve manually.' % (len(paths), conflicts))