Fossil

Check-in [702331e0]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Fix the empty-dirs property so that creates the complete path of directories, not just leaves, and so that it does not leak memory.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 702331e057f6ec35d93ec0c12d9f4721d5b6d74c
User & Date: drh 2015-05-18 13:56:48.122
Context
2015-05-18
14:04
If the "r=" or "t=" query parameter on /timeline does not match any tag or branch name, then show an empty timeline rather than just ignoring the query parameter. Ticket [674d5d5556]. ... (check-in: a2f03b8c user: drh tags: trunk)
13:56
Fix the empty-dirs property so that creates the complete path of directories, not just leaves, and so that it does not leak memory. ... (check-in: 702331e0 user: drh tags: trunk)
2015-05-17
22:24
Remove redundant assignment in blob_str() setting nUsed to zero right after confirming it is zero. ... (check-in: 48499514 user: andygoth tags: trunk)
17:55
Revert inadvertent style change. ... (Closed-Leaf check-in: bdb90f69 user: andygoth tags: andygoth-empty-dirs-parents)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/blob.c.
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
#endif
    fwrite(blob_buffer(pBlob), 1, nWrote, stdout);
#if defined(_WIN32)
    fflush(stdout);
    _setmode(_fileno(stdout), _O_TEXT);
#endif
  }else{
    file_mkfolder(zFilename, 1);
    out = fossil_fopen(zFilename, "wb");
    if( out==0 ){
      fossil_fatal_recursive("unable to open file \"%s\" for writing",
                             zFilename);
      return 0;
    }
    blob_is_init(pBlob);







|







836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
#endif
    fwrite(blob_buffer(pBlob), 1, nWrote, stdout);
#if defined(_WIN32)
    fflush(stdout);
    _setmode(_fileno(stdout), _O_TEXT);
#endif
  }else{
    file_mkfolder(zFilename, 1, 0);
    out = fossil_fopen(zFilename, "wb");
    if( out==0 ){
      fossil_fatal_recursive("unable to open file \"%s\" for writing",
                             zFilename);
      return 0;
    }
    blob_is_init(pBlob);
Changes to src/file.c.
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
*/
void file_copy(const char *zFrom, const char *zTo){
  FILE *in, *out;
  int got;
  char zBuf[8192];
  in = fossil_fopen(zFrom, "rb");
  if( in==0 ) fossil_fatal("cannot open \"%s\" for reading", zFrom);
  file_mkfolder(zTo, 0);
  out = fossil_fopen(zTo, "wb");
  if( out==0 ) fossil_fatal("cannot open \"%s\" for writing", zTo);
  while( (got=fread(zBuf, 1, sizeof(zBuf), in))>0 ){
    fwrite(zBuf, 1, got, out);
  }
  fclose(in);
  fclose(out);







|







384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
*/
void file_copy(const char *zFrom, const char *zTo){
  FILE *in, *out;
  int got;
  char zBuf[8192];
  in = fossil_fopen(zFrom, "rb");
  if( in==0 ) fossil_fatal("cannot open \"%s\" for reading", zFrom);
  file_mkfolder(zTo, 0, 0);
  out = fossil_fopen(zTo, "wb");
  if( out==0 ) fossil_fatal("cannot open \"%s\" for writing", zTo);
  while( (got=fread(zBuf, 1, sizeof(zBuf), in))>0 ){
    fwrite(zBuf, 1, got, out);
  }
  fclose(in);
  fclose(out);
528
529
530
531
532
533
534



535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554

555

556

557
558
559
560
561
562
563
564

565
566
567
568
569
570
571
  }
  return 0;
}

/*
** Create the tree of directories in which zFilename belongs, if that sequence
** of directories does not already exist.



*/
void file_mkfolder(const char *zFilename, int forceFlag){
  int i, nName;
  char *zName;

  nName = strlen(zFilename);
  zName = mprintf("%s", zFilename);
  nName = file_simplify_name(zName, nName, 0);
  for(i=1; i<nName; i++){
    if( zName[i]=='/' ){
      zName[i] = 0;
#if defined(_WIN32) || defined(__CYGWIN__)
      /*
      ** On Windows, local path looks like: C:/develop/project/file.txt
      ** The if stops us from trying to create a directory of a drive letter
      ** C: in this example.
      */
      if( !(i==2 && zName[1]==':') ){
#endif
        if( file_mkdir(zName, forceFlag) && file_isdir(zName)!=1 ){

          fossil_fatal_recursive("unable to create directory %s", zName);

          return;

        }
#if defined(_WIN32) || defined(__CYGWIN__)
      }
#endif
      zName[i] = '/';
    }
  }
  free(zName);

}

/*
** Removes the directory named in the argument, if it exists.  The directory
** must be empty and cannot be the current directory or the root directory.
**
** Returns zero upon success.







>
>
>

|
|

















>
|
>
|
>








>







528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
  }
  return 0;
}

/*
** Create the tree of directories in which zFilename belongs, if that sequence
** of directories does not already exist.
**
** On success, return zero.  On error, return errorReturn if positive, otherwise
** print an error message and abort.
*/
int file_mkfolder(const char *zFilename, int forceFlag, int errorReturn){
  int i, nName, rc = 0;
  char *zName;

  nName = strlen(zFilename);
  zName = mprintf("%s", zFilename);
  nName = file_simplify_name(zName, nName, 0);
  for(i=1; i<nName; i++){
    if( zName[i]=='/' ){
      zName[i] = 0;
#if defined(_WIN32) || defined(__CYGWIN__)
      /*
      ** On Windows, local path looks like: C:/develop/project/file.txt
      ** The if stops us from trying to create a directory of a drive letter
      ** C: in this example.
      */
      if( !(i==2 && zName[1]==':') ){
#endif
        if( file_mkdir(zName, forceFlag) && file_isdir(zName)!=1 ){
          if (errorReturn <= 0) {
            fossil_fatal_recursive("unable to create directory %s", zName);
          }
          rc = errorReturn;
          break;
        }
#if defined(_WIN32) || defined(__CYGWIN__)
      }
#endif
      zName[i] = '/';
    }
  }
  free(zName);
  return rc;
}

/*
** Removes the directory named in the argument, if it exists.  The directory
** must be empty and cannot be the current directory or the root directory.
**
** Returns zero upon success.
Changes to src/update.c.
584
585
586
587
588
589
590
591
592
593
594
595
596

597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622


623
624
625
626
627
628
629
630
631
632
633
634
635
636
637

638
639


640
641
642
643
644
645
646
    if( !internalUpdate ) undo_finish();
    if( setmtimeFlag ) vfile_check_signature(tid, CKSIG_SETMTIME);
    db_end_transaction(0);
  }
}

/*
** Make sure empty directories are created
*/
void ensure_empty_dirs_created(void){
  /* Make empty directories? */
  char *zEmptyDirs = db_get("empty-dirs", 0);
  if( zEmptyDirs!=0 ){

    char *bc;
    Blob dirName;
    Blob dirsList;

    blob_zero(&dirsList);
    blob_init(&dirsList, zEmptyDirs, strlen(zEmptyDirs));
    /* Replace commas by spaces */
    bc = blob_str(&dirsList);
    while( (*bc)!='\0' ){
      if( (*bc)==',' ) { *bc = ' '; }
      ++bc;
    }
    /* Make directories */
    blob_zero(&dirName);
    while( blob_token(&dirsList, &dirName) ){
      const char *zDir = blob_str(&dirName);
      /* Make full pathname of the directory */
      Blob path;
      const char *zPath;

      blob_zero(&path);
      blob_appendf(&path, "%s/%s", g.zLocalRoot, zDir);
      zPath = blob_str(&path);
      /* Handle various cases of existence of the directory */
      switch( file_wd_isdir(zPath) ){
        case 0: { /* doesn't exist */


          if( file_mkdir(zPath, 0)!=0 ) {
            fossil_warning("couldn't create directory %s as "
                           "required by empty-dirs setting", zDir);
          }
          break;
        }
        case 1: { /* exists, and is a directory */
          /* do nothing - required directory exists already */
          break;
        }
        case 2: { /* exists, but isn't a directory */
          fossil_warning("file %s found, but a directory is required "
                         "by empty-dirs setting", zDir);
        }
      }

      blob_reset(&path);
    }


  }
}


/*
** Get the contents of a file within the check-in "revision".  If
** revision==NULL then get the file content for the current checkout.







|


<


>




|
|
<
<
<
|
<

<
|


<
<
|
<
<
<
<
<


>
>
|














>
|

>
>







584
585
586
587
588
589
590
591
592
593

594
595
596
597
598
599
600
601
602



603

604

605
606
607


608





609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
    if( !internalUpdate ) undo_finish();
    if( setmtimeFlag ) vfile_check_signature(tid, CKSIG_SETMTIME);
    db_end_transaction(0);
  }
}

/*
** Create empty directories specified by the empty-dirs setting.
*/
void ensure_empty_dirs_created(void){

  char *zEmptyDirs = db_get("empty-dirs", 0);
  if( zEmptyDirs!=0 ){
    int i;
    char *bc;
    Blob dirName;
    Blob dirsList;

    zEmptyDirs = fossil_strdup(zEmptyDirs);
    for(i=0; zEmptyDirs[i]; i++){



      if( zEmptyDirs[i]==',' ) zEmptyDirs[i] = ' ';    

    }

    blob_init(&dirsList, zEmptyDirs, -1);
    while( blob_token(&dirsList, &dirName) ){
      const char *zDir = blob_str(&dirName);


      const char *zPath = mprintf("%s/%s", g.zLocalRoot, zDir);





      switch( file_wd_isdir(zPath) ){
        case 0: { /* doesn't exist */
          fossil_free(zPath);
          zPath = mprintf("%s/%s/x", g.zLocalRoot, zDir);
          if( file_mkfolder(zPath, 0, 1)!=0 ) {
            fossil_warning("couldn't create directory %s as "
                           "required by empty-dirs setting", zDir);
          }
          break;
        }
        case 1: { /* exists, and is a directory */
          /* do nothing - required directory exists already */
          break;
        }
        case 2: { /* exists, but isn't a directory */
          fossil_warning("file %s found, but a directory is required "
                         "by empty-dirs setting", zDir);
        }
      }
      fossil_free(zPath);
      blob_reset(&dirName);
    }
    blob_reset(&dirsList);
    fossil_free(zEmptyDirs);
  }
}


/*
** Get the contents of a file within the check-in "revision".  If
** revision==NULL then get the file content for the current checkout.
Changes to www/changes.wiki.
38
39
40
41
42
43
44


45
46
47
48
49
50
51
  *  Added fork warning to be issued if sync produced a fork
  *  Update the [/help?cmd=/info|info] page to report when a file becomes a
     symlink.  Additionally show the UUID for files whose types have changed
     without changing contents or symlink target.
  *  Have [/help?cmd=changes|fossil changes] and
     [/help?cmd=status|fossil status] report when executable or symlink status
     changes on otherwise unmodified files.



<h2>Changes for Version 1.32 (2015-03-14)</h2>
  *  When creating a new repository using [/help?cmd=init|fossil init], ensure
     that the new repository is fully compatible with historical versions of
     Fossil by having a valid manifest as RID 1.
  *  Anti-aliased rendering of arrowheads on timeline graphs.
  *  Added vi/less-style key bindings to the --tk diff GUI.







>
>







38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
  *  Added fork warning to be issued if sync produced a fork
  *  Update the [/help?cmd=/info|info] page to report when a file becomes a
     symlink.  Additionally show the UUID for files whose types have changed
     without changing contents or symlink target.
  *  Have [/help?cmd=changes|fossil changes] and
     [/help?cmd=status|fossil status] report when executable or symlink status
     changes on otherwise unmodified files.
  *  Create parent directories of [/help?cmd=settings|empty-dirs] if they don't
     already exist.

<h2>Changes for Version 1.32 (2015-03-14)</h2>
  *  When creating a new repository using [/help?cmd=init|fossil init], ensure
     that the new repository is fully compatible with historical versions of
     Fossil by having a valid manifest as RID 1.
  *  Anti-aliased rendering of arrowheads on timeline graphs.
  *  Added vi/less-style key bindings to the --tk diff GUI.