Fossil SCM

For the "fossil update" and "fossil checkout" commands, if a managed file is removed because it is no longer part of the target check-in and the directory containing the file is empty after the file is removed and the directory is not the current working directory and is not on the empty-dirs list, then also remove the directory.

drh 2019-02-27 14:23 trunk merge
Commit f132f86bbe1d1c84f7dc9cd890bca1a939d450e4e20313b005a8c916823e907a
+42 -4
--- src/checkout.c
+++ src/checkout.c
@@ -39,15 +39,53 @@
3939
}
4040
4141
/*
4242
** Undo the current check-out. Unlink all files from the disk.
4343
** Clear the VFILE table.
44
+**
45
+** Also delete any directory that becomes empty as a result of deleting
46
+** files due to this operation, as long as that directory is not the
47
+** current working directory and is not on the empty-dirs list.
4448
*/
4549
void uncheckout(int vid){
46
- if( vid>0 ){
47
- vfile_unlink(vid);
48
- }
50
+ char *zPwd;
51
+ if( vid<=0 ) return;
52
+ sqlite3_create_function(g.db, "dirname",1,SQLITE_UTF8,0,
53
+ file_dirname_sql_function, 0, 0);
54
+ sqlite3_create_function(g.db, "unlink",1,SQLITE_UTF8,0,
55
+ file_delete_sql_function, 0, 0);
56
+ sqlite3_create_function(g.db, "rmdir", 1, SQLITE_UTF8, 0,
57
+ file_rmdir_sql_function, 0, 0);
58
+ db_multi_exec(
59
+ "CREATE TEMP TABLE dir_to_delete(name TEXT %s PRIMARY KEY)WITHOUT ROWID",
60
+ filename_collation()
61
+ );
62
+ db_multi_exec(
63
+ "INSERT OR IGNORE INTO dir_to_delete(name)"
64
+ " SELECT dirname(pathname) FROM vfile"
65
+ " WHERE vid=%d AND mrid>0",
66
+ vid
67
+ );
68
+ do{
69
+ db_multi_exec(
70
+ "INSERT OR IGNORE INTO dir_to_delete(name)"
71
+ " SELECT dirname(name) FROM dir_to_delete;"
72
+ );
73
+ }while( db_changes() );
74
+ db_multi_exec(
75
+ "SELECT unlink(%Q||pathname) FROM vfile"
76
+ " WHERE vid=%d AND mrid>0;",
77
+ g.zLocalRoot, vid
78
+ );
79
+ ensure_empty_dirs_created(1);
80
+ zPwd = file_getcwd(0,0);
81
+ db_multi_exec(
82
+ "SELECT rmdir(%Q||name) FROM dir_to_delete"
83
+ " WHERE (%Q||name)<>%Q ORDER BY name DESC",
84
+ g.zLocalRoot, g.zLocalRoot, zPwd
85
+ );
86
+ fossil_free(zPwd);
4987
db_multi_exec("DELETE FROM vfile WHERE vid=%d", vid);
5088
}
5189
5290
5391
/*
@@ -303,11 +341,11 @@
303341
if( !keepFlag ){
304342
vfile_to_disk(vid, 0, !g.fQuiet, promptFlag);
305343
}
306344
checkout_set_all_exe(vid);
307345
manifest_to_disk(vid);
308
- ensure_empty_dirs_created();
346
+ ensure_empty_dirs_created(0);
309347
db_set_checkout(vid);
310348
undo_reset();
311349
db_multi_exec("DELETE FROM vmerge");
312350
if( !keepFlag && db_get_boolean("repo-cksum",1) ){
313351
vfile_aggregate_checksum_manifest(vid, &cksum1, &cksum1b);
314352
--- src/checkout.c
+++ src/checkout.c
@@ -39,15 +39,53 @@
39 }
40
41 /*
42 ** Undo the current check-out. Unlink all files from the disk.
43 ** Clear the VFILE table.
 
 
 
 
44 */
45 void uncheckout(int vid){
46 if( vid>0 ){
47 vfile_unlink(vid);
48 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49 db_multi_exec("DELETE FROM vfile WHERE vid=%d", vid);
50 }
51
52
53 /*
@@ -303,11 +341,11 @@
303 if( !keepFlag ){
304 vfile_to_disk(vid, 0, !g.fQuiet, promptFlag);
305 }
306 checkout_set_all_exe(vid);
307 manifest_to_disk(vid);
308 ensure_empty_dirs_created();
309 db_set_checkout(vid);
310 undo_reset();
311 db_multi_exec("DELETE FROM vmerge");
312 if( !keepFlag && db_get_boolean("repo-cksum",1) ){
313 vfile_aggregate_checksum_manifest(vid, &cksum1, &cksum1b);
314
--- src/checkout.c
+++ src/checkout.c
@@ -39,15 +39,53 @@
39 }
40
41 /*
42 ** Undo the current check-out. Unlink all files from the disk.
43 ** Clear the VFILE table.
44 **
45 ** Also delete any directory that becomes empty as a result of deleting
46 ** files due to this operation, as long as that directory is not the
47 ** current working directory and is not on the empty-dirs list.
48 */
49 void uncheckout(int vid){
50 char *zPwd;
51 if( vid<=0 ) return;
52 sqlite3_create_function(g.db, "dirname",1,SQLITE_UTF8,0,
53 file_dirname_sql_function, 0, 0);
54 sqlite3_create_function(g.db, "unlink",1,SQLITE_UTF8,0,
55 file_delete_sql_function, 0, 0);
56 sqlite3_create_function(g.db, "rmdir", 1, SQLITE_UTF8, 0,
57 file_rmdir_sql_function, 0, 0);
58 db_multi_exec(
59 "CREATE TEMP TABLE dir_to_delete(name TEXT %s PRIMARY KEY)WITHOUT ROWID",
60 filename_collation()
61 );
62 db_multi_exec(
63 "INSERT OR IGNORE INTO dir_to_delete(name)"
64 " SELECT dirname(pathname) FROM vfile"
65 " WHERE vid=%d AND mrid>0",
66 vid
67 );
68 do{
69 db_multi_exec(
70 "INSERT OR IGNORE INTO dir_to_delete(name)"
71 " SELECT dirname(name) FROM dir_to_delete;"
72 );
73 }while( db_changes() );
74 db_multi_exec(
75 "SELECT unlink(%Q||pathname) FROM vfile"
76 " WHERE vid=%d AND mrid>0;",
77 g.zLocalRoot, vid
78 );
79 ensure_empty_dirs_created(1);
80 zPwd = file_getcwd(0,0);
81 db_multi_exec(
82 "SELECT rmdir(%Q||name) FROM dir_to_delete"
83 " WHERE (%Q||name)<>%Q ORDER BY name DESC",
84 g.zLocalRoot, g.zLocalRoot, zPwd
85 );
86 fossil_free(zPwd);
87 db_multi_exec("DELETE FROM vfile WHERE vid=%d", vid);
88 }
89
90
91 /*
@@ -303,11 +341,11 @@
341 if( !keepFlag ){
342 vfile_to_disk(vid, 0, !g.fQuiet, promptFlag);
343 }
344 checkout_set_all_exe(vid);
345 manifest_to_disk(vid);
346 ensure_empty_dirs_created(0);
347 db_set_checkout(vid);
348 undo_reset();
349 db_multi_exec("DELETE FROM vmerge");
350 if( !keepFlag && db_get_boolean("repo-cksum",1) ){
351 vfile_aggregate_checksum_manifest(vid, &cksum1, &cksum1b);
352
+69 -1
--- src/file.c
+++ src/file.c
@@ -437,10 +437,29 @@
437437
return mprintf("%.*s", (int)(zTail-z-1), z);
438438
}else{
439439
return 0;
440440
}
441441
}
442
+
443
+/* SQL Function: file_dirname(NAME)
444
+**
445
+** Return the directory for NAME
446
+*/
447
+void file_dirname_sql_function(
448
+ sqlite3_context *context,
449
+ int argc,
450
+ sqlite3_value **argv
451
+){
452
+ const char *zName = (const char*)sqlite3_value_text(argv[0]);
453
+ char *zDir;
454
+ if( zName==0 ) return;
455
+ zDir = file_dirname(zName);
456
+ if( zDir ){
457
+ sqlite3_result_text(context,zDir,-1,fossil_free);
458
+ }
459
+}
460
+
442461
443462
/*
444463
** Rename a file or directory.
445464
** Returns zero upon success.
446465
*/
@@ -594,10 +613,30 @@
594613
rc = unlink(zFilename);
595614
#endif
596615
fossil_path_free(z);
597616
return rc;
598617
}
618
+
619
+/* SQL Function: file_delete(NAME)
620
+**
621
+** Remove file NAME. Return zero on success and non-zero if anything goes
622
+** wrong.
623
+*/
624
+void file_delete_sql_function(
625
+ sqlite3_context *context,
626
+ int argc,
627
+ sqlite3_value **argv
628
+){
629
+ const char *zName = (const char*)sqlite3_value_text(argv[0]);
630
+ int rc;
631
+ if( zName==0 ){
632
+ rc = 1;
633
+ }else{
634
+ rc = file_delete(zName);
635
+ }
636
+ sqlite3_result_int(context, rc);
637
+}
599638
600639
/*
601640
** Create a directory called zName, if it does not already exist.
602641
** If forceFlag is 1, delete any prior non-directory object
603642
** with the same name.
@@ -684,10 +723,30 @@
684723
fossil_path_free(zMbcs);
685724
return rc;
686725
}
687726
return 0;
688727
}
728
+
729
+/* SQL Function: rmdir(NAME)
730
+**
731
+** Try to remove the directory NAME. Return zero on success and non-zero
732
+** for failure.
733
+*/
734
+void file_rmdir_sql_function(
735
+ sqlite3_context *context,
736
+ int argc,
737
+ sqlite3_value **argv
738
+){
739
+ const char *zName = (const char*)sqlite3_value_text(argv[0]);
740
+ int rc;
741
+ if( zName==0 ){
742
+ rc = 1;
743
+ }else{
744
+ rc = file_rmdir(zName);
745
+ }
746
+ sqlite3_result_int(context, rc);
747
+}
689748
690749
/*
691750
** Return true if the filename given is a valid filename for
692751
** a file in a repository. Valid filenames follow all of the
693752
** following rules:
@@ -890,12 +949,20 @@
890949
** Get the current working directory.
891950
**
892951
** On windows, the name is converted from unicode to UTF8 and all '\\'
893952
** characters are converted to '/'. No conversions are needed on
894953
** unix.
954
+**
955
+** Store the value of the CWD in zBuf which is nBuf bytes in size.
956
+** or if zBuf==0, allocate space to hold the result using fossil_malloc().
895957
*/
896
-void file_getcwd(char *zBuf, int nBuf){
958
+char *file_getcwd(char *zBuf, int nBuf){
959
+ char zTemp[2000];
960
+ if( zBuf==0 ){
961
+ zBuf = zTemp;
962
+ nBuf = sizeof(zTemp);
963
+ }
897964
#ifdef _WIN32
898965
win32_getcwd(zBuf, nBuf);
899966
#else
900967
if( getcwd(zBuf, nBuf-1)==0 ){
901968
if( errno==ERANGE ){
@@ -904,10 +971,11 @@
904971
fossil_panic("cannot find current working directory; %s",
905972
strerror(errno));
906973
}
907974
}
908975
#endif
976
+ return zBuf==zTemp ? fossil_strdup(zBuf) : zBuf;
909977
}
910978
911979
/*
912980
** Return true if zPath is an absolute pathname. Return false
913981
** if it is relative.
914982
--- src/file.c
+++ src/file.c
@@ -437,10 +437,29 @@
437 return mprintf("%.*s", (int)(zTail-z-1), z);
438 }else{
439 return 0;
440 }
441 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
442
443 /*
444 ** Rename a file or directory.
445 ** Returns zero upon success.
446 */
@@ -594,10 +613,30 @@
594 rc = unlink(zFilename);
595 #endif
596 fossil_path_free(z);
597 return rc;
598 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
599
600 /*
601 ** Create a directory called zName, if it does not already exist.
602 ** If forceFlag is 1, delete any prior non-directory object
603 ** with the same name.
@@ -684,10 +723,30 @@
684 fossil_path_free(zMbcs);
685 return rc;
686 }
687 return 0;
688 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
689
690 /*
691 ** Return true if the filename given is a valid filename for
692 ** a file in a repository. Valid filenames follow all of the
693 ** following rules:
@@ -890,12 +949,20 @@
890 ** Get the current working directory.
891 **
892 ** On windows, the name is converted from unicode to UTF8 and all '\\'
893 ** characters are converted to '/'. No conversions are needed on
894 ** unix.
 
 
 
895 */
896 void file_getcwd(char *zBuf, int nBuf){
 
 
 
 
 
897 #ifdef _WIN32
898 win32_getcwd(zBuf, nBuf);
899 #else
900 if( getcwd(zBuf, nBuf-1)==0 ){
901 if( errno==ERANGE ){
@@ -904,10 +971,11 @@
904 fossil_panic("cannot find current working directory; %s",
905 strerror(errno));
906 }
907 }
908 #endif
 
909 }
910
911 /*
912 ** Return true if zPath is an absolute pathname. Return false
913 ** if it is relative.
914
--- src/file.c
+++ src/file.c
@@ -437,10 +437,29 @@
437 return mprintf("%.*s", (int)(zTail-z-1), z);
438 }else{
439 return 0;
440 }
441 }
442
443 /* SQL Function: file_dirname(NAME)
444 **
445 ** Return the directory for NAME
446 */
447 void file_dirname_sql_function(
448 sqlite3_context *context,
449 int argc,
450 sqlite3_value **argv
451 ){
452 const char *zName = (const char*)sqlite3_value_text(argv[0]);
453 char *zDir;
454 if( zName==0 ) return;
455 zDir = file_dirname(zName);
456 if( zDir ){
457 sqlite3_result_text(context,zDir,-1,fossil_free);
458 }
459 }
460
461
462 /*
463 ** Rename a file or directory.
464 ** Returns zero upon success.
465 */
@@ -594,10 +613,30 @@
613 rc = unlink(zFilename);
614 #endif
615 fossil_path_free(z);
616 return rc;
617 }
618
619 /* SQL Function: file_delete(NAME)
620 **
621 ** Remove file NAME. Return zero on success and non-zero if anything goes
622 ** wrong.
623 */
624 void file_delete_sql_function(
625 sqlite3_context *context,
626 int argc,
627 sqlite3_value **argv
628 ){
629 const char *zName = (const char*)sqlite3_value_text(argv[0]);
630 int rc;
631 if( zName==0 ){
632 rc = 1;
633 }else{
634 rc = file_delete(zName);
635 }
636 sqlite3_result_int(context, rc);
637 }
638
639 /*
640 ** Create a directory called zName, if it does not already exist.
641 ** If forceFlag is 1, delete any prior non-directory object
642 ** with the same name.
@@ -684,10 +723,30 @@
723 fossil_path_free(zMbcs);
724 return rc;
725 }
726 return 0;
727 }
728
729 /* SQL Function: rmdir(NAME)
730 **
731 ** Try to remove the directory NAME. Return zero on success and non-zero
732 ** for failure.
733 */
734 void file_rmdir_sql_function(
735 sqlite3_context *context,
736 int argc,
737 sqlite3_value **argv
738 ){
739 const char *zName = (const char*)sqlite3_value_text(argv[0]);
740 int rc;
741 if( zName==0 ){
742 rc = 1;
743 }else{
744 rc = file_rmdir(zName);
745 }
746 sqlite3_result_int(context, rc);
747 }
748
749 /*
750 ** Return true if the filename given is a valid filename for
751 ** a file in a repository. Valid filenames follow all of the
752 ** following rules:
@@ -890,12 +949,20 @@
949 ** Get the current working directory.
950 **
951 ** On windows, the name is converted from unicode to UTF8 and all '\\'
952 ** characters are converted to '/'. No conversions are needed on
953 ** unix.
954 **
955 ** Store the value of the CWD in zBuf which is nBuf bytes in size.
956 ** or if zBuf==0, allocate space to hold the result using fossil_malloc().
957 */
958 char *file_getcwd(char *zBuf, int nBuf){
959 char zTemp[2000];
960 if( zBuf==0 ){
961 zBuf = zTemp;
962 nBuf = sizeof(zTemp);
963 }
964 #ifdef _WIN32
965 win32_getcwd(zBuf, nBuf);
966 #else
967 if( getcwd(zBuf, nBuf-1)==0 ){
968 if( errno==ERANGE ){
@@ -904,10 +971,11 @@
971 fossil_panic("cannot find current working directory; %s",
972 strerror(errno));
973 }
974 }
975 #endif
976 return zBuf==zTemp ? fossil_strdup(zBuf) : zBuf;
977 }
978
979 /*
980 ** Return true if zPath is an absolute pathname. Return false
981 ** if it is relative.
982
+36 -5
--- src/update.c
+++ src/update.c
@@ -160,11 +160,11 @@
160160
}
161161
}
162162
163163
/* Create any empty directories now, as well as after the update,
164164
** so changes in settings are reflected now */
165
- if( !dryRunFlag ) ensure_empty_dirs_created();
165
+ if( !dryRunFlag ) ensure_empty_dirs_created(0);
166166
167167
if( internalUpdate ){
168168
tid = internalUpdate;
169169
}else if( g.argc>=3 ){
170170
if( fossil_strcmp(g.argv[2], "current")==0 ){
@@ -227,10 +227,14 @@
227227
if( tid==0 ){
228228
return;
229229
}
230230
231231
db_begin_transaction();
232
+ db_multi_exec(
233
+ "CREATE TEMP TABLE dir_to_delete(name TEXT %s PRIMARY KEY)WITHOUT ROWID",
234
+ filename_collation()
235
+ );
232236
vfile_check_signature(vid, CKSIG_ENOTFILE);
233237
if( !dryRunFlag && !internalUpdate ) undo_begin();
234238
if( load_vfile_from_rid(tid) && !forceMissingFlag ){
235239
fossil_fatal("missing content, unable to update");
236240
};
@@ -455,11 +459,23 @@
455459
zName);
456460
nConflict++;
457461
}else{
458462
fossil_print("REMOVE %s\n", zName);
459463
if( !dryRunFlag && !internalUpdate ) undo_save(zName);
460
- if( !dryRunFlag ) file_delete(zFullPath);
464
+ if( !dryRunFlag ){
465
+ char *zDir;
466
+ file_delete(zFullPath);
467
+ zDir = file_dirname(zName);
468
+ while( zDir!=0 ){
469
+ char *zNext;
470
+ db_multi_exec("INSERT OR IGNORE INTO dir_to_delete(name)"
471
+ "VALUES(%Q)", zDir);
472
+ zNext = db_changes() ? file_dirname(zDir) : 0;
473
+ fossil_free(zDir);
474
+ zDir = zNext;
475
+ }
476
+ }
461477
}
462478
}else if( idt>0 && idv>0 && ridt!=ridv && chnged ){
463479
/* Merge the changes in the current tree into the target version */
464480
Blob r, t, v;
465481
int rc;
@@ -566,11 +582,21 @@
566582
** Clean up the mid and pid VFILE entries. Then commit the changes.
567583
*/
568584
if( dryRunFlag ){
569585
db_end_transaction(1); /* With --dry-run, rollback changes */
570586
}else{
571
- ensure_empty_dirs_created();
587
+ char *zPwd;
588
+ ensure_empty_dirs_created(1);
589
+ sqlite3_create_function(g.db, "rmdir", 1, SQLITE_UTF8, 0,
590
+ file_rmdir_sql_function, 0, 0);
591
+ zPwd = file_getcwd(0,0);
592
+ db_multi_exec(
593
+ "SELECT rmdir(%Q||name) FROM dir_to_delete"
594
+ " WHERE (%Q||name)<>%Q ORDER BY name DESC",
595
+ g.zLocalRoot, g.zLocalRoot, zPwd
596
+ );
597
+ fossil_free(zPwd);
572598
if( g.argc<=3 ){
573599
/* All files updated. Shift the current checkout to the target. */
574600
db_multi_exec("DELETE FROM vfile WHERE vid!=%d", tid);
575601
checkout_set_all_exe(tid);
576602
manifest_to_disk(tid);
@@ -587,11 +613,11 @@
587613
}
588614
589615
/*
590616
** Create empty directories specified by the empty-dirs setting.
591617
*/
592
-void ensure_empty_dirs_created(void){
618
+void ensure_empty_dirs_created(int clearDirTable){
593619
char *zEmptyDirs = db_get("empty-dirs", 0);
594620
if( zEmptyDirs!=0 ){
595621
int i;
596622
Blob dirName;
597623
Blob dirsList;
@@ -613,11 +639,16 @@
613639
"required by empty-dirs setting", zDir);
614640
}
615641
break;
616642
}
617643
case 1: { /* exists, and is a directory */
618
- /* do nothing - required directory exists already */
644
+ /* make sure this directory is not on the delete list */
645
+ if( clearDirTable ){
646
+ db_multi_exec(
647
+ "DELETE FROM dir_to_delete WHERE name=%Q", zDir
648
+ );
649
+ }
619650
break;
620651
}
621652
case 2: { /* exists, but isn't a directory */
622653
fossil_warning("file %s found, but a directory is required "
623654
"by empty-dirs setting", zDir);
624655
--- src/update.c
+++ src/update.c
@@ -160,11 +160,11 @@
160 }
161 }
162
163 /* Create any empty directories now, as well as after the update,
164 ** so changes in settings are reflected now */
165 if( !dryRunFlag ) ensure_empty_dirs_created();
166
167 if( internalUpdate ){
168 tid = internalUpdate;
169 }else if( g.argc>=3 ){
170 if( fossil_strcmp(g.argv[2], "current")==0 ){
@@ -227,10 +227,14 @@
227 if( tid==0 ){
228 return;
229 }
230
231 db_begin_transaction();
 
 
 
 
232 vfile_check_signature(vid, CKSIG_ENOTFILE);
233 if( !dryRunFlag && !internalUpdate ) undo_begin();
234 if( load_vfile_from_rid(tid) && !forceMissingFlag ){
235 fossil_fatal("missing content, unable to update");
236 };
@@ -455,11 +459,23 @@
455 zName);
456 nConflict++;
457 }else{
458 fossil_print("REMOVE %s\n", zName);
459 if( !dryRunFlag && !internalUpdate ) undo_save(zName);
460 if( !dryRunFlag ) file_delete(zFullPath);
 
 
 
 
 
 
 
 
 
 
 
 
461 }
462 }else if( idt>0 && idv>0 && ridt!=ridv && chnged ){
463 /* Merge the changes in the current tree into the target version */
464 Blob r, t, v;
465 int rc;
@@ -566,11 +582,21 @@
566 ** Clean up the mid and pid VFILE entries. Then commit the changes.
567 */
568 if( dryRunFlag ){
569 db_end_transaction(1); /* With --dry-run, rollback changes */
570 }else{
571 ensure_empty_dirs_created();
 
 
 
 
 
 
 
 
 
 
572 if( g.argc<=3 ){
573 /* All files updated. Shift the current checkout to the target. */
574 db_multi_exec("DELETE FROM vfile WHERE vid!=%d", tid);
575 checkout_set_all_exe(tid);
576 manifest_to_disk(tid);
@@ -587,11 +613,11 @@
587 }
588
589 /*
590 ** Create empty directories specified by the empty-dirs setting.
591 */
592 void ensure_empty_dirs_created(void){
593 char *zEmptyDirs = db_get("empty-dirs", 0);
594 if( zEmptyDirs!=0 ){
595 int i;
596 Blob dirName;
597 Blob dirsList;
@@ -613,11 +639,16 @@
613 "required by empty-dirs setting", zDir);
614 }
615 break;
616 }
617 case 1: { /* exists, and is a directory */
618 /* do nothing - required directory exists already */
 
 
 
 
 
619 break;
620 }
621 case 2: { /* exists, but isn't a directory */
622 fossil_warning("file %s found, but a directory is required "
623 "by empty-dirs setting", zDir);
624
--- src/update.c
+++ src/update.c
@@ -160,11 +160,11 @@
160 }
161 }
162
163 /* Create any empty directories now, as well as after the update,
164 ** so changes in settings are reflected now */
165 if( !dryRunFlag ) ensure_empty_dirs_created(0);
166
167 if( internalUpdate ){
168 tid = internalUpdate;
169 }else if( g.argc>=3 ){
170 if( fossil_strcmp(g.argv[2], "current")==0 ){
@@ -227,10 +227,14 @@
227 if( tid==0 ){
228 return;
229 }
230
231 db_begin_transaction();
232 db_multi_exec(
233 "CREATE TEMP TABLE dir_to_delete(name TEXT %s PRIMARY KEY)WITHOUT ROWID",
234 filename_collation()
235 );
236 vfile_check_signature(vid, CKSIG_ENOTFILE);
237 if( !dryRunFlag && !internalUpdate ) undo_begin();
238 if( load_vfile_from_rid(tid) && !forceMissingFlag ){
239 fossil_fatal("missing content, unable to update");
240 };
@@ -455,11 +459,23 @@
459 zName);
460 nConflict++;
461 }else{
462 fossil_print("REMOVE %s\n", zName);
463 if( !dryRunFlag && !internalUpdate ) undo_save(zName);
464 if( !dryRunFlag ){
465 char *zDir;
466 file_delete(zFullPath);
467 zDir = file_dirname(zName);
468 while( zDir!=0 ){
469 char *zNext;
470 db_multi_exec("INSERT OR IGNORE INTO dir_to_delete(name)"
471 "VALUES(%Q)", zDir);
472 zNext = db_changes() ? file_dirname(zDir) : 0;
473 fossil_free(zDir);
474 zDir = zNext;
475 }
476 }
477 }
478 }else if( idt>0 && idv>0 && ridt!=ridv && chnged ){
479 /* Merge the changes in the current tree into the target version */
480 Blob r, t, v;
481 int rc;
@@ -566,11 +582,21 @@
582 ** Clean up the mid and pid VFILE entries. Then commit the changes.
583 */
584 if( dryRunFlag ){
585 db_end_transaction(1); /* With --dry-run, rollback changes */
586 }else{
587 char *zPwd;
588 ensure_empty_dirs_created(1);
589 sqlite3_create_function(g.db, "rmdir", 1, SQLITE_UTF8, 0,
590 file_rmdir_sql_function, 0, 0);
591 zPwd = file_getcwd(0,0);
592 db_multi_exec(
593 "SELECT rmdir(%Q||name) FROM dir_to_delete"
594 " WHERE (%Q||name)<>%Q ORDER BY name DESC",
595 g.zLocalRoot, g.zLocalRoot, zPwd
596 );
597 fossil_free(zPwd);
598 if( g.argc<=3 ){
599 /* All files updated. Shift the current checkout to the target. */
600 db_multi_exec("DELETE FROM vfile WHERE vid!=%d", tid);
601 checkout_set_all_exe(tid);
602 manifest_to_disk(tid);
@@ -587,11 +613,11 @@
613 }
614
615 /*
616 ** Create empty directories specified by the empty-dirs setting.
617 */
618 void ensure_empty_dirs_created(int clearDirTable){
619 char *zEmptyDirs = db_get("empty-dirs", 0);
620 if( zEmptyDirs!=0 ){
621 int i;
622 Blob dirName;
623 Blob dirsList;
@@ -613,11 +639,16 @@
639 "required by empty-dirs setting", zDir);
640 }
641 break;
642 }
643 case 1: { /* exists, and is a directory */
644 /* make sure this directory is not on the delete list */
645 if( clearDirTable ){
646 db_multi_exec(
647 "DELETE FROM dir_to_delete WHERE name=%Q", zDir
648 );
649 }
650 break;
651 }
652 case 2: { /* exists, but isn't a directory */
653 fossil_warning("file %s found, but a directory is required "
654 "by empty-dirs setting", zDir);
655
-18
--- src/vfile.c
+++ src/vfile.c
@@ -359,28 +359,10 @@
359359
file_mtime(zName, RepoFILE), id);
360360
}
361361
db_finalize(&q);
362362
}
363363
364
-
365
-/*
366
-** Delete from the disk every file in VFILE vid.
367
-*/
368
-void vfile_unlink(int vid){
369
- Stmt q;
370
- db_prepare(&q, "SELECT %Q || pathname FROM vfile"
371
- " WHERE vid=%d AND mrid>0", g.zLocalRoot, vid);
372
- while( db_step(&q)==SQLITE_ROW ){
373
- const char *zName;
374
-
375
- zName = db_column_text(&q, 0);
376
- file_delete(zName);
377
- }
378
- db_finalize(&q);
379
- db_multi_exec("UPDATE vfile SET mtime=NULL WHERE vid=%d AND mrid>0", vid);
380
-}
381
-
382364
/*
383365
** Check to see if the directory named in zPath is the top of a checkout.
384366
** In other words, check to see if directory pPath contains a file named
385367
** "_FOSSIL_" or ".fslckout". Return true or false.
386368
*/
387369
--- src/vfile.c
+++ src/vfile.c
@@ -359,28 +359,10 @@
359 file_mtime(zName, RepoFILE), id);
360 }
361 db_finalize(&q);
362 }
363
364
365 /*
366 ** Delete from the disk every file in VFILE vid.
367 */
368 void vfile_unlink(int vid){
369 Stmt q;
370 db_prepare(&q, "SELECT %Q || pathname FROM vfile"
371 " WHERE vid=%d AND mrid>0", g.zLocalRoot, vid);
372 while( db_step(&q)==SQLITE_ROW ){
373 const char *zName;
374
375 zName = db_column_text(&q, 0);
376 file_delete(zName);
377 }
378 db_finalize(&q);
379 db_multi_exec("UPDATE vfile SET mtime=NULL WHERE vid=%d AND mrid>0", vid);
380 }
381
382 /*
383 ** Check to see if the directory named in zPath is the top of a checkout.
384 ** In other words, check to see if directory pPath contains a file named
385 ** "_FOSSIL_" or ".fslckout". Return true or false.
386 */
387
--- src/vfile.c
+++ src/vfile.c
@@ -359,28 +359,10 @@
359 file_mtime(zName, RepoFILE), id);
360 }
361 db_finalize(&q);
362 }
363
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
364 /*
365 ** Check to see if the directory named in zPath is the top of a checkout.
366 ** In other words, check to see if directory pPath contains a file named
367 ** "_FOSSIL_" or ".fslckout". Return true or false.
368 */
369

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button