#include <stdio.h> #include <stdlib.h> #include <sys/stat.h> #include <time.h> #include <string.h> //#define INIT_SIZE 20 #define INCREASEMENT 10 //FILE *fcmd;//存放从键盘获得的命令 int quitFlag=0; char Para[60]; typedef struct CVersion { int cur_num;//当前版本数目 int max_num;//能容纳的最大版本数目 int *index;//存放版本信息的数组 char **log;//存放 日志文件的信息 }CVersion; CVersion Version; void Read_LogFile();//读日志文件 void Write_LogFile(); //写日志文件 //int *Version; //解析键盘命令为相应的命令号 //---cmdLine---cmdNum------ // create 1 // status 2 // add 3 // delete 4 // update 5 // commit 6 // revert 7 // log 8 // attribute 9 // quit 10 //------------------------- void svn(); void getCmdLine(); int Get_Commond_type(char *); void cmd_exec(int cmdNum); void createFolder(); int showStatus(int flag); //void showStatus(); void OnLog(); void OnQuit(); void OnCommit(); void OnAttribute(); void OnAdd(); void OnDelete(); void OnUpDate(); void OnRevert(); int main(void) { svn(); return 1; } void svn() { int cmdNum; char command[70]; FILE *fcmd; do{ printf("/nsvn>"); getCmdLine(); fcmd=fopen("c://cmdline.dat" ,"r");//?? if(fcmd==NULL) { printf("读取cmdline.dat失败"); exit(-1); } fgets(command,30,fcmd); cmdNum=Get_Commond_type(command); fclose(fcmd); // if(cmdNum==10)quitFlag=1; system("del c://cmdline.dat"); cmd_exec(cmdNum); }while(quitFlag!=1); system("pause"); } //读取键盘命令存入到cmdline.txt文件中 void getCmdLine() { char ch; FILE *fcmd; fcmd=fopen("c://cmdline.dat","w+");//需注意打开文件和关闭文件要配对?? if(fcmd==NULL) { printf("键盘命令存取失败"); exit(-1); } while((ch=fgetc(stdin))!='/n') { fputc(ch,fcmd); // printf("%c",ch); } fclose(fcmd); } int Get_Commond_type(char *s) { char *commond[10]={"create","status","add","delete","update","commit","revert","log","attribute","quit"}; int i=0,j=0,CommondType; char str[15];//?? Para[0]='/0'; while(s[i]==' '||s[i]=='/t') i++;//去掉命令前输入的空格和制表符 while(s[i]!=' '&&s[i]!='/t'&&s[i]!='/0') str[j++]=s[i++];//将输入的命令存入到数组str中 str[j]='/0'; for(CommondType=0;CommondType<10&&strcmp(commond[CommondType],str);CommondType++) ;//判断输入的命令是何种类型 if(CommondType==10) return -1;//没找到对应的命令,返回-1 while(s[i]==' '||s[i]=='/t') i++;//去掉命令和参数之间输入的空格和制表符 j=0; if(CommondType!=5) while(s[i]!='/0'&&s[i]!=' '&&s[i]!='/t') Para[j++]=s[i++];//存储参数 else while(s[i]!='/0') Para[j++]=s[i++]; Para[j]='/0';//获得输入命令的参数 while(s[i]!='/0'&&(s[i]==' '||s[i]=='/t')) i++; if (s[i]!='/0')//若参数后面还有字符,则错误命令格式 return -1; switch (CommondType) { case 0: case 1: case 6: case 9: if(!j) return CommondType+1; else return -1; case 2: case 3: if(j) return CommondType+1; else return -1; default: return CommondType+1; } } //解析键盘命令为相应的命令号 //---cmdLine---cmdNum------ // create 1 // status 2 // add 3 // delete 4 // update 5 // commit 6 // revert 7 // log 8 // attribute 9 // quit 10 //------------------------- void cmd_exec(int cmdNum) { switch(cmdNum) { case 1:createFolder();break; case 2:showStatus(0);break; case 3:OnAdd();break; case 4:OnDelete();break; case 5:OnUpDate();break; case 6:OnCommit();break; case 7:OnRevert();break; case 8:OnLog();break; case 9:OnAttribute();break; case 10:quitFlag=1;OnQuit();break; default:printf("No such command!/n");break; } } void Read_LogFile() { FILE *fp; int data_num,i,j,k; char s[80]; if((fp=fopen("_svn_/log.txt","r"))==NULL) { //打开配置文件 printf("这个文件不存在,出现错误!/n"); return; } fscanf(fp,"%d",&data_num);//读取第一个数字,代表版本的数目 Version.max_num=data_num+INCREASEMENT+1;//对结构组中的max_num项赋值 Version.cur_num=data_num; Version.index=(int*)malloc((Version.max_num)*sizeof(int)); Version.log=(char **)malloc(Version.max_num*sizeof(char*)); //进行动态申请空间 fscanf(fp,"%d",&(Version.index[0]));//读取第二个数字,表示目前的版本号 Version.log[0]=NULL;//对应的日志项为空 fgets(s,80,fp);//读取下一条记录 日志不超过50字符,可行 for(i=1;i<=Version.cur_num;i++) {//顺序读取每个版本的信息 fgets(s,80,fp); while(s[0]=='/n') fgets(s,80,fp); j=0; k=0; while(s[j]>='0'&&s[j]<='9')//??如果提交的日志第一个字符为数字 {//读取这一行前面的数字字符 k*=10; k+=(s[j]-'0'); j++; }//通过循环语句,获得版本号 Version.index[i]=k;//将版本号存到结构体中 j++; k=strlen(s)-j;//计算出版本信息的长度 if(k!=0){//k!=0,说明这一项中有相应的版本信息 ??版本长度最大为50,没有必要动态申请 Version.log[i]=(char*)malloc((k+1)*sizeof(char)); //动态申请空间 for(k=0;s[j]!='/0';k++,j++)//将数组s中的信息复制到版本信息中 Version.log[i][k]=s[j]; Version.log[i][k]='/0'; // printf("%s",Version.log[i]); } else Version.log[i]=NULL;//k==0时,对应的版本信息项为空 } fclose(fp); //关闭文件 } void Write_LogFile() { FILE *fp; int i; if((fp=fopen("_svn_/log.txt","w+"))==NULL) {//以写更新的方式打开配置文件 printf("这个文件不存在,出现错误!/n"); return; } fprintf(fp,"%d",Version.cur_num); //先存入版本数目的信息 for(i=0;i<=Version.cur_num;i++) {//存入每一个版本号和版本信息 fprintf(fp,"/n%d",Version.index[i]); if(Version.log[i])//如果这一项的版本信息不空 { fprintf(fp," ");//写入空格符 //fputs(Version.log[i],fp);//写文件 fprintf(fp,"%s",Version.log[i]); free(Version.log[i]);//释放动态申请的空间 } else fprintf(fp,"/n"); } free(Version.index);//释放动态申请的空间 free(Version.log);//释放空间 fclose(fp);//关闭文件 } void createFolder(){ FILE *fp; if((fp=fopen("_svn_/log.txt","r"))==NULL) { system("mkdir _svn_"); system("mkdir _svn_//1"); system("mkdir _svn_//0"); Version.cur_num=0; Version.max_num=10; Version.index=(int *)malloc(Version.max_num*sizeof(int)); Version.log=(char **)malloc(Version.max_num*sizeof(char *)); Version.log[0]=NULL; Version.index[0]=0; Version.index[1]=0; return; } fclose(fp); Read_LogFile(); } void OnLog() { int ver,len=0,i; int a[20]; if(Para[0]=='/0') { ver=Version.index[0]; i=ver; while(i!=0) { a[len++]=i; i=Version.index[i]; } len--; while(len!=-1) { printf("/nversion: %d",a[len]); if(a[len]==Version.index[0]) printf("<-"); printf("/nlog: %s",Version.log[a[len]]); len--; } return; } i=0; ver=0; while(Para[i]>='0'&&Para[i]<='9') { ver*=10; ver+=Para[i]-'0'; i++; } if(Para[i]){ printf("Error commond !/n"); return; } if(ver>Version.cur_num||ver<=0) { printf("no such version!/n"); return; } printf("/nversion: %d",ver); if(ver==Version.index[0]) printf("<-"); printf("/nlog: %s",Version.log[ver]); } void OnQuit() { Write_LogFile(); } void OnCommit() { FILE *fp,*fc; char pathp[40]="dir /b _svn_//",pathc[40]="dir /b _svn_//"; char s[10]; char filep[15]="_svn_//",filec[15]="_svn_//"; int i,j; struct stat statp,statc; if(Version.index[0]!=0) { i=Version.cur_num+1; j=Version.index[0]; strcat(pathp,itoa(j,s,10)); strcat(filep,s); strcat(pathp," >_svn_//a.txt"); system(pathp); strcat(pathc,itoa(i,s,10)); strcat(filec,s); strcat(pathc," >_svn_//b.txt"); system(pathc); fp=fopen("_svn_//a.txt","r"); fc=fopen("_svn_//b.txt","r"); while(!feof(fp)&&!feof(fc)) { fgets(pathp,19,fp); fgets(pathc,19,fc); if(!feof(fp)&&!feof(fc)) { if(strcmp(pathp,pathc)) break;//两字符串不同,说明有更改,跳出循环体 pathp[strlen(pathp)-1]='/0'; pathc[strlen(pathc)-1]='/0'; strcat(filep,"//"); strcat(filep,pathp); strcat(filec,"//"); strcat(filec,pathc); stat(filep,&statp); stat(filec,&statc); char chp[25]; char chc[25]; chp[0]='/0'; chc[0]='/0'; strncpy(chp,ctime(&statp.st_mtime),24); strncpy(chc,ctime(&statc.st_mtime),24); chp[24]='/0'; chc[24]='/0'; if(strcmp(chp,chc)) break;//获得文件的最后修改日期,如果最后修改日期不同,则认为是不同的文件 } } if(feof(fp)&&feof(fc)) {//如果版本没有被更新过,输出no modification printf("no modification/n"); fclose(fp); fclose(fc); system("del _svn_//a.txt"); system("del _svn_//b.txt"); return ; } fclose(fp); fclose(fc); system("del _svn_//a.txt"); system("del _svn_//b.txt"); } Version.cur_num++;//版本数目加一 i=Version.cur_num;//将版本数目放在变量i中 Version.index[i]=Version.index[0]; Version.index[0]=i;//更新当前版本号 if(Para[0]!='/0'){ Version.log[i]=(char *)malloc((strlen(Para)-1)*sizeof(char)); for(j=1;Para[j]!='"';j++) Version.log[i][j-1]=Para[j]; Version.log[i][j-1]='/0'; } else Version.log[i]=NULL; itoa(i+1,s,10); strcpy(pathp,"mkdir _svn_//"); strcat(pathp,s); system(pathp); strcpy(pathp,"copy _svn_//"); strcat(pathp,(itoa(i,s,10))); strcat(pathp,"//* _svn_//"); strcat(pathp,itoa(i+1,s,10)); strcat(pathp," > _svn_//a.txt"); system(pathp); system("del _svn_//a.txt"); } void OnAttribute() { int ver; //FILE *fp; char path[40]="dir /b _svn_//"; if(Para[0]!='/0'){ strcat(path,Para); ver=atoi(Para); } else{ ver=Version.index[0];//获得当前版本 strcat(path,itoa(ver,Para,10));//获得版本对应的路径 } //strcat(path," >_svn_//a.txt"); if(ver>Version.cur_num||ver<=0){ printf("no such version!/n"); return; } printf("version : %d/nfile :/n",ver); system(path); //puts(path); //fp=fopen("_svn_//a.txt","r"); //if(!fp) return; printf("log : %s",Version.log[ver]); } void OnAdd() { int ver=Version.cur_num+1; char path[40]="copy "; char s[10]; FILE *fp; if((fp=fopen(Para,"r"))==NULL) { printf("no file /"%s/"/n",Para); return; } fclose(fp); strcat(path,Para); strcat(path," _svn_//"); strcat(path,itoa(ver,s,10)); strcat(path,"> _svn_//a.txt"); system(path); strcpy(path,"del _svn_//a.txt"); system(path); } void OnDelete() { int ver=Version.cur_num+1; char path[40]="del _svn_//"; char s[10]; FILE *fp; strcat(path,itoa(ver,s,10)); strcat(path,"//"); strcat(path,Para); if((fp=fopen(Para,"r"))==NULL) { printf("no file /"%s/"/n",Para); return; } fclose(fp); system(path); } void OnUpDate() { int ver; char path[40]="del /Q _svn_//",s[10]; if(showStatus(1)) { printf("there changes /n"); return; } if(Para[0]=='/0') ver=Version.cur_num; else ver=atoi(Para); if(ver>Version.cur_num||ver<=0) { printf("no such version %d/n",ver); return ; } strcat(path,itoa(Version.cur_num+1,s,10)); system(path); strcpy(path,"copy _svn_//"); strcat(path,Para); strcat(path,"//* _svn_//"); strcat(path,itoa(Version.cur_num+1,s,10)); strcat(path," >_svn_//a.txt"); system(path); system("del _svn_//a.txt"); Version.index[0]=ver; } int showStatus(int flag) { char *dir_ver_cur;//输出版本所在文件夹里面内容到vv.txt的system字符串 char *path_ver_cur;//寻找当前版本某一个文件的路径 char *path_ver;//去掉路径后面的换行符 char *path_out;//受管理文件的路径 char *dir_ver_pre; struct stat statbuf1; struct stat statbuf2; char a1[25]; char a2[25]; a1[0]='/0'; a2[0]='/0'; char verFolderName[2]; char verFolderName_pre[2]; char filename_out[15]; filename_out[0]='/0'; FILE *fall; FILE *fvv_active; FILE *fsearch; FILE *fvv_pre; system("dir /b >_svn_//all.txt"); dir_ver_cur=(char *)malloc(30*sizeof(char)); path_ver_cur=(char *)malloc(30*sizeof(char)); path_ver=(char *)malloc(30*sizeof(char)); path_out=(char *)malloc(30*sizeof(char)); dir_ver_pre=(char *)malloc(30*sizeof(char)); dir_ver_cur[0]='/0'; dir_ver_pre[0]='/0'; // 将当前版本里面所有文件的文件名写到vv.txt文件里面 dir_ver_cur=strcat(dir_ver_cur,"dir /b _svn_//"); itoa(Version.cur_num+1,verFolderName,10); dir_ver_cur=strcat(dir_ver_cur,verFolderName); dir_ver_cur=strcat(dir_ver_cur,">_svn_//vv.txt"); system(dir_ver_cur); dir_ver_pre=strcat(dir_ver_pre,"dir /b _svn_//"); itoa(*(Version.index),verFolderName_pre,10); dir_ver_pre=strcat(dir_ver_pre,verFolderName_pre); dir_ver_pre=strcat(dir_ver_pre,">_svn_//vv_pre.txt"); system(dir_ver_pre); // free(dir_ver_pre); //去掉all.txt里面的非文本文件,如_svn_文件夹 和svn.exe fvv_active=fopen("_svn_//all.txt","r"); fall=fopen("_svn_//all_simp.txt","w+"); while(fgets(filename_out,15,fvv_active)!=NULL) { if(strcmp(filename_out,"_svn_/n") && strcmp(filename_out,"svn.exe/n")) { fputs(filename_out,fall); } } fclose(fall); fclose(fvv_active); fall=fopen("_svn_//all_simp.txt","r"); if(fall==NULL) { printf("无法找到all_simp.txt文件"); exit(-1); } while(fgets(filename_out,15,fall)!=NULL) { path_ver_cur[0]='/0'; path_ver[0]='/0'; path_ver_cur=strcat(path_ver_cur,"_svn_//"); path_ver_cur=strcat(path_ver_cur,verFolderName); path_ver_cur=strcat(path_ver_cur,"//"); path_ver_cur=strcat(path_ver_cur,filename_out); strncpy(path_ver,path_ver_cur,strlen(path_ver_cur)-1); path_ver[strlen(path_ver_cur)-1]='/0'; fsearch=fopen(path_ver,"r"); //在当前版本里面没找到该文件说明该文件未受管理 if(fsearch==NULL) { if(flag==0)printf("? %s",filename_out); } else { strncpy(path_out,filename_out,strlen(filename_out)); path_out[strlen(filename_out)-1]='/0'; stat(path_out,&statbuf1); stat(path_ver,&statbuf2); strncpy(a1,ctime(&statbuf1.st_mtime),24); a1[24]='/0'; strncpy(a2,ctime(&statbuf2.st_mtime),24); a2[24]='/0'; // printf("/n%d/n",strncmp(ctime(&statbuf1.st_mtime),ctime(&statbuf2.st_mtime) ,24)); if(strcmp(a1,a2)) { if(flag==0)printf("M %s",filename_out); else return 1; } fclose(fsearch); } } fclose(fall); //在受管理的文件中没找到该版本本应管理的文件则说明此文件丢失 dir_ver_cur[0]='/0'; strcat(dir_ver_cur,"_svn_//vv.txt"); // strcat(dir_ver_cur,verFolderName); fvv_active=fopen(dir_ver_cur,"r"); if(fvv_active==NULL) { printf("vv.txt无法打开"); exit(-1); } while(fgets(filename_out,15,fvv_active)!=NULL) { path_out[0]='/0'; strcat(path_out,filename_out); path_out[strlen(path_out)-1]='/0'; fall=fopen(path_out,"r"); if(fall==NULL) { if(flag==0)printf("G %s",filename_out); else return 1; } else fclose(fall); } fclose(fvv_active); //活动版本中少了当前版本的内容,则视为delete fvv_pre=fopen("_svn_//vv_pre.txt","r"); if(fvv_pre==NULL) { printf("vv_pre.txt无法打开"); exit(-1); } while(fgets(filename_out,15,fvv_pre)!=NULL) { path_out[0]='/0'; strcat(path_out,"_svn_//"); strcat(path_out,verFolderName); strcat(path_out,"//"); strcat(path_out,filename_out); path_out[strlen(path_out)-1]='/0'; fall=fopen(path_out,"r"); if(fall==NULL) { if(flag==0)printf("- %s",filename_out); else return 1; } else fclose(fall); } fclose(fvv_pre); //活动版本中比当前版本多了一些内容,则视为+ fvv_active=fopen("_svn_//vv.txt","r"); if(fvv_active==NULL) { printf("vv.txt无法打开"); exit(-1); } while(fgets(filename_out,15,fvv_active)!=NULL){ path_out[0]='/0'; strcat(path_out,"_svn_//"); strcat(path_out,verFolderName_pre); strcat(path_out,"//"); strcat(path_out,filename_out); path_out[strlen(path_out)-1]='/0'; fall=fopen(path_out,"r"); if(fall==NULL) { if(flag==0)printf("+ %s",filename_out); else return 1; } else fclose(fall); } fclose(fvv_active); system("del _svn_//vv.txt"); system("del _svn_//vv_pre.txt"); system("del _svn_//all.txt"); system("del _svn_//all_simp.txt"); free(dir_ver_cur); free(path_ver_cur); free(path_ver); free(path_out); return 0; } void OnRevert() { char *del_dir; char *pre_dir; char *active_dir; char * copy_sentence1; char * copy_sentence2; char folderName_active[2]; char folderName_pre[2]; del_dir=(char *)malloc(30*sizeof(char)); del_dir[0]='/0'; del_dir=strcat(del_dir,"del "); del_dir=strcat(del_dir,"_svn_//"); itoa(Version.cur_num+1,folderName_active,10); del_dir=strcat(del_dir,folderName_active); del_dir=strcat(del_dir," /s/q>_svn_//delDir.txt"); // puts(del_dir); system(del_dir); if(*(Version.index )!=0){ pre_dir=(char *)malloc(30*sizeof(char)); active_dir=(char *)malloc(30*sizeof(char)); copy_sentence1=(char *)malloc(50*sizeof(char)); copy_sentence2=(char *)malloc(50*sizeof(char)); if(pre_dir==NULL||active_dir==NULL||copy_sentence1==NULL||copy_sentence2==NULL) { printf("堆栈空间不够"); exit(-1); } pre_dir[0]='/0'; active_dir[0]='/0'; copy_sentence1[0]='/0'; copy_sentence2[0]='/0'; pre_dir=strcat(pre_dir,"_svn_//"); itoa(*(Version.index),folderName_pre,10); pre_dir=strcat(pre_dir,folderName_pre); active_dir=strcat(active_dir,"_svn_//"); active_dir=strcat(active_dir,folderName_active); copy_sentence1=strcat(copy_sentence1,"copy "); copy_sentence1=strcat(copy_sentence1,pre_dir); copy_sentence1=strcat(copy_sentence1,"//*.* "); copy_sentence2=strcat(copy_sentence2,copy_sentence1); copy_sentence1=strcat(copy_sentence1,active_dir); copy_sentence1=strcat(copy_sentence1," /y>_svn_//delDir.txt"); //puts(copy_sentence1); system(copy_sentence1); copy_sentence2=strcat(copy_sentence2,". /y>_svn_//delDir.txt"); // puts(copy_sentence2); system(copy_sentence2); //free(pre_dir); //free(active_dir); //free(copy_sentence1); //free(copy_sentence2); } //free(del_dir); system("del _svn_//delDir.txt"); } 转载自: http://50vip.com