Essencialmente, eu estou procurando por uma ferramenta GNU / Linux, que poderia recursivamente iterar através de dois diretórios, encontrar mudanças de arquivos / adições / exclusões; e para todos os arquivos alterados, imprima um diff. Isso já pode ser feito por diff
eficientemente para arquivos de texto, mas não para arquivos binários grandes - Eu também gostaria de "diffs" eficientes entre arquivos binários incluídos no patch final (que, eu sei, é conhecido como Compressão delta binário - Wikipedia como subconjunto de codificação Delta - Wikipédia . Ou, em outras palavras, faça algo como descrito neste comentário "wishlist" (de CommandLineSyntax - xdelta - Google Project Hosting ):
Seria muito bom se o xdelta suportasse vários arquivos de correção. Algo como:
xdelta3 -r /path/folder1 /path/folder2 >allfilesrecursivepatch.xdelta
Para comparação recursiva de todos os arquivos na pasta1 e na pasta2 e criação de um único arquivo de correção para todos eles. E:
xdelta3 -r -d /path/folder1 <allfilesrecursivepatch.xdelta
Para aplicar o patch em todos os arquivos contidos na pasta1
Este recurso não existe, a julgar por Edição 21 - xdelta - Suporte a diff de diretório recursivo - Google Project Hosting , embora existam maneiras: a página de problemas tem várias sugestões para wrappers de script, mas eu prefiro manter as coisas independentes em uma única ferramenta.
O mais importante para mim seria a correção de uma parte do diretório do sistema de arquivos "ao vivo" como mostrado acima, devido ao meu caso de uso - descrito em mais detalhes abaixo e ilustrado com um script bash
que usa git
. / p>
Gostaria de poder atualizar um site estático em um host / webfarm baratinhos, que só permite a transferência por FTP (portanto, não rsync
e outros) com uma velocidade de transferência bastante baixa e permite apenas a execução de scripts PHP . Normalmente, eu preciso sincronizar de local / cliente / home para servidor / webhost, mas é claro que eu não quero carregar 200 MB cada vez que eu quero atualizar uma página :)
Eu poderia usar outlandishideas / sync · GitHub para "Sincronizar o conteúdo do diretório via HTTP usando PHP", mas além de apenas sincronizar do servidor para local, também somente arquivos inteiros são enviados: "Nenhuma tentativa é feita para enviar diffs; isto não é rsync". Da mesma forma, eu poderia usar o GNU FTPsync ; provavelmente poderia manipular a criação, modificação e exclusão de arquivos, mas tem o mesmo problema - somente arquivos inteiros serão enviados.
Em princípio, git
pode ser usado também - o script abaixo gera diretórios testdir_old
e testdir_new
e mostra que git
pode codificar as diferenças entre eles ( neste caso sendo "removido" ; adicionado 1024; modificado / adicionado 19; modificado inline 1200 ", ou total 3267 bytes de alteração ) como um" sneakernet "git bundle tem 4470 bytes de tamanho. Mas mesmo que eu pudesse persuadir o host a instalar o git
lá, eu ainda teria que manter um .git
repo no webhost para que o pacote fosse aplicado corretamente - e eu definitivamente não quero fazer isso, Eu não poderia poupar o uso extra de tamanho de arquivo; Além disso, parece que gerenciando arquivos binários grandes com o git - o Stack Overflow requer git annex
ou git bup
.. E colocar um script como o abaixo seria problemático porque git
recriaria novos hashes de revisão a cada vez, fazendo com que o pacote não se aplicasse de forma limpa.
Além disso, como no PHP, posso aparentemente " untar-gz sem exec ()? - Stack Overflow ", talvez valha a pena tentar determinar as alterações no diretório, empacote apenas os arquivos alterados em um tar.gz
e envie para o script PHP no servidor, que o descompactaria sobre o diretório de destino. Isso ainda enviaria arquivos inteiros, mas pelo menos eles seriam compactados - mas as exclusões no servidor seriam difíceis de manipular.
Por fim, os utilitários de comparação de arquivos binários sugerem que é possível empacotar os diretórios em .tar(.gz)
cada e, em seguida, executar o utilitário nesses arquivos - por exemplo, (via ExternalCompression - xdelta - Hospedagem do Google Project ):
gzip release-1.tar
gzip release-2.tar
xdelta3 -e -s release-1.tar.gz release-2.tar.gz delta-1-2.xd3
xdelta3 -d -s release-1.tar.gz delta-1-2.xd3 release-2.tar.gz
... provavelmente também é possível com o JojoDiff / jdiff
jdiff archive0000.tar archive0001.tar archive0001.jdf
jptch archive0000.tar archive0001.jdf archive0001b.tar
... ou com bsdiff
. No entanto, isso exige que eu também mantenha um arquivo tar de todo o site no host, para permitir que os patches sejam aplicados de forma limpa a ele, e o espaço será problema aqui novamente.Também me forçaria a pedir ao webhost para permitir a instalação e uso de pelo menos as partes de correção das ferramentas; e isso pode valer a pena tentar novamente, se essas ferramentas também não exigirem que eu mantenha uma cópia adicional do site no host.
De qualquer forma, abaixo está o script que demonstra a extração de um git
.bundle
como uma diferença recursiva entre dois diretórios (ou melhor, duas versões do mesmo diretório); saída terminal relevante é incluída nos comentários:
#!/usr/bin/env bash
## comments with double ##; (relevant) terminal output with single #
## uses git, ImageMagick, tree
set -x
cd /tmp
rm -rf testdir export_compare
mkdir testdir
cd testdir
git init
# Initialized empty Git repository in /tmp/testdir/.git/
git config user.name "test"
git config user.email "[email protected]"
## generate files - revision 1
## - text
cat /dev/urandom | tr -dc '[ -~]' | fold -w 80 -s | head -c 1024 > test_01.txt
mkdir subdir
cat /dev/urandom | tr -dc '[ -~]' | fold -w 80 -s | head -c 1024 > subdir/subtest_01.txt
cat /dev/urandom | tr -dc '[ -~]' | fold -w 80 -s | head -c 1024 > subdir/subtest_02.txt
## - binary
convert -depth 8 -size 200x150 xc:blue rgb:subdir/rgbimage.dat
## check:
## - files:
tree -s --dirsfirst .
# .
# ├── [ 4096] subdir
# │ ├── [ 90000] rgbimage.dat
# │ ├── [ 1024] subtest_01.txt
# │ └── [ 1024] subtest_02.txt
# └── [ 1024] test_01.txt
#
# 1 directory, 4 files
## - view image (press "q" to quit)
display -depth 8 -size 200x150 rgb:subdir/rgbimage.dat
git add *
git commit -m "initial commit"
## check usage
du -ba --max-depth=1 .
# 1024 ./test_01.txt
# 96144 ./subdir
# 99947 ./.git
# 201211 .
## change files - revision 2
## remove file:
REP="removed 1024;"
git rm subdir/subtest_02.txt
## add file
REP="$REP added 1024;"
cat /dev/urandom | tr -dc '[ -~]' | fold -w 80 -s | head -c 1024 > test_02.txt
git add test_02.txt
## change files:
## - text:
REP="$REP modified/added 19;"
echo "a new changed line" >> test_01.txt
## - binary
REP="$REP modified inline 1200"
convert -depth 8 -size 1x200 xc:red rgb:/dev/stdout | dd of=subdir/rgbimage.dat bs=1 seek=$((200*50*3)) count=$((200*3)) conv=notrunc
convert -depth 8 -size 1x200 xc:red rgb:/dev/stdout | dd of=subdir/rgbimage.dat bs=1 seek=$((200*100*3)) count=$((200*3)) conv=notrunc
## check:
## - files:
tree -s --dirsfirst .
# .
# ├── [ 4096] subdir
# │ ├── [ 90000] rgbimage.dat
# │ └── [ 1024] subtest_01.txt
# ├── [ 1043] test_01.txt
# └── [ 1024] test_02.txt
#
# 1 directory, 4 files
## - view image (press "q" to quit)
display -depth 8 -size 200x150 rgb:subdir/rgbimage.dat
git add *
git commit -m "second commit with changes"
# [master 2b243fb] second commit with changes
# 4 files changed, 16 insertions(+), 19 deletions(-) ...
## check usage
du -ba --max-depth=1 .
# 1043 ./test_01.txt
# 1024 ./test_02.txt
# 95120 ./subdir
# 123355 ./.git
# 224638 .
## go back to parent dir (/tmp) and make a new directory for "clean" exports:
cd /tmp
mkdir export_compare
mkdir export_compare/testdir_new
mkdir export_compare/testdir_old
## from git, export each revision "cleanly"
cd testdir
git archive HEAD | tar -x -C /tmp/export_compare/testdir_new
git archive HEAD^1 | tar -x -C /tmp/export_compare/testdir_old
## create git bundle, containing the changes between new and old revision
git bundle create ../commits_testdir.bundle HEAD HEAD^1
# ... Writing objects: 100% (13/13), 4.30 KiB, done.
# Total 13 (delta 2), reused 0 (delta 0)
## check
cd /tmp
echo $REP
# removed 1024; added 1024; modified/added 19; modified inline 1200
du -b commits_testdir.bundle
# 4470 commits_testdir.bundle
cd export_compare
du -bs testdir_old testdir_new
# 101264 testdir_old
# 101283 testdir_new
tree -s --dirsfirst .
# .
# ├── [ 4096] testdir_new
# │ ├── [ 4096] subdir
# │ │ ├── [ 90000] rgbimage.dat
# │ │ └── [ 1024] subtest_01.txt
# │ ├── [ 1043] test_01.txt
# │ └── [ 1024] test_02.txt
# └── [ 4096] testdir_old
# ├── [ 4096] subdir
# │ ├── [ 90000] rgbimage.dat
# │ ├── [ 1024] subtest_01.txt
# │ └── [ 1024] subtest_02.txt
# └── [ 1024] test_01.txt
#
# 4 directories, 8 files
# + set +x
set +x