Je peux supposer que Git utilise la plupart du temps atomic les mises à jour de fichiers qui se font comme ceci :
- Le contenu d'un fichier est lu en mémoire (et modifié).
- Le contenu modifié est écrit dans un fichier séparé (généralement situé dans le même répertoire que l'original, et ayant un format aléatoire (
mktemp
-style) nom. - Le nouveau fichier est alors
rename(2)
d -d sur l'original ; cette opération garantit que chaque observateur essayant d'ouvrir le fichier en utilisant son nom obtiendra soit l'ancien contenu, soit le nouveau.
Ces mises à jour sont vues par inotify(7)
comme moved_to
événements—puisqu'un fichier "réapparaît" dans un répertoire.
Pour répondre à votre question séparément pour git
2.24.1 sur Linux 4.19.95 :
- Pourquoi ces événements manquent-ils dans ces fichiers ?
Vous ne voyez pas IN_MODIFY
/IN_CLOSE_WRITE
événements car git clone
essaiera toujours d'utiliser des liens physiques pour les fichiers sous le .git/objects
annuaire. Lors du clonage sur le réseau ou au-delà des limites du système de fichiers, ces événements réapparaîtront.
- Que peut-on y faire ? Plus précisément, comment puis-je répondre à la fin des écritures dans ces fichiers ? Remarque :idéalement, j'aimerais répondre lorsque l'écriture est "terminée" pour éviter de télécharger inutilement/(incorrectement) une écriture "inachevée".
Afin d'attraper la modification des liens physiques, vous devez configurer un gestionnaire pour l'inotify CREATE
événement qui suit et conserve la trace de ces liens. Veuillez noter qu'un simple CREATE
peut également signifier qu'un fichier non vide a été créé. Puis, au IN_MODIFY
/IN_CLOSE_WRITE
à l'un des fichiers, vous devez également déclencher la même action sur tous les fichiers liés. Évidemment, vous devez également supprimer cette relation sur le DELETE
événement.
Une approche plus simple et plus robuste consisterait probablement à hacher périodiquement tous les fichiers et à vérifier si le contenu d'un fichier a changé.
Correction
Après avoir vérifié le git
code source étroitement et exécutant git
avec strace
, j'ai trouvé que git
utilise des fichiers mappés en mémoire, mais principalement pour lire du contenu. Voir l'utilisation de xmmap
qui est toujours appelé avec PROT_READ
seulement.. Par conséquent, ma réponse précédente ci-dessous est PAS la bonne réponse. Néanmoins, à titre informatif, je voudrais quand même le garder ici :
-
Vous ne voyez pas
IN_MODIFY
événements parce quepackfile.c
utilisemmap
pour l'accès aux fichiers etinotify
ne signale pas les modifications pourmmap
fichiers ed.À partir de la page de manuel inotify :
L'API inotify ne signale pas les accès aux fichiers et les modifications qui peuvent se produire à cause de mmap(2), msync(2) et munmap(2).
Sur la base de cette réponse acceptée, je suppose qu'il pourrait y avoir une différence dans les événements en fonction du protocole utilisé (c'est-à-dire ssh ou https).
Observez-vous le même comportement lors de la surveillance du clonage à partir du système de fichiers local avec le --no-hardlinks
option ?
$ git clone [email protected]:user/repo.git
# set up watcher for new dir
$ git clone --no-hardlinks repo new-repo
Votre comportement observé lors de l'exécution de l'expérience sur un hôte Linux et Mac élimine probablement ce problème ouvert étant la cause https://github.com/docker/for-mac/issues/896 mais en ajoutant juste au cas où.