Фильтрация различий с регулярным выражением - PullRequest
10 голосов
/ 22 ноября 2011

Кажется, что было бы чрезвычайно удобно иметь возможность фильтровать различия, чтобы не отображать тривиальные изменения.Я хотел бы написать регулярное выражение, которое будет выполняться в строке, а затем передать ему другую строку, которая использует захваченные аргументы для генерации канонической формы.Если строки до и после производят один и тот же вывод, то они будут удалены из diff.

Например, я работаю над базой кода PHP, где значительное количество обращений к массиву записывается как my_array[my_key]когда они должны быть my_array["my_key"] для предотвращения проблем, если определена константа my_key.Было бы полезно сгенерировать diff, в котором единственным изменением в строке не было добавление кавычек.

Я не могу изменить их все сразу, так как у нас нет ресурсов для тестирования всегокод базы, поэтому я исправляю это всякий раз, когда я изменяю функцию.Как мне этого добиться?Есть ли что-то похожее на это, что я могу использовать для достижения аналогичного результата.Например, более простой метод может состоять в том, чтобы пропустить каноническую форму и просто посмотреть, преобразован ли вход в выход.Кстати, я использую Git

Ответы [ 7 ]

7 голосов
/ 22 ноября 2011
$ git diff --help

-G<regex>
    Look for differences whose added or removed line matches the given <regex>.

EDIT

После некоторых тестов у меня есть что-то вроде

git diff -b -w --word-diff-regex='.*\[[^"]*\]'

Тогда у меня есть вывод как:

diff --git a/test.php b/test.php
index 62a2de0..b76891f 100644
--- a/test.php
+++ b/test.php
@@ -1,3 +1,5 @@
<?php

{+$my_array[my_key]+} = "test";

?>
diff --git a/test1.php b/test1.php
index 62a2de0..6102fed 100644
--- a/test1.php
+++ b/test1.php
@@ -1,3 +1,5 @@
<?php

some_other_stuff();

?>

Может быть, это поможет вам. Я нашел это здесь http://www.rhinocerus.net/forum/lang-lisp/659593-git-word-diff-regex-lisp-source.html, и есть больше информации об этой теме

EDIT2

git diff -G'\[[A-Za-z_]*\]' --pickaxe-regex
6 голосов
/ 28 ноября 2011

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

Я предполагаю, что вы работаете в Linux; если нет, вы можете настроить эту концепцию в соответствии со своей средой. Допустим, у вас есть репозиторий Git, где HEAD имеет файл file05, содержащий:

line 26662: $my_array[my_key]

И файл file06, содержащий:

line 19768: $my_array[my_key]
line 19769: $my_array[my_key]
line 19770: $my_array[my_key]
line 19771: $my_array[my_key]
line 19772: $my_array[my_key]
line 19773: $my_array[my_key]
line 19775: $my_array[my_key]
line 19776: $my_array[my_key]

Вы меняете file05 на:

line 26662: $my_array["my_key"]

И вы меняете file06 на:

line 19768: $my_array[my_key]
line 19769: $my_array["my_key"]
line 19770: $my_array[my_key]
line 19771: $my_array[my_key]
line 19772: $my_array[my_key]
line 19773: $my_array[my_key]
line 19775: $my_array[my_key2]
line 19776: $my_array[my_key]

Используя следующий скрипт оболочки, давайте назовем его mydiff.sh и поместим его где-нибудь в нашем PATH:

#!/bin/bash
echo "$@"
git diff-files --patch --word-diff=porcelain "${5}" | awk '
/^-./ {rec = FNR; prev = substr($0, 2);}
FNR == rec + 1 && /^+./ {
    ln = substr($0, 2);
    gsub("\\[\"", "[", ln);
    gsub("\"\\]", "]", ln);
    if (prev == ln) {
        print " " ln;
    } else {
        print "-" prev;
        print "+" ln;
    }
}
FNR != rec && FNR != rec + 1 {print;}
'

Выполнение команды:

GIT_EXTERNAL_DIFF=mydiff.sh git --no-pager diff

Будет выводить:

