Subversion diff для архивированного XML-файла
Вопрос
Я использую MySQL Workbench для поддержки схемы базы данных для приложения.Тот Самый .mwb
файл, который использует Workbench, представляющий собой сжатый XML-документ, хранится в репозитории Subversion.
Subversion обрабатывает файл как двоичные данные, поэтому я не могу использовать svn diff
чтобы показать изменения, например, перед фиксацией.
Поскольку данные на самом деле представляют собой XML, я думаю, что в любом случае может быть какой-то способ показать разницу, возможно, какой-то скрипт, который разархивирует файл раньше, или какой-то плагин для svn diff
.
Идеальное решение позволило бы это:
$ svn diff db-model.mwb
или даже с помощью Meld:
$ meld db-model.mwb
Какой подход вы можете придумать для достижения этой цели?Возможно, у кого-то еще была эта проблема с отображением различий для архивированных текстовых файлов в Subversion.
Решение
Subversion позволяет вам использовать внешние инструменты для определения различий .Что вы можете сделать, это написать сценарий-оболочку и сообщить Subversion использовать его в качестве своей команды "diff".Ваша оболочка проанализирует аргументы, которые она получает от Subversion, чтобы выбрать "левое" и "правое" имена файлов, поработать с ними и вернуть код ошибки, который Subversion интерпретирует как успех или неудачу.В вашем случае программа-оболочка может разархивировать XML-файлы и передать распакованные результаты в "diff" или другой инструмент по вашему выбору.
Subversion будет отказываться от различных файлов, которые были обнаружены как "двоичные" при их возврате.Опция "--force" позволяет вам переопределить эту проверку, поэтому ваш сценарий-оболочка будет запущен, даже если входные файлы возвращены в виде двоичных файлов.
Другие советы
Я написал скрипт diff для файлов workbench, который может быть интегрирован с TortoiseSVN и TortoiseGit, который будет точно делать то, что предлагает Джим Льюис:Извлеките фактический XML-файл из архива и отредактируйте его.
Сценарий также устранит все ptr-Атрибутивный шум в diff.Слияние невозможно и было бы немного сложнее (узнайте, как ptr-атрибуты будут вести себя правильно, повторно упакуйте XML в архив, что с другими метаданными в архиве?, ...)
Скрипт на Python доступен в pastebin под управлением CC-BY 3.0.:
# 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)