O 'patch' funciona com contexto assimétrico?

2

Eu tenho o arquivo a :

This
file
does
have
an error
in it
that
needs
to be
fixed.

e um arquivo semelhante b :

This
file
does
have
no error
in it
that
needs
to be
fixed.

Eu posso criar um diff unificado com diff -u a b :

--- a   2018-01-03 14:20:22 +0100
+++ b   2018-01-03 14:20:37 +0100
@@ -2,7 +2,7 @@
 file
 does
 have
-an error
+no error
 in it
 that
 needs

E também posso reduzir o contexto para uma linha em qualquer lado com diff -u1 a b :

--- a   2018-01-03 14:20:22 +0100
+++ b   2018-01-03 14:20:37 +0100
@@ -4,3 +4,3 @@
 have
-an error
+no error
 in it

Esses dois patches podem ser aplicados corretamente com patch . No entanto, não encontrei uma maneira de fazer com que diff produzisse um patch com contexto assimétrico. Eu estou supondo que não pode fazer isso. Então eu tentei remover algum contexto manualmente, fazer um patch com duas linhas de contexto antes da mudança e uma depois:

--- a   2018-01-03 14:20:22 +0100
+++ b   2018-01-03 14:20:37 +0100
@@ -3,4 +3,4 @@
 does
 have
-an error
+no error
 in it

Isso parece válido para mim no formato unificado . No entanto, patch reclama que precisou recorrer à difusão:

patching file a
Hunk #1 succeeded at 3 with fuzz 1.

Estou fazendo algo errado ou é (GNU) patch realmente quebrado para contextos assimétricos porque ninguém imaginou que eles seriam usados, já que diff não pode torná-los assim mesmo?

Também é interessante que o patch funcione se eu reverter a assimetria, ou seja, uma linha antes e duas depois:

--- a   2018-01-03 14:20:22 +0100
+++ b   2018-01-03 14:20:37 +0100
@@ -4,4 +4,4 @@
 have
-an error
+no error
 in it
 that
    
por Karel Vlk 03.01.2018 / 15:06

2 respostas

0

O padrão POSIX não fornece uma maneira de gerar contextos assimétricos. O patch GNU está sendo útil em um caso, aceitando um patch malformado.

A propósito, a página de manual indicada na pergunta faz uma afirmação incorreta:

At present, only GNU diff can produce this format and only GNU patch can automatically apply diffs in this format. For proper operation, patch typically needs at least three lines of context.

O erro ainda está no diffutils arquivo de informações .

patch POSIX lida com diffs unificados.

    
por 03.01.2018 / 22:13
0

O GNU patch simplesmente não gosta quando há mais contexto de prefixo que o contexto de sufixo. Uma solução simples, mas feia, é converter a primeira linha de contexto em uma alteração sem operação como esta:

--- a   2018-01-03 14:20:22 +0100
+++ b   2018-01-03 14:20:37 +0100
@@ -3,4 +3,4 @@
-does
+does
 have
-an error
+no error
 in it

Isso remove todo o contexto do prefixo. Tudo bem quando há mais contexto de sufixo.

Eu passei pelo código-fonte de patch e encontrei o peça ofensiva . Sem entender muito profundamente, criei uma correção simples semelhante à forma como o contexto do prefixo já foi tratado no código. Aqui está minha saída de git diff (um patch para patch ):

diff --git a/src/patch.c b/src/patch.c
index bba7e0e..e661af1 100644
--- a/src/patch.c
+++ b/src/patch.c
@@ -1171,7 +1171,7 @@ locate_hunk (lin fuzz)
     else if (prefix_fuzz < 0)
       prefix_fuzz = 0;

-    if (suffix_fuzz < 0)
+    if (suffix_fuzz < 0 && pch_first () + pat_lines > input_lines)
       {
    /* Can only match end of file.  */
    offset = first_guess - (input_lines - pat_lines + 1);
@@ -1184,6 +1184,8 @@ locate_hunk (lin fuzz)
    else
      return 0;
       }
+    else if (suffix_fuzz < 0)
+      suffix_fuzz = 0;

     min_offset = max_pos_offset < 0 ? first_guess - max_where
           : max_neg_offset < 0 ? first_guess - min_where
diff --git a/tests/asymmetric-hunks b/tests/asymmetric-hunks
index d6979d9..86e4ef9 100644
--- a/tests/asymmetric-hunks
+++ b/tests/asymmetric-hunks
@@ -77,5 +77,4 @@ seq 1 5 > a

 check 'patch < a.diff' <<EOF
 patching file a
-Hunk #1 succeeded at 2 with fuzz 1.
 EOF

Como apontou @Patrick Mevzek, já existe um teste de regressão para contextos assimétricos. Então, isso também é corrigido para não esperar fuzzing. Infelizmente, o teste de mesclagem também falha em um caso e não sei por quê. Eu acho que não posso enviar o patch por causa disso. Seria bom se alguém com mais discernimento pudesse encontrar uma solução melhor.

    
por 05.01.2018 / 19:51

Tags