#include #include #include #include #include "projet.h" #include "projetx.m" /* Indique si le makefile.dat a ‚t‚ lue correctement. Mˆme si makefile.dat est vide ou existe pas, il contiendra toujours au moins 1 entr‚e, soit lui-mˆme. */ PUBLIC int MAKEFILE::isok() { return readok; } /* #Sp‚cification: Archivage / makefile.dat / principal Une r‚vision principal nous permet de localiser un makefile.dat principal. Par exemple, la version principal 0.8 est d‚crite par le fichier /kit/ombre/_0_8.s/makefile.dat. Ce makefile.dat nous permet de d‚terminer la combinaison exacte des r‚visions de projets associ‚s … cette r‚vision principale. En fait quand un programmeur dit: Je travaille sur la version 0.8, cela ne veut pas dire qu'il existe une version 0.8 de tous les projets et sous-projets. Les projets n'‚volue pas tous en mˆme temps. Quand on travaille sur la version 0.8, cela veut dire que la r‚vision du makefile.dat principal est 0.8. Ce fichier nous aiguille (de fa‡on transparente) vers les bonnes r‚visions des projets. */ /* #Sp‚cification: Archivage / makefile.dat / format Le fichier makefile.dat d‚termine le contenu d'un r‚pertoire pour une certaine r‚vision. C'est un fichier texte. Chaque ligne pr‚sente un fichier ou sous-r‚pertoire. Il y a les information suivantes sur chaques lignes, s‚par‚s par des espaces. nom_du_fichier ou sous-r‚pertoire: Simplement son nom, sans path. G‚n‚ralement les nom sont en minuscule, car c'est manipulable directement par DOS et UNIX. Si la ligne d‚crit un r‚pertoire, son nom apparaitra comme suit "r‚pertoire/makefile.dat". Le / sert de marqueur pour reconnaitre que la ligne d‚crit un sous r‚pertoire. La pr‚sence du makefile.dat est aussi importante. On peut dire en fait que chaque ligne d‚crit un fichier, ce fichier ‚tant soit local ou dans un sous-r‚pertoire. date de r‚vision: La date de r‚vision en format jj/mm/aa. Heure de r‚vision: L'heure est en format hh:mm:ss. Location du fichier dans /kit/ombre: On retrouve ici le path absolue du fichier dans /kit/ombre. On remarquera que ce path d‚bute par $(KITOMBRE). Cela fait que les makefile.dat sont transportable, de DOS … UNIX, mais aussi d'un environnement … l'autre. Num‚ro de r‚vision du fichier: Le num‚ro de r‚vision est en format num‚rique avec un point s‚parant chaque nombre. L'information de r‚vision est aussi disponible dans la location. Il y a une certaine redondance. Plusieurs outils interprŠte le makefile.dat. Il ‚tait souhaitable que ces outils soient le plus ind‚pendant possible de l'algorythme qui d‚finie la location dans /kit/ombre … partir du num‚ro de r‚vision. */ /* #Sp‚cification: Archivage / makefile.dat / path Les paths contenu dans le fichier makefile.dat sont toujours en format UNIX. Ca permet les comparaisons de path avec strcmp sans problŠme. Il sont aussi relatif … une base connue par d‚finition. */ # /* Le fichier makefile.dat est l'interface vers un r‚pertoire virtuelle. Il indique le contenu du r‚pertoire (les fichiers), leur date de r‚vision, leur num‚ro de r‚vision, et un path pour trouver une copie du fichier. */ PUBLIC MAKEFILE::MAKEFILE ( const char *_fname, // Si NULL -> makefile.dat // Si fname repr‚sente un r‚pertoire, // Prend le fichier makefile.dat bool silence, // Ne g‚nŠre pas de message si // _fname n'existe pas. const char *_projet, // Nom du projet ou sous-projet const USERINFO *_user) // Programmeur { init (_fname,silence,_projet,_user); } /* Charge le fichier makefile.dat … partir de sa r‚vision. Il indique le contenu du r‚pertoire (les fichiers), leur date de r‚vision, leur num‚ro de r‚vision, et un path pour trouver une copie du fichier. Le fichier est cherch‚ dans le r‚pertoire /kit/ombre/projet/r‚vision. Si le fichier n'existe pas, essai de l'extraire de l'archive RCS. L'absence du fichier n'est pas un erreur. */ PUBLIC MAKEFILE::MAKEFILE ( const char *_fname, // Si NULL -> makefile.dat dans \kit\ombre bool silence, // Ne g‚nŠre pas de message si // _fname n'existe pas. const REVISION *rev, const char *_projet, // Nom du projet ou sous-projet const USERINFO *_user) // Information sur environnement programmeur { // Localise le path user = _user; char revpath[MAXSIZ_PATH]; if (_fname == NULL) _fname = "makefile.dat"; char ombpath[MAXSIZ_PATH]; { _user->makombpath(_projet,ombpath); rev->formatpath (revpath); path_make (ombpath,revpath,ombpath); strcat (ombpath,".s"); path_make (ombpath,_fname,revpath); } if (!file_exist(revpath)){ char version_path[MAXSIZ_PATH]; _user->makombpath(_projet,version_path); path_make (version_path,"version.dat",version_path); VERSION_DAT v(version_path); if (v.get(rev)!=NULL){ // On est certain que cette r‚vision doit exister unzip (ombpath,rev,_fname); } } if (!file_exist(revpath)){ /* #Sp‚cification: makefile.dat / location possibles Lorsqu'on charge un makefile.dat d'un projet sans sp‚cifier (on est pas interess‚ … un en particulier, par exemple, celui dans le r‚pertoire de l'usager), on cherche dans /kit/ombre. Si on trouve pas (mˆme aprŠs le unzip) on cherche dans /kit/build. On retrouve cette situation lorsqu'on pr‚pare une nouvelle fusion dans un version non encore livr‚e dans /kit/build. Comme la version n'a pas ‚t‚ livr‚e, il n'y en a pas trace dans /kit/ombre. */ char usrpath[MAXSIZ_PATH]; _user->makusrpath(_projet,usrpath); path_make (usrpath,_fname,revpath); } init (revpath,silence,_projet,_user); } PUBLIC MAKEFILE::~MAKEFILE() { delete [] tbfile; } /* Localise l'information dans le fichier makefile.dat sur un fichier. Retourne NULL si ne trouve pas. Un fichier qui a ‚t‚ ‚limin‚ via delfil() n'est plus accessible via locate(). */ PUBLIC MAKEFILE_FILE *MAKEFILE::locate ( const char *fname, bool finddeleted) // Cherche aussi les fichiers effacés { MAKEFILE_FILE *ret = NULL; char u_fname[MAXSIZ_PATH]; path_2unix (fname,u_fname); MAKEFILE_FILE *file = tbfile; for (int i=0; iisdel()) && strcmp(u_fname,file->nom)==0){ ret = file; break; } } return ret; } /* Localise l'information dans le fichier makefile.dat sur un fichier. Retourne NULL si ne trouve pas. Un fichier qui a ‚t‚ ‚limin‚ via delfil() n'est plus accessible via locate(). */ PUBLIC MAKEFILE_FILE *MAKEFILE::locate (const char *fname) { return locate (fname,false); } /* Localise un fichier et ajoute si absent. Retourne info sur fichier. */ PROTECTED MAKEFILE_FILE *MAKEFILE::locateadd (const char *fname) { MAKEFILE_FILE *file = locate (fname); if (file == NULL){ // Nouveau fichier ou fichier qui r‚apparait file = tbfile + nbfile++; strcpy (file->nom,fname); file->path = NULL; file->efface = 0; } return file; } /* S‚lectionne l'environment de l'usager comme path courant */ PROTECTED int MAKEFILE::setusrpath (SAVEPATH *save) { char path[MAXSIZ_PATH]; user->makusrpath(projet,path); return path_pushdir (user,path,save); } /* Extrait un fichier de l'archive compress‚ et installation dans le bon r‚pertoire de /kit/ombre */ PROTECTED int MAKEFILE::unzip ( const char *abs_ombpath, const REVISION *rev, const char *nom) { /* #Sp‚cification: archivage / strat‚gie de compaction Le contenu du r‚pertoire /kit/ombre augmente sans cesse. De temps en temps, une proc‚dure (manuelle) est appliqu‚ pour transferer tous les fichiers de kit/ombre dans un fichier pack.zip. La procedure est un script UNIX dans le fichier adm/projet/ziparch. L'organisation d'un r‚pertoire projet de /kit/ombre est donc: X/ X/version.dat X/pack.zip X/sous-projet1 X/... X/dernier-sous-projet X/_0_0.s X/... X/_1_2_3_4.s X/... AprŠs la commande ziparch, les r‚pertoire *.s sont ajout‚s dans pack.zip et effac‚ ensuite. Le r‚sultat est: -R‚duction de la taille de l'archive d'environ 2/3 -R‚duction du nombre de fichier. Pour les systŠmes tel DOS et Novell qui ont un systŠme d'allocation ‚l‚mentaire, chaque fichier occupe minimalement 4k (partition large). Si un fichier est absent de /kit/ombre, on tente de l'extraire du fichier pack.zip du r‚pertoire /kit/ombre correspondant. On utilise la commande unzip. Elle doit ˆtre disponible dans le path. */ int ret = -1; if (file_type(abs_ombpath) == 1 || file_mkdiranc(abs_ombpath) != -1){ char wpath[MAXSIZ_PATH]; path_splitlex (abs_ombpath,wpath,NULL); /* Pour un projet X, si file repr‚sente un fichier, on a: abs_ombpath == /kit/ombre/X nom == nom sans aucun sous-r‚pertoire. Si file repr‚sente un sous-r‚pertoire: abs_ombpath == /kit/ombre/X/sous-r‚pertoire nom == sous-r‚pertoire/makefile.dat */ char revstr[MAXSIZ_PATH]; rev->formatpath(revstr); strcat (revstr,".s"); char fnom[MAXSIZ_NAME]; path_splitlex (nom,NULL,fnom); ret = rcs_unzip (user,wpath,revstr,fnom); } return ret; } /* Extrait une r‚vision d'un fichier ou sous-r‚pertoire dans /kit/ombre Si force == 0, alors extraction seulement si le fichier est absent du r‚pertoire ombre. Retourne -1 si erreur. Signale l'erreur interactivement. */ PUBLIC int MAKEFILE::extract (MAKEFILE_FILE *file, int force) { int ret = -1; char dest[MAXSIZ_PATH]; user->makombpath (file->getrelpath(),dest); char abs_ombpath[MAXSIZ_PATH]; path_splitlex (dest,abs_ombpath,NULL); ret = file_exist(dest) ? 0 : -1; if (force || ret == -1){ ret = unzip(abs_ombpath,file->getrev(),file->nom); } if (ret == -1){ /* #Sp‚cification: archivage / extraction / d‚tection d'erreur Si un erreur est detect‚e durant l'extraction d'un fichier l'archive, on ajoute un message d‚crivant le probleme dans le fichier error.log */ user->logerr ("Ne peut extraire %s\n",dest); char buf[1000]; snprintf (buf,sizeof(buf)-1,MSG_U(Q_EXTRACT ,"Ne peut localiser ou extraire correctement\n" "\n%s\n\n" "L'archive est probablement corrompue\n" "Voulez vous continuer quand même ?") ,dest); if (xconf_yesno ("",buf,help_nil) == MENU_YES){ /* #Sp‚cification: archivage / extraction / d‚tection d'erreur Si un erreur est detect‚e durant l'extraction d'un fichier l'archive, on demande … l'usager si il veut passer l'erreur sous-silence. Ca permet de continuer une proc‚dure et de corriger aprŠs le problŠme. Ca rend le programme plus tol‚rant. Evidemment cette strat‚gie n'est applicable que dans un cas o— l'int‚grit‚ de l'archive n'est pas mise en danger. */ ret = 0; } } return ret; } /* Corrige le no de r‚vision d'un fichier. La fonction d‚terminera le num‚ro de r‚vision requis. Tout les fichiers trait‚s ici porteront le mˆme num‚ro de r‚vision, soit le prochain num‚ro de livraison du fichier makefile.dat principal. La version courante est contenu dans le champs user. Si le fichier ne fait pas partie de makefile.dat, il est ajout‚. Retourne NULL si erreur. ATTENTION: Le r‚pertoire courant doit ˆtre celui du projet dans l'environnement usager. */ PUBLIC MAKEFILE_FILE *MAKEFILE::setrev ( const char *fname, REVISION_TYPE revtype, REVISION *oldrev) // Contiendra une copie de l'ancien num‚ro // de r‚vision. { MAKEFILE_FILE *file = locateadd(fname); file->date = file_dosdate(fname); *oldrev = file->rev; file->pushrev (NULL); user->setrevnxt(&file->rev,revtype); file->setombpath(projet); is_modif = 1; return file; } /* Corrige la r‚vision d'un fichier de fa‡on absolue. */ PUBLIC MAKEFILE_FILE *MAKEFILE::setabsrev ( const char *fname, long date, // Date du fichier const REVISION *absrev) // Nouveau num‚ro de r‚vision { MAKEFILE_FILE *file = locateadd(fname); file->date = date; file->pushrev(absrev); file->setombpath(projet); is_modif = 1; return file; } /* Enregistre le nouveau num‚ro de r‚vision d'un fichier. */ PUBLIC MAKEFILE_FILE *MAKEFILE::setrev ( const char *fname, const REVISION *newrev, const char *path, // Path ou le fichier a ‚t‚ d‚sarchiv‚. // Si c'est un path relatif, assume // qu'il est relatif … ombre. unsigned long date, // Date de r‚vision du fichier. int archivable) // Fichier archivable ou compl‚mentaire. { MAKEFILE_FILE *file = locateadd(fname); file->date = date; file->pushrev (newrev); if (file->path != NULL) free (file->path); file->archive = archivable; char relpath[MAXSIZ_PATH]; if (path_abs2rel (path,user->getombre(),relpath) != 0){ strcpy (relpath,path); } path_2unix (relpath,relpath); file->path = strdup_err (relpath); is_modif = 1; return file; } /* Retourne la structure associ‚ au makefile.dat lui-mˆme. Ne peut pas retourner NULL. */ PUBLIC MAKEFILE_FILE *MAKEFILE::toi() { assert (moi != NULL); return moi; } /* Efface tous les versions locales des fichiers qui ont ‚t‚ livr‚s. Retourne -1 si erreur. */ PUBLIC int MAKEFILE::cleanup () { int ret = -1; SAVEPATH save; if (setusrpath (&save) != -1){ ret = 0; MAKEFILE_FILE *file = tbfile; for (int i=0; iefface){ if (file_unlink (file->nom) == -1){ xconf_error (MSG_U(E_CANTDELETE ,"Ne peut effacer le fichier\n%s") ,file->nom); ret = -1; break; } } } path_popdir (&save); } return ret; } /* Extrait tout les fichiers ou les r‚pertoire d'un projet vers ombre. Retourne -1 si erreur. */ PUBLIC int MAKEFILE::extract (int extr_file) { int ret = 0; MAKEFILE_FILE *file = tbfile; for (int i=0; iis_dir){ if (!extr_file){ // Extrait les sous-r‚pertoires. Trait‚s dans prjenv.c // plutot. } }else if (file->archive && file != moi){ ret = extract (file,0); } } return ret; } /* Retourne le path relatif du fichier dans le systŠme de r‚f‚rence ombre. C'est le path vers la version originale. Si fichier == NULL, alors retourne le path original du makefile.dat. */ PUBLIC const char *MAKEFILE::getref (const char *fichier) { const char *ret = NULL; MAKEFILE_FILE *file = fichier == NULL ? moi : locate(fichier); if (file != NULL){ ret = file->getref(); } return ret; } #ifdef TEST void error_showdef (int noerr, ...) { fprintf (stderr,"Error #%d\n",noerr); exit (-1); } int main (int argc, char *argv[]) { USERINFO user(prog_getid(true),"ref" ,EVOL "/kit/groupe2",EVOL "/kit/groupe2" ,EVOL "/kit/ombre"); MAKEFILE mkf (NULL,0,"vdi",&user); mkf.ecrit (); return 0; } #endif