Puedo especular que Git la mayor parte del tiempo usa atomic actualizaciones de archivos que se hacen así:
- El contenido de un archivo se lee en la memoria (y se modifica).
- El contenido modificado se escribe en un archivo separado (generalmente ubicado en el mismo directorio que el original, y tiene un formato aleatorio (
mktemp
-estilo) nombre. - El nuevo archivo es entonces
rename(2)
d -d sobre el original; esta operación garantiza que cada observador que intente abrir el archivo usando su nombre obtendrá el contenido antiguo o el nuevo.
Tales actualizaciones son vistas por inotify(7)
como moved_to
eventos, ya que un archivo "reaparece" en un directorio.
Para responder a su pregunta por separado para git
2.24.1 en Linux 4.19.95:
- ¿Por qué faltan estos eventos en estos archivos?
No ves IN_MODIFY
/IN_CLOSE_WRITE
eventos porque git clone
siempre intentará usar enlaces duros para archivos bajo el .git/objects
directorio. Al clonar a través de la red o a través de los límites del sistema de archivos, estos eventos volverán a aparecer.
- ¿Qué se puede hacer al respecto? Específicamente, ¿cómo puedo responder a la finalización de escrituras en estos archivos? Nota:idealmente, me gustaría responder cuando la escritura esté "terminada" para evitar cargar innecesariamente/(incorrectamente) la escritura "sin terminar".
Para detectar la modificación de enlaces duros, debe configurar un controlador para inotify CREATE
evento que sigue y realiza un seguimiento de esos enlaces. Tenga en cuenta que un simple CREATE
también puede significar que se creó un archivo no vacío. Luego, en IN_MODIFY
/IN_CLOSE_WRITE
a cualquiera de los archivos, también debe activar la misma acción en todos los archivos vinculados. Obviamente, también debe eliminar esa relación en el DELETE
evento.
Probablemente, un enfoque más simple y más sólido sería hacer un hash periódico de todos los archivos y comprobar si el contenido de un archivo ha cambiado.
Corrección
Después de comprobar el git
código fuente de cerca y ejecutando git
con strace
, encontré que git
utiliza archivos mapeados en memoria, pero principalmente para leer contenido. Ver el uso de xmmap
que siempre se llama con PROT_READ
solo... Por lo tanto, mi respuesta anterior a continuación es NO La respuesta correcta. Sin embargo, con fines informativos, me gustaría mantenerlo aquí:
-
No ves
IN_MODIFY
eventos porquepackfile.c
usammap
para acceso a archivos yinotify
no informa modificaciones parammap
archivos editados.Desde la página de manual de inotify:
La API de inotify no informa sobre los accesos a archivos y las modificaciones que pueden ocurrir debido a mmap(2), msync(2) y munmap(2).
Según esta respuesta aceptada, supongo que podría haber alguna diferencia en los eventos según el protocolo que se utiliza (es decir, ssh o https).
¿Observa el mismo comportamiento al monitorear la clonación desde el sistema de archivos local con el --no-hardlinks
opción?
$ git clone [email protected]:user/repo.git
# set up watcher for new dir
$ git clone --no-hardlinks repo new-repo
Su comportamiento observado al ejecutar el experimento en un host Linux y Mac probablemente elimine este problema abierto siendo la causa https://github.com/docker/for-mac/issues/896 pero agregando solo por si acaso.