diff -ur /usr/src/usr.sbin/ctm/mkCTM/mkctm.c mkCTM/mkctm.c --- /usr/src/usr.sbin/ctm/mkCTM/mkctm.c 2010-04-24 17:19:38.000000000 -0500 +++ mkCTM/mkctm.c 2012-09-09 13:40:02.000000000 -0500 @@ -54,6 +54,9 @@ u_long s_edit_files, s_edit_bytes, s_edit_saves; u_long s_sub_files, s_sub_bytes; +char *svnbase = NULL, + svnbase_default[] = "base"; + void Usage(void) { @@ -63,6 +66,7 @@ fprintf(stderr, "\t\t-B bogus_regexp\n"); fprintf(stderr, "\t\t-D damage_limit\n"); fprintf(stderr, "\t\t-I ignore_regexp\n"); + fprintf(stderr, "\t\t-s svn-base-dir\n"); fprintf(stderr, "\t\t-q\n"); fprintf(stderr, "\t\t-v\n"); } @@ -493,6 +497,134 @@ free(nl2); } +void +Do_ctm_status(const char *dir1, const char *dir2) +{ + char *name = ""; + int i1, i2, n1, n2, i; + struct dirent **nl1, **nl2; + char *buf1 = alloca(strlen(dir1) + strlen(name) + 4); + char *buf2 = alloca(strlen(dir2) + strlen(name) + 4); + + strcpy(buf1, dir1); strcat(buf1, "/"); strcat(buf1, name); + strcpy(buf2, dir2); strcat(buf2, "/"); strcat(buf2, name); + n1 = scandir(buf1, &nl1, dirselect, alphasort); + n2 = scandir(buf2, &nl2, dirselect, alphasort); + i1 = i2 = -1; + GetNext(&i1, &n1, nl1, dir1, name, &s1_ignored, &s1_bogus, &s1_wrong); + GetNext(&i2, &n2, nl2, dir2, name, &s2_ignored, &s2_bogus, &s2_wrong); + for (;i1 < n1 || i2 < n2;) { + + if (damage_limit && damage > damage_limit) + break; + + /* Get next item from list 1 */ + if (i1 < n1 && !nl1[i1]) + GetNext(&i1, &n1, nl1, dir1, name, + &s1_ignored, &s1_bogus, &s1_wrong); + + /* Get next item from list 2 */ + if (i2 < n2 && !nl2[i2]) + GetNext(&i2, &n2, nl2, dir2, name, + &s2_ignored, &s2_bogus, &s2_wrong); + + if (i1 >= n1 && i2 >= n2) { + /* Done */ + break; + } else if (i1 >= n1 && i2 < n2) { + /* end of list 1 */ + if (strcmp(nl2[i2]->d_name,".ctm_status")==0) + Add(dir1, dir2, name, nl2[i2]); + free(nl2[i2]); nl2[i2] = 0; + } else if (i1 < n1 && i2 >= n2) { + /* end of list 2 */ + free(nl1[i1]); nl1[i1] = 0; + } else if (!(i = strcmp(nl1[i1]->d_name, nl2[i2]->d_name))) { + /* Identical names */ + if (nl1[i1]->d_type == nl2[i2]->d_type && strcmp(nl1[i1]->d_name,".ctm_status")==0) { + /* same type and .ctm_status */ + Equ(dir1, dir2, name, nl1[i1]); + } + free(nl1[i1]); nl1[i1] = 0; + free(nl2[i2]); nl2[i2] = 0; + } else if (i < 0) { + /* Something extra in list 1, delete it */ + free(nl1[i1]); nl1[i1] = 0; + } else { + /* Something extra in list 2, add it */ + free(nl2[i2]); nl2[i2] = 0; + } + } + if (n1 >= 0) + free(nl1); + if (n2 >= 0) + free(nl2); +} + +void +DoSvn(const char *dir1, const char *dir2) +{ + char current_file[] = "/db/current"; + char *buf1 = alloca(strlen(dir1) + strlen(current_file) + strlen(svnbase) + 4); + char *buf2 = alloca(strlen(dir2) + strlen(current_file) + strlen(svnbase) + 4); + char *tmpdir = getenv("TMPDIR"); + if (tmpdir == NULL) + tmpdir = strdup(_PATH_TMP); + char tmpfilebase[] = "/CTMserver.XXXXXXXXXX"; + char *tmpfilename = alloca(strlen(tmpdir)+strlen(tmpfilebase)+4); + int command_size = strlen(dir2) + strlen(tmpdir)+strlen(tmpfilebase) + strlen(svnbase) + 128; + char *command = alloca(command_size+1); + long int release1, release2; + FILE *current1, *current2; + int ret_val; + + Do_ctm_status(dir1, dir2); + + strcpy(buf1, dir1); strcat(buf1, "/"); strcat(buf1, svnbase); strcat(buf1, current_file); + strcpy(buf2, dir2); strcat(buf2, "/"); strcat(buf2, svnbase); strcat(buf2, current_file); + strcpy(tmpfilename, tmpdir); strcat(tmpfilename, tmpfilebase); + mktemp(tmpfilename); + + current1 = fopen(buf1,"r"); + current2 = fopen(buf2,"r"); + + if (current1 != NULL) { + fscanf(current1,"%ld",&release1); + fclose(current1); + } else + release1 = -1; + if (current2 != NULL) { + fscanf(current2,"%ld",&release2); + fclose(current2); + } else + release2 = -1; + + if (release1 == -1) { + snprintf(command,command_size,"tar -C %s -cvf %s %s 2>&%d\n",dir2,tmpfilename,svnbase,fileno(logf)); + fflush(logf); + ret_val = system(command); + if (ret_val!=0) errx(1,"The command \"%s\" failed with return value %d",command,ret_val); + printf("CTMTR "); + change++; + } else if (release2 > release1) { + snprintf(command,command_size,"svnadmin dump %s/%s -r %ld:%ld --incremental --deltas 2>&%d > %s\n",dir2,svnbase,release1+1,release2,fileno(logf),tmpfilename); + fflush(logf); + ret_val = system(command); + if (ret_val!=0) errx(1,"The command \"%s\" failed with return value %d",command,ret_val); + printf("CTMSV %s %ld ", svnbase, release1); + change++; + } + + if (change >= 2) { + StatFile(tmpfilename); + printf("%jd\n", st.st_size); + snprintf(command,command_size,"cat %s; rm -f %s\n",tmpfilename,tmpfilename); + ret_val = system(command); + if (ret_val!=0) errx(1,"The command \"%s\" failed with return value %d",command,ret_val); + putchar('\n'); + } +} + int main(int argc, char **argv) { @@ -512,7 +644,7 @@ flag_ignore = 1; #endif - while ((i = getopt(argc, argv, "D:I:B:l:qv")) != -1) + while ((i = getopt(argc, argv, "s:D:I:B:l:qv")) != -1) switch (i) { case 'D': damage_limit = strtol(optarg, 0, 0); @@ -555,6 +687,12 @@ case 'v': verbose++; break; + case 's': + if (!*optarg) + break; + svnbase = malloc(strlen(optarg) + 1); + strcpy(svnbase, optarg); + break; case '?': default: Usage(); @@ -566,6 +704,8 @@ if (!logf) logf = fopen(_PATH_DEVNULL, "w"); + if (!svnbase) + svnbase = svnbase_default; setbuf(stdout, 0); if (argc != 6) { @@ -581,7 +721,10 @@ argv[0], argv[1], argv[2], argv[3]); printf("CTM_BEGIN 2.0 %s %s %s %s\n", argv[0], argv[1], argv[2], argv[3]); - DoDir(argv[4], argv[5], ""); + if (strncmp(argv[0],"svn",3) == 0) + DoSvn(argv[4], argv[5]); + else + DoDir(argv[4], argv[5], ""); if (damage_limit && damage > damage_limit) { print_stat(stderr, "DAMAGE: "); errx(1, "damage of %d would exceed %d files", @@ -591,7 +734,8 @@ } else { printf("CTM_END "); fprintf(logf, "CTM_END\n"); - print_stat(stderr, "END: "); + if (strncmp(argv[0],"svn",3) != 0) + print_stat(stderr, "END: "); } exit(0); }