file05 /tmp/r2aBca_file05 d86525edcf5ec0157366ea6c41bc6e4965b3be1e 100644 file05 0000000000000000000000000000000000000000 100644
index d86525e..c2180dc 100644
--- a/file05
+++ b/file05
@@ -1 +1 @@
 line 26662: 
 $my_array[my_key]
~
file06 /tmp/2lgz7J_file06 d84a44f9a9aac6fb82e6ffb94db0eec5c575787d 100644 file06 0000000000000000000000000000000000000000 100644
index d84a44f..bc27446 100644
--- a/file06
+++ b/file06
@@ -1,8 +1,8 @@
 line 19768: $my_array[my_key]
~
 line 19769: 
 $my_array[my_key]
~
 line 19770: $my_array[my_key]
~
 line 19771: $my_array[my_key]
~
 line 19772: $my_array[my_key]
~
 line 19773: $my_array[my_key]
~
 line 19775: 
-$my_array[my_key]
+$my_array[my_key2]
~
 line 19776: $my_array[my_key]
~

Этот вывод не показывает изменения для добавленных кавычек в file05 и file06. Внешний скрипт diff в основном использует команду Git diff-files для создания патча и фильтрует вывод через скрипт GNU awk для манипулирования им. Этот пример сценария не обрабатывает все различные комбинации старых и новых файлов, упомянутых для GIT_EXTERNAL_DIFF, и не выводит действительный патч, но этого должно быть достаточно для начала работы.

Вы можете использовать регулярные выражения Perl , Python difflib или все, что вам удобно для реализации внешнего инструмента сравнения, который соответствует вашим потребностям.

4 голосов
/ 16 февраля 2016

grepdiff может использоваться для фильтрации блоков в файле diff.

$ git diff -U1 | grepdiff 'console' --output-matching=hunk

Показывает только те фрагменты, которые соответствуют данной строке "console".

2 голосов
/ 30 ноября 2011

из моего собственного git --help

- word-diff-regex = <regex>

Используйте <regex>, чтобы решить, что такое слово, вместо рассмотренияпробеги без пробелов, чтобы быть словом.Также подразумевает --word-diff, если он уже не был включен.Каждое неперекрывающееся совпадение <regex> считается словом.Все, что находится между этими совпадениями, считается пробелом и игнорируется (!) Для нахождения различий.Вы можете добавить |[^[:space:]] к своему регулярному выражению, чтобы убедиться, что оно соответствует всем непробельным символам.Совпадение, которое содержит символ новой строки, молча обрезается (!) На символе новой строки.Регулярное выражение также можно установить с помощью драйвера diff или опции конфигурации, см. Gitattributes (1) или git-config (1).Предоставление этого явно переопределяет любой драйвер diff или настройку конфигурации.Драйверы Diff переопределяют параметры конфигурации.

1 голос
/ 26 ноября 2011

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

Некоторые утилиты diff, такие как, например, meld, позволяют скрыть «незначительную» разницу и поставляются с набором шаблонов по умолчанию, напримерскрыть только пробельные изменения.Думаю, это почти то, что вы хотите.

0 голосов
/ 26 ноября 2011

Если целью является минимизация тривиальных различий, вы можете рассмотреть наш SmartDifferencer инструмент.

Эти инструменты сравнивают синтаксис языка , а не макет, поэтому многие тривиальныеИзменения (макет, измененные комментарии, даже изменение радиуса на числах) игнорируются и не сообщаются.Каждый инструмент имеет полный синтаксический анализатор языка;есть версия для многих языков, включая PHP.

Он не будет обрабатывать пример $ FOO [abc] как "семантически идентичный" $ FOO ["abc"], потому что это не так.Если abc actaully имеет определение константы, то $ FOO ["abc"] не является семантически эквивалентным.

0 голосов
/ 24 ноября 2011

Я использую подход, который комбинирует git diff и применяет регулярное выражение, сопоставляющее результаты.В некотором коде тестирования (PERL) я знаю, что тестирование успешно, когда OutputFingerprint, сохраненный в результирующих файлах тестов, не изменился.

Сначала я делаю

my $matches = `git diff -- mytestfile`

а затем оцените результат:

if($matches =~ /OutputFingerprint/){
  fail();
  return 1;
}else{
  ok();
  return 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...