Mantenha o patch em sincronia com a mudança de fonte

3

Existe alguma opção padrão para criar 'patch' P que funciona no arquivo F de tal forma que ele continuará funcionando corretamente quando o arquivo F for alterado para F '.

Então eu vou ter algum mecanismo que irá mudar P em P 'para que P' (F ') produza a mesma mudança que P (F), ou, preferencialmente, eu terei P resiliente para que possa ser usado para ambos F & F '.

Atualmente, estou usando a expressão regular search and replace para criar esse patch, mas imagino que exista uma maneira padrão de fazer isso.

    
por majkinetor 07.01.2013 / 10:01

2 respostas

2

Esse problema é conhecido como mesclagem. Você tem um arquivo original A e duas versões modificadas B e C, e você quer fazer uma versão D que combine ambas as modificações. Isso só funciona se as alterações forem independentes; caso contrário, a mesclagem é um processo manual. O gerenciamento de mesclagens de alterações simultâneas no código-fonte é uma tarefa frequente na engenharia de software.

Em casos simples, um patch produzido por diff já funcionará se o arquivo de origem for alterado. O utilitário patch permite algum “fuzz”: se você fizer um diff de A para B, e as áreas afetadas por esse diff forem idênticas (mas possivelmente em diferentes deslocamentos no arquivo) em A e C, então o patch será aplicado limpamente em C. Isso funciona bem, desde que as áreas alteradas em B e C não estejam nos mesmos locais (deve haver uma separação de algumas linhas).

Quando os patches não se aplicam corretamente, a mesclagem é um problema difícil e específico do domínio. Por exemplo, considere estas duas alterações:

A         B         C
a=2       a=3       b=2
x=a       x=a       x=b

Os seres humanos tendem a identificar o padrão que B mudou 2 para 3 e C renomeou a para b , portanto, o resultado da mesclagem deve ser b=3 , x=b . Mas as ferramentas automatizadas provavelmente marcarão a primeira linha como um conflito, porque ela foi modificada de duas maneiras diferentes.

Escrever um patch que “faz algo sensato” para B e C é um problema difícil (AI-completo). Em casos práticos, para muitas situações típicas, usar diff -u A B como o patch tende a funcionar e produzir o D desejado de C, ou falhar com um erro declarando que o patch não se aplica de forma limpa.

    
por 08.01.2013 / 01:54
3

Eu realmente não recomendaria usar sed para tal coisa. O problema é que, mesmo que um patch seja aplicado, ele pode estar com um "fuzz" - o que significa que algumas das linhas de contexto não são correspondidas perfeitamente. Embora isso muitas vezes signifique que o código subjacente mudou um pouco, também pode significar que o patch foi aplicado em um lugar errado (já vi isso acontecer, não foi legal nem fácil depurar).

Além disso, mesmo que o patch seja aplicado corretamente, é provável que não faça mais sentido semanticamente. Para entender isso, você deve estar ciente das alterações que ocorreram no código corrigido.

Pelas razões expostas, considera-se uma boa prática rever pelo menos tudo o que se aplica a um fuzz (e provavelmente também verificar superficialmente o que se aplica a um offset). Ter mais do que as 3 linhas de contexto padrão também pode ser uma boa ideia.

Tendo passado pelo grande aviso de gordura, uma das maneiras de fazer isso de forma relativamente indolor é usar um sistema de controle de versão, provavelmente um sistema distribuído avançado como, por exemplo, mercurial ou git . As opiniões sobre a escolha entre estes dois variam, o Mercurial é um pouco mais parecido com o CVS e SVN mais antigos do que o Git, e sem dúvida também tem uma curva de aprendizado melhor (o Git supostamente é mais rico em recursos).

No Mercurial temos a extensão Mercurial Queues (MQ) exatamente para esses casos. A postagem no blog deste Steve Losh é uma introdução bastante agradável usando o MQ e outra boa leitura é este guia para o MQ no site do desenvolvedor do Mozilla.

Às vezes, patchutils pode ser útil também.

    
por 07.01.2013 / 12:09

Tags