2012-05-04 1 views
5

Ich arbeite an einem Projekt, bei dem Menschen Geschichten einreichen und andere Leute dazu beitragen können. Anstatt einfach einen Eintrag in der Datenbank zu bearbeiten, möchte ich lieber die Änderungen speichern, die von den Benutzern vorgenommen werden, als die gesamten neuen Änderungen. Dann kann ich diffs dynamisch anwenden, wenn Leute zu einer vorherigen Version zurückkehren möchten. Ich kann auch Benutzern, die Editoren sind, einfach nur den geänderten Text präsentieren, damit sie direkt zu den Änderungen springen können.Wie kann ich string und Patch/merge Zeichenfolgen anstelle von Dateien?

Ich bin mir bewusst, wie man Diff-Dateien nimmt und andere Dateien mit ihnen patcht. Aber ich mache eine Web-App mit Python und Django, und ich werde all diese Diffs in einer MySQL-Datenbank speichern. Angesichts der Tatsache, dass die Leistung für diese App kein großes Problem darstellt, bin ich bereit, die Daten aus der DB zu ziehen, Dateien zu erstellen und git diff und patch für diese Dateien auszuführen.

Gibt es einen besseren Weg als neue Dateien zu erstellen und sie jedes Mal zu löschen, wenn ich eine neue Version erstellen oder einen neuen Diff anwenden möchte? Gibt es eine Möglichkeit, Diffs auf einem geraden Text statt auf Dateien auszuführen? Z.B. Setzen von Variablen in bash, um den Inhalt von (was wäre) eine Datei (aber ist eigentlich Daten aus der DB), und läuft git diff auf ihnen? Ich möchte diese Aktionen aus einer Python-Datei steuern, nachdem der Benutzer ein Formular übermittelt hat.

Ich bin wirklich nur auf der Suche nach einem guten Weg, um mit diesem Problem zu beginnen, so würde jede Hilfe sehr geschätzt werden.

Vielen Dank für Ihre Zeit,

ParagonRG

+4

Sie können sicher die Grundsätze der Speicherung Diffs anstelle des vollständigen Wortlauts in der Datenbank übernehmen, aber es ist ein wenig seltsam, dass Sie eine VCS für den Zweck verwenden wollen würde. .. (haben Sie sich http://docs.python.org/library/difflib.html angesehen)? – geoffspear

+0

Danke, schau dir das jetzt an! – Paragon

+0

Leider difflib war nicht erlaubt, Text von Diffs neu zu erstellen, es sei denn Diffs, die den gesamten Text und seine Änderungen speichern. Ich habe deshalb ein Modul dafür gebaut; Bitte sehen Sie meine Antwort unten. – Paragon

Antwort

4

Ich habe ziemlich viel nach einer Lösung dafür gesucht. Python's difflib ist ziemlich legitim, aber leider neigt es dazu, dass die Diff-Strings die gesamten ursprünglichen Strings mit Aufzeichnungen dessen, was geändert wurde, erfordern. Das unterscheidet sich von einem Git Diff, wo Sie nur sehen, was geändert wurde und einige zusätzliche Kontext. difflib bietet auch eine Funktion namens unified_diff, die zwar ein kürzeres diff bietet, aber keine Funktion zum Neuerstellen einer Zeichenfolge aus einer Zeichenfolge und einem diff bereitstellt. Z.B. Wenn ich ein diff aus text1 und text2, diff1 genannt, gemacht habe, dann konnte ich text2 aus text1 und diff1 nicht erzeugen.

Ich habe daher ein einfaches Python-Modul gemacht, das es ermöglicht, Strings sowohl vorwärts als auch rückwärts von einer einzigen Zeichenkette und den zugehörigen Diffs zu rekonstruieren. Es heißt merge_in_memory und kann unter https://github.com/danielmoniz/merge_in_memory gefunden werden. Ziehen Sie einfach das Repository und führen Sie die Datei setup.py aus.

Ein einfaches Beispiel für seine Nutzung:

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) 

erhalten Sie folgende Ausgabe:

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

diffs sind einfach Strings (eher tan Generatoren, wie sie sind, wenn difflib verwenden) .Sie ein erstellen Anzahl der Diffs und gelten sie sofort (dh.mit der Funktion diff_apply_bulk() vorwärts oder rückwärts spulen.

Um in den Verlauf zurückzukehren, stellen Sie einfach sicher, dass das Attribut reverse auf True gesetzt ist, wenn entweder diff_bulk() oder diff_apply_bulk aufgerufen wird. Zum Beispiel:

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

Wenn Sie mit text1 und text2 erzeugt und text3 mit diff1 und diff2 starten, dann wird text1 mit dem obigen Codezeile wieder aufgebaut. Beachten Sie, dass die Liste der Diffs immer noch in aufsteigender Reihenfolge ist. Eine 'Zusammenführung', d. Anwenden eines Diff auf eine Zeichenfolge, ist selbst eine Zeichenfolge.

All dies erlaubt mir, Diffs in der Datenbank als einfache VARCHARs (oder was auch immer) zu speichern. Ich kann sie in der richtigen Reihenfolge herausziehen und in beide Richtungen anwenden, um den gewünschten Text zu erzeugen, solange ich einen Startpunkt habe.

Bitte zögern Sie keine Kommentare zu diesem Thema, da es mein erstes Python-Modul ist.

Danke,

ParagonRG

1

Werfen Sie einen Blick auf libgit. Es ist eine C-Schnittstelle (und jede andere Sprache), mit der Sie ein Git-Repository auf verschiedene Arten bearbeiten können.

Es scheint ziemlich Low-Level, so dass es tatsächlich zu commit, diff und so weiter könnte langweilig sein, aber es hat zumindest eine Funktion zu add a blob to the repo without it needing to be on disk.

Die Alternative besteht natürlich darin, ein normales dateibasiertes Repository und eine Arbeitskopie zu erstellen und zwischen der Datenbank und dem Dateisystem unter Verwendung der os.system Aufrufe hin- und herzuspringen.

Verwandte Themen