#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

const int maxLine=1024;
const char *separator1="@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@";

static
void ChopEOL(char *b)
{
 int l=strlen(b);
 if (b[l-1]=='\n') b[l-1]=0;
}

static
char *GetFileName(char *s)
{
 if (*s!='"') return 0;
 char *b;
 for (b=s+1; *b && *b!='"'; b++);
 *b=0;
 return strdup(s+1);
}

static
void CreateTmpFile(FILE *f, char *cf, int &endM)
{
 char b[maxLine];
 long start=ftell(f),end;
 do
   {
    end=ftell(f);
    fgets(b,maxLine-1,f);
   }
 while (!feof(f) && *b!='~' && strncmp(b,separator1,sizeof(separator1)-1)!=0);
 endM=*b=='@';
 if (feof(f))
   {
    printf("Unexpected end of file\n");
    exit(2);
   }
 long pos=ftell(f);
 strcpy(cf,"/tmp/csXXXXXX");
 int fh=mkstemp(cf);
 if (fh==-1)
   {
    printf("Error creating temporal file\n");
    exit(3);
   }
 long l=end-start;
 char buf[l];
 fseek(f,start,SEEK_SET);
 fread(buf,l,1,f);
 fseek(f,pos,SEEK_SET);
 write(fh,buf,l);
 close(fh);
}

void ProcessFile(const char *fileIn, int noCI)
{
 FILE *f=fopen(fileIn,"rt");
 if (!f)
   {
    printf("Error opening %s\n",fileIn);
    return;
   }
 char b[maxLine];
 int first,newFile;
 fgets(b,maxLine-1,f);
 if (strncmp(b,separator1,sizeof(separator1)-1)!=0)
   {
    printf("Separator expected\n");
    return;
   }
 char *file;
 while (!feof(f))
   {
    // Get the file name
    fgets(b,maxLine-1,f);
    if (strncmp(b,"File: ",6)==0)
      {
       file=GetFileName(b+6);
       printf("File: %s\n",file);
       newFile=0;
      }
    else if (strncmp(b,"New File: ",10)==0)
      {
       file=GetFileName(b+10);
       printf("New File: %s\n",file);
       newFile=1;
      }
    else
      {
       printf("File expected\n");
       return;
      }
    fgets(b,maxLine-1,f);
    ChopEOL(b);
    if (strncmp(b,separator1,sizeof(separator1)-1)!=0)
      {
       printf("Separator expected\n");
       return;
      }
    first=1;
    int endM;
    // Now the patches
    do
      {
       fgets(b,maxLine-1,f);
       if (*b=='@' || feof(f))
          break;
       if (strncmp(b,"date: ",6)!=0)
         {
          printf("Date expected");
          return;
         }

       char cfc[16]; *cfc=0;
       char cfp[16]; *cfp=0;
       CreateTmpFile(f,cfc,endM);
       if (!endM)
         {
          CreateTmpFile(f,cfp,endM);
          if (endM)
            {
             printf("What?!\n");
             exit(4);
            }
          if (newFile && first)
             sprintf(b,"cp %s %s",cfp,file);
          else
             sprintf(b,"patch %s %s",file,cfp);
          fprintf(stderr,"%s\n",b);
          system(b);
          if (newFile && first)
            {
             sprintf(b,"cvs -z 9 add %s",file);
             fprintf(stderr,"%s\n",b);
             system(b);
            }
         }

       if (strcmp(file,"change.log")!=0)
         {
          sprintf(b,"cvs -z 9 ci -F %s %s",cfc,file);
          fprintf(stderr,"%s\n",b);
          if (!noCI)
             system(b);
         }
       unlink(cfc);
       unlink(cfp);
       first=0;
      }
    while (!feof(f) && !endM);
    if (strcmp(file,"change.log")==0 && !noCI)
      {// My change.log uses $Log
       system("cvs -z 9 ci -m + change.log");
      }
    free(file);
   }
 fclose(f);
}

int main(int argc, char *argv[])
{
 if (argc!=3)
   {
    printf("cvssyncput Copyright (c) 2001 by Salvador E. Tropea.\n");
    printf("Synchronizes two cvs trunks with information generated by cvssyncget.\n\n");
    printf("Use: cvssyncput info_file extra.tar.gz\n\n");
    return 1;
   }

 char b[12+strlen(argv[2])];
 sprintf(b,"tar zxvf %s",argv[2]);
 system(b);

 ProcessFile(argv[1],0);
 return 0;
}
