Краткое сравнение и частичное объединение деревьев конфигурации - PullRequest
2 голосов
/ 23 ноября 2010

Я хотел бы кратко различать дерево файлов конфигурации, большинство из которых являются плоскими (то есть пары ключ / значение), но некоторые из которых являются XML, скриптами bash или пользовательскими форматами. Информация о конфигурации почти всегда не упорядочена и может содержать пробелы и комментарии.

Для плоских файлов выполнение различий без пробелов или комментариев к отсортированному выводу очень близко к тому, что я хотел бы сделать. Для XML есть некоторые инструменты доступные . Однако некоторые пользовательские форматы имеют, например, вложенная конфигурация Порядок ключей не важен, порядок подразделов не важен, но древовидная структура (очень похожа на XML). Другие очень зависят от заказа.

Как бы вы поступили так, если бы вам приходилось делать это часто? Есть ли какие-либо инструменты, которые являются достаточно общими? А как насчет моего собственного решения? Количество форматов не так уж и велико (конечно, не так плохо, как / etc), а значение по умолчанию плоское - возможно, какое-то соответствие libmagic и имени файла в сочетании с пользовательскими парсерами? Кто-нибудь пробовал что-то подобное?

Один из подходов состоит в том, чтобы попытаться решить 95% проблемы, выполнив приличную работу с файлами с вложенной, но неупорядоченной структурой и со специальным корпусом нескольких других типов с помощью существующих инструментов. Можете ли вы предложить подход к простым вложенным файлам, в основном работающий?

Некоторые примеры:

com.example.resource.host=foo
com.example.resource.port=8080

против

com.example.resource.port=8080
com.example.resource.host=bar
//com.example.network.timeout=600
com.example.network.timeout=300

должен производить

< com.example.resource.host=foo
---
> com.example.resource.host=bar
> //com.example.network.timeout=600
> com.example.network.timeout=300

или опционально:

< com.example.resource.host=foo
---
> com.example.resource.host=bar
> com.example.network.timeout=300

как и следовало ожидать. Тем не менее, что-то вроде:

Conf com.example.resource =
    Conf host = foo;
    Conf port = 8080;
;

против

Conf com.example.resource =
    Conf port = 8080;
    Conf host = bar;
;
Conf com.example.network =
    Conf timeout = 300;
;

Должно также работать:

<     Conf host = foo
---
>     Conf host = bar
> Conf com.example.network =
>     Conf timeout = 300;
> ;

1 Ответ

1 голос
/ 03 марта 2011

Каждый из ваших файлов конфигурации имеет синтаксис и подразумеваемую семантику. Похоже, что вы хотите сделать, это сравнить файлы конфигурации по подразумеваемой семантике, а не по тексту.

Единственный способ сделать это - создать собственный анализатор для каждого типа файла конфигурации. Затем вам нужно сравнить файлы в соответствии с подразумеваемой семантикой.

В общем, это довольно сложно сделать, конечно же, для реальных языков программирования. Мы предлагаем компромиссное решение, вызывающее SmartDifferencers , которое анализирует код в соответствии с точным синтаксисом языка, а затем сравнивает их в соответствии со структурами языка (например, выражениями, операторами, объявлениями, методами, ...), сообщая о различиях в качестве абстрактных операций редактирования (перемещение, копирование, удаление, вставка, переименование идентификатора в блоке). Это дает succint deltas (то, что вы просили) в терминах, которые имеют смысл для программистов, а не просто «этот блок строк изменился каким-то образом», типичный для diff.

Эти инструменты знают синтаксис языка, и они знают крошечный бит семантики; в частности, мы пытаемся (и мы не полностью готовы для всех) справиться с понятием коммутативных языковых элементов. В Java порядок методов в классе не имеет значения. В вашем случае порядок некоторых элементов конфигурации скорее всего не имеет значения. Наша техника может принять это во внимание.

Чтобы сделать это для того, что вы хотите сделать, вам нужен отдельный анализатор для каждого типа файла конфигурации и отдельные знания для каждого типа, когда вы можете безопасно перемещать команды. Вам нужен отдельный инструмент для каждого типа файла конфигурации, чтобы сделать это правильно. (Те файлы, которые основаны на XML, в действительности нуждаются в отдельных инструментах, потому что вы пытаетесь различать как семантику, так и синтаксис.). Я думаю, что вашим идеальным решением являются SmartDifferencers для каждого из ваших типов файлов конфигурации.

...