Posso ipotizzare che Git la maggior parte delle volte usi atomic aggiornamenti dei file che vengono eseguiti in questo modo:
- Il contenuto di un file viene letto in memoria (e modificato).
- Il contenuto modificato viene scritto in un file separato (di solito situato nella stessa directory di quello originale e con un numero casuale (
mktemp
-style) nome. - Il nuovo file è quindi
rename(2)
d -d su quello originale; questa operazione garantisce che ogni osservatore che tenta di aprire il file usando il suo nome ottenga o il vecchio contenuto o quello nuovo.
Tali aggiornamenti sono visti da inotify(7)
come moved_to
events, poiché un file "riappare" in una directory.
Per rispondere alla tua domanda separatamente per git
2.24.1 su Linux 4.19.95:
- Perché questi eventi mancano su questi file?
Non vedi IN_MODIFY
/IN_CLOSE_WRITE
eventi perché git clone
cercherà sempre di utilizzare gli hard link per i file sotto .git/objects
directory. Durante la clonazione sulla rete o oltre i limiti del file system, questi eventi verranno visualizzati di nuovo.
- Cosa si può fare al riguardo? Nello specifico, come posso rispondere al completamento delle scritture su questi file? Nota:idealmente vorrei rispondere quando la scrittura è "finita" per evitare di caricare inutilmente/(erroneamente) testi "non finiti".
Per rilevare la modifica degli hard link devi impostare un gestore per inotify CREATE
evento che segue e tiene traccia di tali collegamenti. Tieni presente che un semplice CREATE
può anche significare che è stato creato un file non vuoto. Quindi, su IN_MODIFY
/IN_CLOSE_WRITE
a uno qualsiasi dei file devi attivare la stessa azione anche su tutti i file collegati. Ovviamente devi anche rimuovere quella relazione sul DELETE
evento.
Un approccio più semplice e robusto sarebbe probabilmente quello di eseguire periodicamente l'hashing di tutti i file e controllare se il contenuto di un file è cambiato.
Correzione
Dopo aver controllato il git
codice sorgente da vicino ed eseguendo git
con strace
, ho trovato che git
usa i file mappati in memoria, ma principalmente per leggere i contenuti. Vedi l'uso di xmmap
che viene sempre chiamato con PROT_READ
solo .. Pertanto la mia risposta precedente di seguito è NON la risposta corretta. Tuttavia, a scopo informativo, vorrei comunque tenerlo qui:
-
Non vedi
IN_MODIFY
eventi perchépackfile.c
utilizzammap
per l'accesso ai file einotify
non riporta modifiche permmap
ed.Dalla manpage di inotify:
L'API inotify non segnala gli accessi ai file e le modifiche che possono verificarsi a causa di mmap(2), msync(2) e munmap(2).
Sulla base di questa risposta accettata, presumo che potrebbero esserci delle differenze negli eventi in base al protocollo utilizzato (ad esempio ssh o https).
Osservi lo stesso comportamento durante il monitoraggio della clonazione dal filesystem locale con --no-hardlinks
opzione?
$ git clone [email protected]:user/repo.git
# set up watcher for new dir
$ git clone --no-hardlinks repo new-repo
Il tuo comportamento osservato durante l'esecuzione dell'esperimento sia su un host Linux che Mac probabilmente elimina questo problema aperto essendo la causa https://github.com/docker/for-mac/issues/896 ma aggiungendo solo incase.