Questo può essere fatto anche in Python. In Python 3 (perché siamo nel 2015 ...), possiamo usare qualcosa di simile a questo:
#!/usr/bin/env python3
import os
import re
import subprocess
import sys
from functools import partial
from multiprocessing import Pool
def list_submodules(path):
gitmodules = open(os.path.join(path, ".gitmodules"), 'r')
matches = re.findall("path = ([\w\-_\/]+)", gitmodules.read())
gitmodules.close()
return matches
def update_submodule(name, path):
cmd = ["git", "-C", path, "submodule", "update", "--init", name]
return subprocess.call(cmd, shell=False)
if __name__ == '__main__':
if len(sys.argv) != 2:
sys.exit(2)
root_path = sys.argv[1]
p = Pool()
p.map(partial(update_submodule, path=root_path), list_submodules(root_path))
Questo può essere più sicuro che l'one-liner data dal @Karmazzin (dato che uno solo mantiene i processi di deposizione delle uova senza alcun controllo sul numero di processi generati), segue sempre la stessa logica: leggere .gitmodules
, quindi generare più processi che eseguono il comando git corretto, ma qui utilizzando un pool di processi (è possibile impostare anche il numero massimo di processi). Il percorso del repository clonato deve essere passato come argomento. Questo è stato testato estesamente su un repository con circa 700 sottomoduli.
noti che nel caso di inizializzazione modulo, ogni processo tenterà di scrivere a .git/config
, e problemi di blocco può accadere:
error: could not lock config file .git/config: File exists
Failed to register url for submodule path '...'
Questo può essere catturato con subprocess.check_output
ed un blocco try/except subprocess.CalledProcessError
, che è più pulito del sonno aggiunto al metodo di @ Karmazzin. Un metodo aggiornato potrebbe apparire come:
def update_submodule(name, path):
cmd = ["git", "-C", path, "submodule", "update", "--init", name]
while True:
try:
subprocess.check_output(cmd, stderr=subprocess.PIPE, shell=False)
return
except subprocess.CalledProcessError as e:
if b"could not lock config file .git/config: File exists" in e.stderr:
continue
else:
raise e
Con questo, sono riuscito a eseguire l'init/aggiornamento di 700 sottomoduli nel corso di un Travis costruire senza la necessità di limitare la dimensione del pool di processi. Vedo spesso alcune serrature catturate in questo modo (~ 3 max).
Cosa intendi con asincrono? Lo farebbe: 'aggiorna git submodule --init &'? – rodrigo
Intendo un modo quando ciascun sottomodulo viene inizializzato in un processo separato. – Leksat
Cioè, parallelo piuttosto che sequenziale? –