Se a reversão de um patch for bem-sucedida, isso sempre significa que o patch foi totalmente aplicado?

9

Isso é abordado em duas perguntas: ' Verifique se um arquivo ou pasta já foi corrigido ' e ' Faça o patchretorno 0 ao ignorar um patch já aplicado ', no entanto, nenhuma das respostas foi satisfatória.

Estou escrevendo um script e quero testar o seguinte para um patch:

Totalmente aplicado: continue

Parcialmente aplicado: exit

Não aplicado: se puder ser aplicado com êxito, faça-o e continue; caso contrário, saia

O problema está lidando com o caso parcialmente aplicado:

mkdir test && cd test

cat << EOF > foobar.patch
--- /dev/null
+++ foo
@@ -0,0 +1 @@
+foo
--- /dev/null
+++ bar
@@ -0,0 +1 @@
+bar
EOF

patch --forward -i foobar.patch
rm foo

Portanto, a barra existe, mas o foo não existe, porque em algum momento foi removido. Agora, se eu aplicar o patch adiante em uma execução a seco, o código de saída é 1, pois não foi aplicado com sucesso.

$ patch --dry-run --forward --force -i foobar.patch
checking file foo
The next patch would create the file bar,
which already exists!  Skipping patch.
1 out of 1 hunk ignored
$ echo $?
1

Isso não me diz se o patch foi totalmente aplicado, apenas que falhou no teste a seco. Não sei por que isso está marcado como correto, como a resposta do stackoverflow. Eu tentei reverter, mas como é um script não interativo, ele só funcionou com força:

$ patch --dry-run --reverse --force -i foobar.patch
The next patch, when reversed, would delete the file foo,
which does not exist!  Applying it anyway.
checking file foo
Hunk #1 FAILED at 1.
1 out of 1 hunk FAILED
checking file bar
$ echo $?
1

Então, sempre é válido que, se eu tentar inverter forçosamente um patch em um processo a seco e for bem-sucedido, ele será totalmente aplicado e, se falhar, não será totalmente aplicado (ou aplicado)? Porque se sim, então eu posso fazer algo como

patch --dry-run --reverse --force -i foobar.patch ||
(patch --dry-run --forward --force -i foobar.patch &&
 patch --forward --force -i foobar.patch) ||
exit 1
Jay
fonte
O código fonte está sob seu controle, ou seja, você pode garantir que todos os patches sempre serão aplicados exatamente uma vez?
roaima 19/09/16
1
@roamia bem, o patch e o script estão sob meu controle. somente meu script aplicaria o patch.
Jay
Eu acho que é possível inventar um ponto de partida e um patch que tenha sucesso total nas direções para frente e para trás.
Jasen

Respostas:

3

Com esta diferença:

diff --git a/bar b/bar
new file mode 100644
index 0000000..e69de29
diff --git a/foo b/foo
new file mode 100644
index 0000000..257cc56
--- /dev/null
+++ b/foo
@@ -0,0 +1 @@
+foo

isto acontece:

$ cd /tmp/test
$ patch --forward -i foobar.patch
patching file bar
patching file foo
$ echo $?
0
$ rm bar
$ patch --dry-run --reverse --force -i foobar.patch
The next patch, when reversed, would delete the file bar,
which does not exist!  Applying it anyway.
checking file bar
checking file foo
$ echo $?
0

Portanto, a resposta para sua pergunta é não.

aferber
fonte
Obrigado por apontar isso. Descobri que posso corrigir esse caso usando, --posixpois ele definirá um erro quando não houver arquivo para corrigir. No entanto, o uso do modo POSIX não configurará um erro se um arquivo a ser excluído contiver conteúdo diferente do patch. Por exemplo, se eu executar esse comando reverso --posixe o arquivo bar contiver alguns dados, no modo POSIX, o arquivo não será excluído e nenhum erro ocorrerá. Portanto, minha correção é executada com e sem o modo posix e, se ambos estiverem ok, presumo que o patch foi aplicado com êxito. Vou atualizar minha pergunta para refletir isso.
Jay
Parece que --posixpode não ser a cura - tudo o que pensei que era. Se um arquivo for excluído por um patch e eu for executado --posix --reverse, será um erro que o arquivo não exista. Vou ter que investigar isso mais amanhã.
Jay