Por que o 'cp -uav' de um repositório git foi “removido” para alguns arquivos?

2

Eu usei cp -uav para atualizar uma cópia de um repositório do git, incluindo arquivos não confirmados.

Por que ele diz que está removendo arquivos? Parece assim:

$ cp -uav repos copy
removed 'copy/repos/h/.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391'
removed 'copy/repos/h/.git/objects/3b/b3f834dd037db9298b10d71e0cd7383000fa1c'
removed 'copy/repos/h/.git/objects/49/6d6428b9cf92981dc9495211e6e1120fb6f2ba'
removed 'copy/repos/h/.git/objects/2b/bf350cea1fb4fd036235d7e6c36eb600e68885'

$ rpm -q --whatprovides 'which cp'
coreutils-8.25-17.fc25.x86_64
    
por sourcejedi 24.05.2017 / 13:35

1 resposta

3

Eu posso reproduzir as mensagens acima da seguinte forma:

mkdir test; cd test
mkdir repos; cd repos

mkdir g; cd g
git init
touch a
git add a
git commit -m test
cd ..

git clone g h
cd ..

mkdir copy
cp -ua repos copy
cp -uav repos copy

A execução do comando cp -ua em strace mostrará que, de fato, está removendo ( unlink ) os arquivos que ele diz.

O que aconteceu é que os objetos em repo/h/.git/objects são hardlinks dos que estão em repo/g/.git/objects . (No meu caso original, eu estava copiando um repositório que continha sub-repos, que foram originalmente criados como clones do repositório principal).

cp -a significa cp --preserve , documentado como

--preserve[=ATTR_LIST]

preserve the specified attributes (default: mode,ownership,timestamps), if possible additional attributes: context, links, xattr, all

O unlink acontece como parte da preservação de hardlink:

linkat(AT_FDCWD, "copy/repos/g/.git/objects/2b/bf350cea1fb4fd036235d7e6c36eb600e68885", AT_FDCWD, "copy/repos/h/.git/objects/2b/bf350cea1fb4fd036235d7e6c36eb600e68885", 0) = -1 EEXIST (File exists)

unlink("copy/repos/h/.git/objects/2b/bf350cea1fb4fd036235d7e6c36eb600e68885") = 0

linkat(AT_FDCWD, "copy/repos/g/.git/objects/2b/bf350cea1fb4fd036235d7e6c36eb600e68885", AT_FDCWD, "copy/repos/h/.git/objects/2b/bf350cea1fb4fd036235d7e6c36eb600e68885", 0) = 0

Por que exatamente gera mensagens que me confundiram?

Parece que -u ( --update ) não está implementado neste código. É principalmente uma otimização de desempenho para evitar a recopiação de dados desnecessariamente. Fazer hardlinks não requer copiar nenhum dado.

Podemos ver outros cenários na documentação em que cp também deve remover arquivos:

   -f, --force

         if an existing destination file cannot be opened, remove it and try again (this option is ignored when the -n option is also used)

No caso de -f , posso entender que talvez seja necessário mostrar os arquivos específicos que ele deve "forçar".

Suponho que também possa ser útil mostrar a exclusão, no caso de cp ser interrompido. Caso contrário, seria improvável que os usuários percebessem que um arquivo poderia ter sido excluído do destino (como uma etapa intermediária).

A questão final é por que ela também não mostrava uma mensagem quando recriava os links, o que seria menos confuso. Eu suspeito que isso seja uma peculiaridade da opção -u .

    
por 24.05.2017 / 13:35