2012-05-04 11 views
5

Estoy trabajando en un proyecto donde las personas pueden enviar historias y hacer que otras personas contribuyan. En lugar de simplemente editar una entrada en la base de datos, me gustaría almacenar los cambios que las personas hacen en lugar del conjunto completo de cambios. Luego puedo aplicar dffs dinámicamente si la gente quiere volver a una versión anterior. También puedo presentar fácilmente a los usuarios que son editores con solo el texto modificado para que puedan ir directamente a los cambios.¿Cómo puedo diferir y parchear/fusionar cadenas en lugar de archivos?

Soy consciente de cómo tomar archivos diff y parchar otros archivos con ellos. Pero estoy haciendo una aplicación web con Python y Django, y almacenaré todas estas diferencias en una base de datos MySQL. Dado que el rendimiento no es un problema importante para esta aplicación, estoy preparado para extraer los datos de la BD, crear archivos y ejecutar git diff y patch en esos archivos.

¿Existe alguna manera mejor que crear nuevos archivos y eliminarlos cada vez que deseo crear una nueva versión o aplicar una nueva diferencia? ¿Hay alguna forma de ejecutar diffs en texto directo en lugar de archivos? P.ej. establecer variables en bash para que sean los contenidos de (lo que sería) un archivo (pero en realidad son datos de la base de datos) y ejecutar git diff en ellos? Me gustaría controlar estas acciones desde un archivo de Python después de que el usuario envíe un formulario.

Realmente estoy buscando una buena manera de comenzar con este problema, por lo que cualquier ayuda sería muy apreciada.

Gracias por su tiempo,

ParagonRG

+4

que sin duda puede aplicar los principios de almacenamiento de las diferenciaciones en lugar del texto completo en la base de datos, pero es un poco extraño que te gustaría utilizar un VCS para el propósito. .. (has mirado http://docs.python.org/library/difflib.html)? – geoffspear

+0

¡Gracias, investigando esto ahora! – Paragon

+0

Desafortunadamente difflib no permitía reconstruir texto de dif a menos que se usen diffs que almacenan la totalidad del texto y sus cambios. Por lo tanto, construí un módulo para hacer esto; por favor mira mi respuesta a continuación. – Paragon

Respuesta

4

He hecho bastante buscando una solución para esto. Python's difflib es bastante legal, pero desafortunadamente tiende a requerir que las cadenas de diferencias contengan todas las cadenas originales con registros de lo que se modificó. Esto difiere de, por ejemplo, un git diff, donde solo se ve lo que se cambió y algún contexto extra. difflib también proporciona una función llamada unified_diff que de hecho proporciona una diferencia más corta, pero no proporciona una función para reconstruir una cadena de una cadena y un diff. P.ej. si hice un diff de text1 y text2, llamado diff1, entonces no pude generar text2 de text1 y diff1.

He creado, por lo tanto, un módulo de Python simple que permite reconstruir cadenas, tanto hacia delante como hacia atrás, desde una única cadena y sus diferencias relacionadas. Se llama merge_in_memory y se puede encontrar en https://github.com/danielmoniz/merge_in_memory. Simplemente tire del repositorio y ejecute setup.py.

Un ejemplo sencillo de su uso:

import merge_in_memory as mim_module 

str1 = """line 1 
line 2""" 
str2 = """line 1 
line 2 changed""" 

merger = mim_module.Merger() 
print merger.diff_make(str1, str2) 

Esta salida voluntad:

--- 
+++ 
@@ -1,2 +1,2 @@ 
line 1 
-line 2 
+line 2 changed 

diffs son simplemente cadenas (generadores en lugar de bronceado, ya que están utilizando las difflib) Usted puede crear una número de diffs y aplicarlos a la vez (es decir.avance rápido a través de un historial o seguimiento atrás) con la función diff_apply_bulk().

Para revertir en el historial, simplemente asegúrese de que el atributo reverse esté establecido en True al llamar a diff_bulk() o diff_apply_bulk. Por ejemplo:

merge = self.inline_merge.diff_apply_bulk(text3, [diff1, diff2], reverse=True) 

Si usted comienza con texto1 y texto2 generados y text3 con dif1 y dif2, a continuación, Texto1 se reconstruye con la línea de código anterior. Tenga en cuenta que la lista de diferencias todavía está en orden ascendente. Una 'fusión', es decir. aplicar un diff a una cadena, es en sí mismo una cadena.

Todo esto me permite almacenar diffs en la base de datos como simples VARCHAR (o lo que sea que tenga). Puedo sacarlos en orden y aplicarlos en cualquier dirección para generar el texto que quiero, siempre que tenga un punto de partida.

Por favor, siéntanse libres de dejar ningún comentario sobre esto, ya que es mi primer módulo de Python.

Gracias,

ParagonRG

1

Eche un vistazo a libgit. Es una interfaz C (y cualquier otro idioma) que le permite manipular un repositorio git de varias maneras.

Parece muy bajo nivel, por lo que llegar a comprometerse realmente, diff y demás puede ser tedioso, pero al menos tiene una función para add a blob to the repo without it needing to be on disk.

La alternativa, por supuesto, es crear un repositorio normal basado en archivos y trabajar copiando y volviendo cosas entre la base de datos y el sistema de archivos usando llamadas os.system.

Cuestiones relacionadas