2009-09-01 2 views
10

Я использую MySQL Workbench для поддержки схемы базы данных для приложения. Файл .mwb, который использует Workbench, который является заархивированным XML-документом, хранится в репозитории Subversion.Subversion diff для zipped xml file

Файл обработан как двоичные данные Subversion, поэтому я не могу использовать svn diff, чтобы показать изменения, например, перед совершением.

Поскольку данные действительно являются XML, я думаю, что может быть какой-то способ показать diff в любом случае, может быть, какой-то скрипт, который распаковывает файл раньше, или какой-то плагин до svn diff.

Идеальное решение позволило бы это:

$ svn diff db-model.mwb 

или даже с помощью оплавления:

$ meld db-model.mwb 

Какой подход вы можете думать, чтобы это сделать? Возможно, у кого-то еще была проблема с отображением diff для архивных текстовых файлов в Subversion.

+0

из любопытства Oskar, вы когда-нибудь открыть путь для визуализации различий в качестве MWB, что на самом деле доказано полезным? –

+0

Брэд, нет, к сожалению, я этого не сделал. В основном из-за того, что в дереве XML содержались сгенерированные идентификаторы, которые сильно менялись каждый раз, когда модель была изменена/обновлена, поэтому сравнение деревьев было очень неудобным. Это было, однако, два года назад, так что все могло измениться? – Oskar

+0

Нет, все по-прежнему кажется тем же самым извращением XML, которым они всегда были. Эти атрибуты ptr по-прежнему изменяются при каждом сохранении, и, похоже, нет никакой другой информации, доступной в легко читаемом формате. По-прежнему теоретически возможны различия, но это будет огромная работа. –

ответ

8

Subversion позволяет вам использовать external differencing tools. Что вы можете сделать, это написать сценарий оболочки и сообщить Subversion использовать его как команду «diff». Ваша обертка проанализирует аргументы, которые она получает из Subversion, чтобы выбрать «левые» и «правильные» имена файлов, оперировать и вернуть код ошибки, который Subversion будет интерпретировать как успех или неудачу. В вашем случае оболочка может распаковать файлы XML и передать распакованные результаты в «diff» или другой инструмент по вашему выбору.

Subversion будет препятствовать разным файлам, которые были обнаружены как «двоичные», когда они были отмечены. Параметр «-force» позволяет вам переопределить эту проверку, поэтому ваш скрипт-оболочка будет запущен, даже если вход файлы проверяются как двоичные файлы.

+0

Спасибо. Оказывается, это было довольно сложно. Subversion не будет вызывать никаких внешних инструментов разнесения, пока файл имеет свойство svn: mime-type, установленное на что-то «не читаемое человеком» (например, мои zip-файлы). Но удаление этого свойства приведет к тому, что zip-файл не будет версироваться как двоичный файл, что не так хорошо, верно? – Oskar

+0

Я бы не удалял свойство - SVN может понадобиться по другим причинам. Вы попробовали параметр «--force», чтобы получить SVN для запуска вашего сценария оболочки diff? –

+0

--force сделал трюк! – Oskar

2

Я написал сценарий diff для файлов workbench, которые могут быть интегрированы с TortoiseSVN и TortoiseGit, которые точно будут делать то, что предлагает Джим Льюис: Извлеките фактический XML из архива и проанализируйте его.

Сценарий также устранит все ptr -Attribute noise в diff. Слияние не возможно, и будет немного сложнее (выяснить, как PTR -attributes будет вести себя, упаковывайте XML в архив, что с другими метаданными в архиве ?, ...)

сценарий питон доступен в Pastebin под CC-BY 3.0:

http://pastebin.com/AcD7dBNH

# extensions: mwb 
# TortoiseSVN Diff script for MySQL Workbench scheme files 
# 2012 by Oliver Iking, Z-Software GmbH, oliverikingREPLACETHISWITHANATz-software.net, http://www.z-software.net/ 
# This work is licensed under a Creative Commons Attribution 3.0 Unported License - http://creativecommons.org/licenses/by/3.0/ 

# Will produce two diffable documents, which don't resemble the FULL MWB content, but the scheme relevant data. 
# Merging is not possible 

# Open your TortoiseSVN (or TortoiseSomething) settings, go to the "Diff Viewer" tab and click on "Advanced". Add 
# a row with the extension ".mwb" and a command line of 
# "path\to\python.exe" "path\to\diff-mwb.py" %base %mine 
# Apply changes and now you can diff mysql workbench scheme files 

import sys 
import zipfile 
import os 
import time 
import tempfile 
import re 

# mysql workbench XML will have _ptr_ attributes which are modified on each save for almost each XML node. Remove the visual litter, 
# make actual changes stand out. 
def sanitizeMwbXml(xml): 
    return re.sub('_ptr_="([0-9a-fA-F]{8})"', '', xml) 

try: 
    if len(sys.argv) < 2: 
     print("Not enough parameters, cannot diff documents!") 
     sys.exit(1) 

    docOld = sys.argv[1] 
    docNew = sys.argv[2] 

    if not os.path.exists(docOld) or not os.path.exists(docNew): 
     print("Documents don't exist, cannot diff!") 
     sys.exit(1) 

    # Workbench files are actually zip archives 
    zipA = zipfile.ZipFile(docOld, 'r') 
    zipB = zipfile.ZipFile(docNew, 'r') 

    tempSubpath = os.tempnam(None,"mwbcompare") 

    docA = os.path.join(tempSubpath, "mine.document.mwb.xml") 
    docB = os.path.join(tempSubpath, "theirs.document.mwb.xml") 

    os.makedirs(tempSubpath) 

    if os.path.exists(docA) or os.path.exists(docB): 
     print("Cannot extract documents, files exist!") 
     sys.exit(1) 

    # Read, sanitize and write actual scheme XML contents to temporary files 

    docABytes = sanitizeMwbXml(zipA.read("document.mwb.xml")) 
    docBBytes = sanitizeMwbXml(zipB.read("document.mwb.xml")) 

    docAFile = open(docA, "w") 
    docBFile = open(docB, "w") 

    docAFile.write(docABytes) 
    docBFile.write(docBBytes) 

    docAFile.close() 
    docBFile.close() 

    os.system("TortoiseProc /command:diff /path:\"" + docA + "\" /path2:\"" + docB + "\""); 

    # TortoiseProc will spawn a subprocess so we can't delete the files. They're in the tempdir, so they 
    # will be cleaned up eventually 
    #os.unlink(docA) 
    #os.unlink(docB) 

    sys.exit(0) 
except Exception as e: 
    print str(e) 
    # Sleep, or the command window will close 
    time.sleep(5) 
+1

Python 3 требует 'print (" ")' вместо 'print '" '. Кроме того, 'os.tempnam' удален, вместо этого я использую' tempfile.mkdtemp'. Наконец, мне пришлось обернуть 'zipA.read (...)' с помощью 'bytes.decode (zipA.read (" document ... "))'. –

Смежные вопросы