GNU/Linux >> Tutoriels Linux >  >> Linux

Événements inotify manquants (dans le répertoire .git)

Je peux supposer que Git utilise la plupart du temps atomic les mises à jour de fichiers qui se font comme ceci :

  1. Le contenu d'un fichier est lu en mémoire (et modifié).
  2. 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.
  3. 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 que packfile.c utilise mmap pour l'accès aux fichiers et inotify ne signale pas les modifications pour mmap 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ù.


Linux
  1. Supprimer un lien symbolique vers un répertoire

  2. Obtenir le fichier le plus récent dans un répertoire sous Linux

  3. Conserver les autorisations de fichiers avec Git

  4. Exclure le répertoire lors de la création d'un fichier .tar.gz

  5. Comment limiter la taille du fichier lors de la validation ?

Gestionnaire de fichiers Java

Utiliser Inotify pour surveiller l'accès à un fichier ?

Linux – But du répertoire /net ?

Comment :une introduction à l'utilisation de Git

sys/types.h :aucun fichier ou répertoire de ce type

touch :impossible de toucher `foo' :aucun fichier ou répertoire de ce type