Mohu spekulovat, že Git většinu času používá atomický aktualizace souborů, které se provádějí takto:
- Obsah souboru je načten do paměti (a upraven).
- Upravený obsah je zapsán do samostatného souboru (obvykle umístěného ve stejném adresáři jako původní a s náhodným výběrem (
mktemp
-style) jméno. - Nový soubor je pak
rename(2)
d -d nad původní; tato operace zaručuje, že každý pozorovatel, který se pokusí otevřít soubor pomocí jeho názvu, získá buď starý obsah, nebo nový.
Takové aktualizace vidí inotify(7)
jako moved_to
události – protože soubor se „znovu objeví“ v adresáři.
Chcete-li odpovědět na vaši otázku samostatně pro git
2.24.1 v systému Linux 4.19.95:
- Proč tyto události v těchto souborech chybí?
Nevidíte IN_MODIFY
/IN_CLOSE_WRITE
události, protože git clone
se vždy pokusí použít pevné odkazy pro soubory pod .git/objects
adresář. Při klonování přes síť nebo přes hranice systému souborů se tyto události objeví znovu.
- Co se s tím dá dělat? Jak konkrétně mohu reagovat na dokončení zápisů do těchto souborů? Poznámka:v ideálním případě bych rád odpověděl, když je psaní „dokončeno“, abych se vyhnul zbytečnému/(nesprávnému) nahrávání „nedokončeného“ psaní.
Abyste mohli zachytit modifikaci pevných odkazů, musíte nastavit handler pro inotify CREATE
událost, která tyto odkazy sleduje a sleduje. Upozorňujeme, že jednoduchý CREATE
může také znamenat, že byl vytvořen prázdný soubor. Poté na IN_MODIFY
/IN_CLOSE_WRITE
u kteréhokoli ze souborů musíte spustit stejnou akci také u všech propojených souborů. Samozřejmě musíte také odstranit tento vztah na DELETE
událost.
Jednodušší a robustnější přístup by pravděpodobně byl pouze periodicky hashovat všechny soubory a kontrolovat, zda se obsah souboru nezměnil.
Oprava
Po kontrole git
zdrojový kód a běžící git
s strace
, zjistil jsem, že git
používá soubory mapované v paměti, ale většinou pro čtení obsahu. Viz použití xmmap
který se vždy volá s PROT_READ
pouze.. Moje předchozí odpověď níže je proto NE správná odpověď. Nicméně pro informační účely bych to zde rád ponechal:
-
Nevidíte
IN_MODIFY
události, protožepackfile.c
používámmap
pro přístup k souboru ainotify
nehlásí změny prommap
ed souborů.Z manuálové stránky inotify:
Rozhraní inotify API nehlásí přístupy k souborům a změny, ke kterým může dojít kvůli mmap(2), msync(2) a munmap(2).
Na základě této přijaté odpovědi bych předpokládal, že může existovat nějaký rozdíl v událostech na základě používaného protokolu (tj. ssh nebo https).
Pozorujete stejné chování při monitorování klonování z místního souborového systému pomocí --no-hardlinks
možnost?
$ git clone [email protected]:user/repo.git
# set up watcher for new dir
$ git clone --no-hardlinks repo new-repo
Vaše pozorované chování při spuštění experimentu na hostiteli linux i Mac pravděpodobně eliminuje tento otevřený problém, který je příčinou https://github.com/docker/for-mac/issues/896, ale přidává jen zapouzdřit.