#include #include #include #include "projet.h" #include "projetx.m" /* Enregistre la nouvelle version du makefile.dat dans version.dat */ PROTECTED int MAKEFILE::logversion ( const char *nomver, // Nom symbolique de la nouvelle r‚vision const REVISION *newrev, const char *comment) // Commentaires ajout‚s dans version.dat { /* #Sp‚cification: livraison / version.dat / principal Lors d'une livraison, un entr‚e est ajout‚ dans le version.dat de chaque projet livr‚. Cet entr‚e identifie la r‚vision. Elle est suivie d'un commentaire identifiant la r‚vision de provenance. exemple: v42 jacques 0.0.2.2 14/07/92 ;Livraison de 0.0.2.1 */ VERSION_DAT ver(user,projet); VERSION_ONE *one = ver.add (nomver,user->getnom(),newrev); { char line[1000]; char *pt = line; while (*comment != '\0'){ if (*comment == '\n'){ *pt = '\0'; one->addinfo (line); pt = line; comment++; }else{ *pt++ = *comment++; } } if (pt > line){ *pt = '\0'; one->addinfo (line); } } if (projet[0] == '\0'){ /* #Sp‚cification: livraison / version.dat / principal Pour le fichier version.dat principal, un commentaire est ajout‚ pour chaque sous-projet qui ont ‚t‚ livr‚s durant la mˆme session Ces commentaires permettent de d‚terminer la provenance de la r‚vision. exemple: v42 jacques 0.0.2.2 14/07/92 ;Livraison de 0.0.2.1 ; projet page ; projet workbox */ // Patch etrangoide. // Recense tous les */makefile.dat de meme r‚vision que makefile.dat // courant, pour retrouver les projets qui ont ‚t‚ livr‚s // en mˆme temps. setiter(); MAKEFILE_FILE *file; while ((file=iter("*/makefile.dat"))!=NULL){ if (file->rev.cmp(&moi->rev)==0){ char prj[MAXSIZ_NAME]; path_splitlex (file->nom,prj,NULL); one->addinfo (" projet %s",prj); } } } { /* #Sp‚cification: livraison / version.dat partiel Lors de la livraison d'un r‚pertoire, la composante ajout‚e au version.dat de ce r‚pertoire est copi‚ dans un version.dat partiel de l'environnement /kit/livre. */ char revstr[MAXSIZ_REVISION+1]; moi->rev.formatpath (revstr); char path[MAXSIZ_PATH]; user->maklivpath(revstr,path); path_make (path,projet,path); path_make (path,"version.dat",path); FILE *fout = fopen_err (path,"w",0); if (fout != NULL){ one->save (fout); fclose (fout); } } return ver.save(user); } /* Note que la version locales devra ˆtre effac‚. Extrait la version dans le r‚pertoire ombre. ATTENTION: Le r‚pertoire courant doit ˆtre celui du projet dans l'environnement usager. */ PROTECTED int MAKEFILE::archive (MAKEFILE_FILE *file, const char *) { int ret = -1; /* #Sp‚cification: Archivage / RCS / historique de l'abandon Initialement, le programme projetX a ‚t‚ con‡u pour piloter RCS qui s'occupait d'archiver les diff‚rentes versions des fichiers sources. Comme les transactions avec l'archive (l'extraction d'une version par exemple) sont relativement lente, un r‚pertoire tampon a ‚t‚ cr‚‚. Il contient simplement toutes les variations de tous les sources. Les fichiers makefile.dat y font r‚f‚rence. C'est le r‚pertoire /kit/ombre. La vie a d‚montrer que RCS ‚tait plus ou moins utile. Voici les constatations qui nous amŠne en ce soir de septembre … mettre RCS sur la tablette: 1-Il est bugg‚. La version DOS a simplement ‚t‚ compil‚ et … peu prŠs rien n'a ‚t‚ fait pour contrecarrer les limites de DOS. Plus sp‚cifiquement, les noms de fichier limit‚s. 2-Il est bugg‚. L'indentation de certain source n'est pas conserv‚. 3-Il est lent. 4-On ne peut pas ins‚rer de r‚vision dans n'importe quel ordre. Pour cet aspect, la politique de RCS n'est pas compatible … la notre. Dans RCS, les num‚ros de r‚visions sont allou‚s par fichier. Dans notre systŠme, ils sont impos‚ par la r‚vision du projet. Par exemple, tous les sources r‚vis‚s pour produire une nouvelle r‚vision d'un projet porteront ce num‚ro de r‚vision. 5-Et finalement, /kit/ombre est une duplication de l'archive et peut donc remplir la mˆme fonction. Et ce sans restriction sur l'insertion des r‚visions. */ /* #Sp‚cification: Archivage / RCS / Avenir de RCS RCS sera peut-ˆtre utilis‚ pour d‚charg‚ /kit/ombre des version moins utile. Son usage sera associ‚ au m‚canisme de m‚nage de /kit/ombre. ... X années plus tard ... Finalement, c'est le programme zip qui a remplacé RCS pour faire le ménage dans /kit/ombre. C'est moins efficace que RCS, mais plus rapide et plus souple. */ /* #Sp‚cification: Archivage / r‚pertoires / /kit/ombre Le r‚pertoire /kit/ombre contient un sous r‚pertoire pour tous les projets existant. Ces sous-r‚pertoires contiennent eux-mˆmes les sous-r‚pertoires repr‚sentant les sous-projets. etc ... Chacun des r‚pertoire contient des sous-r‚pertoires dont le nom repr‚sente un num‚ro de r‚vision. exemple /kit/ombre/vdi/osdos/_0_1_2_1.s Ces r‚pertoires-versions contiennent des fichiers sources de la r‚vision correspondante. Attention: Une r‚vision X d'un projet contient des sources de mˆme r‚vision (X) et partage des sources d'autre r‚vision. exemple: La r‚vision 0.1.2.1 du projet vdi/osdos est compos‚ de sources portant la r‚vision 0.1.2.1 ainsi que de fichiers sources provenant d'autre r‚vision. Il est probable que la r‚vision 0.1.2.1 est majoritairement compos‚ de sources de r‚vision 0.1 et 0.0, et de quelques sources de r‚vision 0.1.2.1. */ #if 0 char pathref[MAXSIZ_PATH]; user->makrefpath(projet,pathref); if (rcs_put (file->nom,user->getnom(),&file->rev,pathref,doc) != -1){ // On force l'extraction mˆme si le fichier est d‚j… l…. // En principe, c'est impossible que cette version du fichier // puisqu'on vient tout juste de l'archiver. Ca d‚panne pour // la phase de debug du systŠme, sp‚cialement bootrcs.c. On // archive … r‚p‚tition la mˆme chose. if (extract(file,1)!=-1){ // Note la nouvelle r‚vision et note que la version // locale du fichier devra ˆtre effacer. file->efface = 1; ret = 0; } } #else /* #Sp‚cification: Archivage / Op‚rations L'archivage se fait en deux op‚rations. On copie le fichier dans le r‚pertoire appropri‚ de /kit/ombre et on le copie ensuite dans /kit/livre. */ if (foper_archive (file->nom,projet,&file->rev,user) != -1 && foper_backup (file->nom,projet,&file->rev,user) != -1){ file->efface = 1; ret = 0; } #endif return ret; } /* Livraison d'une r‚vision de fichier dans l'archive. La fonction d‚terminera la num‚ro de r‚vision requis. Le fichier sera copié dans l'archive. Si tous va bien, le fichier fname sera d‚truit. Tout les fichiers archiv‚s avec cette instance porteront le mˆme num‚ro de r‚vision, soit le prochain num‚ro de livraison du fichier makefile.dat lui-mˆme. Si le fichier ne fait pas partie de makefile.dat, il est ajout‚. Retourne -1 si erreur. */ PUBLIC int MAKEFILE::livre ( const char *fname, REVISION_TYPE revtype, const char *doc, // Documentation expliquant les diff‚rences // avec la version pr‚c‚dante. const SSTRINGS &tbnew, // Fichiers jamais livré, mais accepté. bool &doarch) // Sera vrai si le fichier a vraiment été livré // (si le fichier n'a pas changé, il n'est pas // livré, mais simplement effacé) { int ret = -1; SAVEPATH save; doarch = false; if (setusrpath (&save) != -1){ MAKEFILE_FILE *file = locate (fname,true); doarch = true; if (file != NULL){ char path[MAXSIZ_PATH]; user->makombpath(projet,path); char revstr[MAXSIZ_PATH]; file->rev.formatpath (revstr); strcat (revstr,".s"); path_make (path,revstr,path); path_make (path,fname,path); file->is_del = 0; if (foper_compare (fname,path)==0){ doarch = false; ret = 0; file->efface = 1; foper_logprintf (MSG_B(I_NOTCHANGED ,"Fichier inchangé, efface %s\n" ,"File not changed, erase %s\n") ,fname); } }else{ // Nouveau fichier char path[MAXSIZ_PATH]; path_make (projet,fname,path); if (tbnew.lookup(path)!=-1){ doarch = true; }else{ // Ok, nous n'archivons pas ce fichier, mais c'est ce que nous // voulions doarch = false; ret = 0; } } if (doarch){ REVISION oldrev; MAKEFILE_FILE *file = setrev(fname,revtype,&oldrev); ret = archive (file,doc); if (ret == -1){ file->rev = oldrev; } } path_popdir (&save); } return ret; } /* Retourne vrai si le fichier serait effectivement livré par la fonction livre(). */ PUBLIC bool MAKEFILE::livre_test (MAKEFILE_FILE *file) { bool ret = false; SAVEPATH save; if (setusrpath (&save) != -1){ if (file != NULL){ const char *nom = file->getnom(); char path[MAXSIZ_PATH]; user->makombpath(projet,path); char revstr[MAXSIZ_PATH]; file->rev.formatpath (revstr); strcat (revstr,".s"); path_make (path,revstr,path); path_make (path,nom,path); if (foper_compare (nom,path)!=0){ ret = true; } }else{ ret = true; } path_popdir (&save); } return ret; } /* Livraison du fichier makefile.dat lui-mˆme. Retourne -1 si erreur. AprŠs la livraison, on peut effacer (MAKEFILE::cleanup()) les copies locales des fichiers livr‚s. */ PUBLIC int MAKEFILE::livretoi ( REVISION_TYPE revtype, bool keep, // Garde une copie locale du makefile.dat const char *newversion, const char *comment) // Commentaire { int ret = -1; SAVEPATH save; /* #Sp‚cification: livraison / makefile.dat Voici les op‚rations pour r‚aliser la livraison du makefile.dat. Il doit tout d'abord s'‚crire sur disque et se livrer comme un fichier ordinaire. Il ‚crit seulement la partie qui d‚crit ce qui provient de /kit/ombre. Les fichiers de /kit/build qui se sont ajout‚s lors de la commande du projet sont exclus de l'archivage. AprŠs la livraison, il se r‚‚crit complŠtement sur disque (incluant les composantes de /kit/build). Le fichier version.dat enregistre la sp‚cification de la nouvelle livraison. Il doit ensuite r‚viser le makefile.dat ancˆtre (pour lui indiquer le changement de r‚vision). Optionnellement, il devra rester pr‚sent dans le r‚pertoire usager. (L'op‚ration de livraison ne doit pas interrompre le travail du programmeur. AprŠs une livraison, son r‚pertoire doit ˆtre logiquement dans le mˆme ‚tat. Il peut continuer … travailler et compiler). On peut ensuite faire le cleanup si requis, soit effacer les versions locales des fichiers qui ont ‚t‚ livr‚s. */ if (setusrpath (&save) != -1){ REVISION oldrev; MAKEFILE_FILE * file = setrev(moi->nom,revtype,&oldrev); // On force la date courante puisque le fichier va etre ‚crit. file->date = ((unsigned long)date_currentu()<<16) + time_currentu(); if (file != NULL){ if (ecrit(1) != -1 && archive (file,NULL) != -1){ char revstr[MAXSIZ_REVISION]; oldrev.format (revstr); SSTRING tmp; tmp.setfromf ("Livraison de %s\n",revstr); tmp.append (comment); if (logversion ( newversion == NULL || newversion[0] == '\0' ? user->getversion() : newversion ,&moi->rev ,tmp.get()) != -1){ cleanup(); if (keep){ ecrit(0); // Efface le makefile.del char pathdel[MAXSIZ_PATH]; file_chgext (fname,pathdel,".del"); file_unlink (pathdel); } if (projet[0] != '\0'){ // Corrige le makefile.dat ancˆtre char anc_projet[MAXSIZ_PATH]; // Path du projet char rel_projet[MAXSIZ_NAME]; // Nom relatif du projet path_splitlex (projet,anc_projet,rel_projet); MAKEFILE anc (NULL,true,anc_projet,user); // Fabrique un path projet/makefile.dat char path[MAXSIZ_PATH]; path_make (rel_projet,file->nom,path); path_2unix (path,path); anc.setrev (path,&file->rev,file->path,file->date,1); //anc.ecrit (0); /* #Sp‚cification: livraison / makefile.dat ancˆtre Le makefile.dat ancˆtre est corrig‚ pour tenir compte de la nouvelle r‚vision du sous-r‚pertoire qui vient d'ˆtre livr‚. En sauvant le makefile.dat ancˆtre, on produit un makefile.old. Il agira comme flag indiquant qu'au moins un sous-r‚pertoire a ‚t‚ livr‚ et qu'il faut donc livr‚ aussi le makefile.dat ancˆtre. Ce m‚canisme est requis lorsqu'il y a panne pendant un s‚quence de livraison. On peut g‚n‚ralement reprendre l'op‚ration de livraison et ainsi le makefile.dat ancˆtre sera livr‚, mˆme si aucune composante du r‚pertoire ancˆtre ou de ses sous-r‚pertoires n'ont ‚t‚ livr‚es. */ anc.save(); } ret = 0; } }else{ file->rev = oldrev; } } path_popdir (&save); } return ret; } /* Cr‚ation d'une nouvelle version a partir de ce makefile.dat La version du fichier est corrig‚, et le makefile.dat est simplement archiv‚. G‚n‚ralement, s'applique surtout au makefile.dat de la racine. */ PUBLIC int MAKEFILE::creation( const char *nomver, // Nom symbolique de la version … cr‚er const REVISION *newrev) // Num‚ro de cette r‚vision { int ret = -1; char tmppath[MAXSIZ_PATH]; projet_tmppath.getval (tmppath,sizeof(tmppath)); SAVEPATH save; // Pour archiver le makefile.dat, il faut l'‚crire // sur disque. Le systŠme d'archive opŠre … partir // du fichier dans le r‚pertoire courant. // On s‚lectionne un r‚pertoire temporaire. if (path_pushdir (user,tmppath,&save)!=-1){ /* #Sp‚cification: admin / cr‚ation d'une version Voici les op‚rations requises pour associ‚ un nouveau num‚ro de r‚vision et un nouveau nom … une r‚vision existente. Le r‚sultat est deux r‚visions qui pointent … la mˆme combinaison de fichier, mais qui vont ‚voluer de fa‡on ind‚pendante par la suite. Voici les ‚tapes requises pour cr‚er une r‚vision 2.0 … partir d'une r‚vision 1.9. mkdir /kit/ombre/_2_0.s cp /kit/ombre/_1_9.s/makefile.dat /kit/ombre/_2_0.s Edition de /kit/ombre/_2_0.s/makefile.dat pour changer sa propre date de r‚vision. mkdir /kit/livre/_2_0 cp /kit/ombre/_2_0.s/makefile.dat /kit/livre/_2_0 Ajoute la r‚vision 2.0 et son nom dans /kit/ombre/version.dat Cr‚ation de /kit/livre/_2_0/version.dat qui contient uniquement l'information sur la r‚vision 2.0. */ long date = ((long)date_currentu()<<16) + time_currentu(); REVISION oldrev = moi->rev; setabsrev ("makefile.dat",date,newrev); // La cr‚ation des r‚pertoire dans /kit/ombre et // /kit/livre est fait par mak.archive if (ecrit("makefile.dat",1) != -1 && archive (moi,"") != -1){ // On doit corriger le version.dat // et cr‚er un version.dat dans /kit/livre char revstr[MAXSIZ_REVISION]; oldrev.format (revstr); SSTRING tmp; tmp.setfromf ("création à partir de %s\n",revstr); ret = logversion (nomver,newrev,tmp.get()); } path_popdir (&save); } return ret; } /* Copie un fichier dans l'espace usager. Extrait de l'archive et place dans r‚pertoire ombre si ce n'est pas d‚j… fait. Retourne -1 si erreur. */ PUBLIC int MAKEFILE::copy2usr (MAKEFILE_FILE *file) { int ret = -1; if (extract(file,0)!=-1){ char usrpath[MAXSIZ_PATH]; user->makusrpath (projet,usrpath); path_make (usrpath,file->getnom(),usrpath); char ombpath[MAXSIZ_PATH]; user->makombpath (file->getrelpath(),ombpath); ret = file_copyp (ombpath,usrpath); } return ret; } /* Copie le makefile.dat dans l'espace usager. Retourne -1 si erreur. */ PUBLIC int MAKEFILE::copy2usr () { return copy2usr (moi); }