Hacer make svn checkout y actualizar varias copys de trabajo

Estoy tratando de escribir un makefile de repo_1 y mantenimiento actualizado (genérico o GNU) para operar en una cantidad de copys de trabajo svn, digamos repo_1repo_n , como este

Para todos los repos que hago

  • si ./repo_i aún no existe, svn checkout repo_i [en realidad debería ser seguro suponer que ninguno o todos existen, pero tiendo a sobre-diseñar]
  • else cd ./repo_i && svn update .

Estoy bastante seguro de que esto debería ser elegantemente factible con la marca, y parece una cosa muy simple de querer, por lo que alguien más debe haber tenido esa idea antes que yo; Aún así, de alguna manera no pude encontrar nada útil en SO y me quedé atascado al buildlo yo mismo.

La parte de pago está bien, donde puedo hacer

 DIRS = repo1 repo2 [...] repoN all: $(DIRS) $(DIRS): svn checkout http://some.svn.path/$@/trunk $@ 

pero el bit de actualización es más complicado. Me gustaría evitar que la actualización se ejecute después de un nuevo checkout (seguro que no va a doler, pero ¿no odias la networkingundancia?), Y luego no estoy seguro de cómo "hacer un bucle" sobre los repos sin explicar la regla de actualización para cada copy de trabajo y hacerla .PHONY , que de nuevo podría interferir con la regla de pago. Mi primera idea se veía como

 DIRS = repo1 repo2 [...] repoN update: $(DIRS) cd $(make-magic) && svn update 

pero esto no funcionará, porque la regla para actualizar repo_i nunca se activará si ./repo_i ya existe, y para verificar si upstream es más reciente, necesito ejecutar svn update en ./repo_i .

¿Alguien más ha intentado esto antes? Felicitaciones extra si tu idea coexiste pacíficamente con make -j , ¡solo porque! (también bastante tedioso en mi caso con N = 4).

PD: Esto es bastante independiente del VCS real, pero necesita funcionar con svn (por lo que cualquiera de esos git solve --all-problems mágicos git solve --all-problems no ayudarán aquí 🙂

Entonces, lo primero que debe recordar es que para los objectives que no tienen prerrequisitos, se consideran actualizados si el objective existe. Por lo tanto, si tiene una regla con un repo1 objective sin requisitos previos y existe (ya sea file o directory) en el sistema de files, cree que está actualizado y no ejecutará la receta.

Lo segundo que debe recordar es que haga tratos solo con filesystems y marcas de time, de forma pnetworkingeterminada. No hay forma de establecer una relación de requisitos previos que dependa de otra cosa, como "¿este repository SVN está actualizado?".

Asi que. Lo primero que debe hacer es marcar todos sus repositorys como .PHONY , de modo que las recetas siempre se ejecutarán incluso si los directorys existen. En segundo lugar, debe cambiar la receta para que revise el repository, si no existe, o lo actualice, si lo hace.

Algo como esto debería hacer lo que quieras:

 DIRS = repo1 repo2 [...] repoN .PHONY: update $(DIRS) update: $(DIRS) $(DIRS): if [ -d $@ ]; then \ cd $@ && svn update; \ else \ svn checkout http://some.svn.path/$@/trunk $@; \ fi 

Esto también funciona con -j . Lo anterior requiere que alguien make update explícita. Si desea incrustarlo para que siempre se ejecute en cada marca (no me gusta esto …) puede poner la update como un requisito previo solo de order en todas las reglas de compilation (reglas de patrones, etc.).