Fossil SCM

Merge the refactored "add", "del", and "addremove" commands into trunk.

drh 2011-04-15 11:57 trunk merge
Commit 8ae917362c692d816c1f94f5d72e31deb0d77a4e
3 files changed +133 -236 +12 -7 +39 -8
+133 -236
--- src/add.c
+++ src/add.c
@@ -85,132 +85,77 @@
8585
zAll = blob_str(&x);
8686
}
8787
return zAll;
8888
}
8989
90
-
91
-/*
92
-** The pIgnore statement is query of the form:
93
-**
94
-** SELECT (:x GLOB ... OR :x GLOB ... OR ...)
95
-**
96
-** In other words, it is a query that returns true if the :x value
97
-** should be ignored. Evaluate the query and return true to ignore
98
-** and false to not ignore.
99
-**
100
-** If pIgnore is NULL, then do not ignore.
101
-*/
102
-static int shouldBeIgnored(Stmt *pIgnore, const char *zName){
103
- int rc = 0;
104
- if( pIgnore ){
105
- db_bind_text(pIgnore, ":x", zName);
106
- db_step(pIgnore);
107
- rc = db_column_int(pIgnore, 0);
108
- db_reset(pIgnore);
109
- }
110
- return rc;
111
-}
112
-
113
-
11490
/*
11591
** Add a single file named zName to the VFILE table with vid.
11692
**
11793
** Omit any file whose name is pOmit.
11894
*/
119
-static void add_one_file(
120
- const char *zName, /* Name of file to add */
121
- int vid, /* Add to this VFILE */
122
- Blob *pOmit
123
-){
124
- Blob pathname;
125
- const char *zPath;
126
- int i;
127
- const char *zReserved;
128
-
129
- file_tree_name(zName, &pathname, 1);
130
- zPath = blob_str(&pathname);
131
- for(i=0; (zReserved = fossil_reserved_name(i))!=0; i++){
132
- if( fossil_strcmp(zPath, zReserved)==0 ) break;
133
- }
134
- if( zReserved || (pOmit && blob_compare(&pathname, pOmit)==0) ){
135
- fossil_warning("cannot add %s", zPath);
136
- }else{
137
- if( !file_is_simple_pathname(zPath) ){
138
- fossil_fatal("filename contains illegal characters: %s", zPath);
139
- }
140
-#if defined(_WIN32)
141
- if( db_exists("SELECT 1 FROM vfile"
142
- " WHERE pathname=%Q COLLATE nocase", zPath) ){
143
- db_multi_exec("UPDATE vfile SET deleted=0"
144
- " WHERE pathname=%Q COLLATE nocase", zPath);
145
- }
146
-#else
147
- if( db_exists("SELECT 1 FROM vfile WHERE pathname=%Q", zPath) ){
148
- db_multi_exec("UPDATE vfile SET deleted=0 WHERE pathname=%Q", zPath);
149
- }
150
-#endif
151
- else{
152
- db_multi_exec(
153
- "INSERT INTO vfile(vid,deleted,rid,mrid,pathname,isexe)"
154
- "VALUES(%d,0,0,0,%Q,%d)",
155
- vid, zPath,file_isexe(zName));
156
- }
157
- printf("ADDED %s\n", zPath);
158
- }
159
- blob_reset(&pathname);
160
-}
161
-
162
-/*
163
-** All content of the zDir directory to the SFILE table.
164
-*/
165
-void add_directory_content(const char *zDir, Stmt *pIgnore){
166
- DIR *d;
167
- int origSize;
168
- struct dirent *pEntry;
169
- Blob path;
170
-
171
- blob_zero(&path);
172
- blob_append(&path, zDir, -1);
173
- origSize = blob_size(&path);
174
- d = opendir(zDir);
175
- if( d ){
176
- while( (pEntry=readdir(d))!=0 ){
177
- char *zPath;
178
- if( pEntry->d_name[0]=='.' ){
179
- if( !includeDotFiles ) continue;
180
- if( pEntry->d_name[1]==0 ) continue;
181
- if( pEntry->d_name[1]=='.' && pEntry->d_name[2]==0 ) continue;
182
- }
183
- blob_appendf(&path, "/%s", pEntry->d_name);
184
- zPath = blob_str(&path);
185
- if( shouldBeIgnored(pIgnore, zPath) ){
186
- /* Noop */
187
- }else if( file_isdir(zPath)==1 ){
188
- add_directory_content(zPath, pIgnore);
189
- }else if( file_isfile(zPath) ){
190
- db_multi_exec("INSERT INTO sfile VALUES(%Q)", zPath);
191
- }
192
- blob_resize(&path, origSize);
193
- }
194
- closedir(d);
195
- }
196
- blob_reset(&path);
197
-}
198
-
199
-/*
200
-** Add all content of a directory.
201
-*/
202
-void add_directory(const char *zDir, int vid, Blob *pOmit, Stmt *pIgnore){
203
- Stmt q;
204
- add_directory_content(zDir, pIgnore);
205
- db_prepare(&q, "SELECT x FROM sfile ORDER BY x");
206
- while( db_step(&q)==SQLITE_ROW ){
207
- const char *zName = db_column_text(&q, 0);
208
- add_one_file(zName, vid, pOmit);
209
- }
210
- db_finalize(&q);
211
- db_multi_exec("DELETE FROM sfile");
95
+static int add_one_file(
96
+ const char *zPath, /* Tree-name of file to add. */
97
+ int vid /* Add to this VFILE */
98
+){
99
+ if( !file_is_simple_pathname(zPath) ){
100
+ fossil_fatal("filename contains illegal characters: %s", zPath);
101
+ }
102
+#if defined(_WIN32)
103
+ if( db_exists("SELECT 1 FROM vfile"
104
+ " WHERE pathname=%Q COLLATE nocase", zPath) ){
105
+ db_multi_exec("UPDATE vfile SET deleted=0"
106
+ " WHERE pathname=%Q COLLATE nocase", zPath);
107
+ }
108
+#else
109
+ if( db_exists("SELECT 1 FROM vfile WHERE pathname=%Q", zPath) ){
110
+ db_multi_exec("UPDATE vfile SET deleted=0 WHERE pathname=%Q", zPath);
111
+ }
112
+#endif
113
+ else{
114
+ char *zFullname = mprintf("%s%s", g.zLocalRoot, zPath);
115
+ db_multi_exec(
116
+ "INSERT INTO vfile(vid,deleted,rid,mrid,pathname,isexe)"
117
+ "VALUES(%d,0,0,0,%Q,%d)",
118
+ vid, zPath, file_isexe(zFullname));
119
+ fossil_free(zFullname);
120
+ }
121
+ printf("ADDED %s\n", zPath);
122
+ return 1;
123
+}
124
+
125
+/*
126
+** Add all files in the sfile temp table.
127
+**
128
+** Automatically exclude the repository file.
129
+*/
130
+static int add_files_in_sfile(int vid){
131
+ const char *zRepo; /* Name of the repository database file */
132
+ int nAdd = 0; /* Number of files added */
133
+ int i; /* Loop counter */
134
+ const char *zReserved; /* Name of a reserved file */
135
+ Blob repoName; /* Treename of the repository */
136
+ Stmt loop; /* SQL to loop over all files to add */
137
+
138
+ if( !file_tree_name(g.zRepositoryName, &repoName, 0) ){
139
+ blob_zero(&repoName);
140
+ zRepo = "";
141
+ }else{
142
+ zRepo = blob_str(&repoName);
143
+ }
144
+ db_prepare(&loop, "SELECT x FROM sfile ORDER BY x");
145
+ while( db_step(&loop)==SQLITE_ROW ){
146
+ const char *zToAdd = db_column_text(&loop, 0);
147
+ if( fossil_strcmp(zToAdd, zRepo)==0 ) continue;
148
+ for(i=0; (zReserved = fossil_reserved_name(i))!=0; i++){
149
+ if( fossil_strcmp(zToAdd, zReserved)==0 ) break;
150
+ }
151
+ if( zReserved ) continue;
152
+ nAdd += add_one_file(zToAdd, vid);
153
+ }
154
+ db_finalize(&loop);
155
+ blob_reset(&repoName);
156
+ return nAdd;
212157
}
213158
214159
/*
215160
** COMMAND: add
216161
**
@@ -221,26 +166,24 @@
221166
**
222167
** When adding files or directories recursively, filenames that begin
223168
** with "." are excluded by default. To include such files, add
224169
** the "--dotfiles" option to the command-line.
225170
**
226
-** The --ignore option specifies the patterns for files to be excluded,
227
-** like *.o,*.obj,*.exe. If not specified, the "ignore-glob" setting is
228
-** used. See ** documentation on the "settings" command for further
229
-** information.
230
-**
171
+** The --ignore option is a comma-separate list of glob patterns for files
172
+** to be excluded. Example: '*.o,*.obj,*.exe' If the --ignore option
173
+** does not appear on the command line then the "ignore-glob" setting is
174
+** used.
231175
**
232176
** SUMMARY: fossil add ?OPTIONS? FILE1 ?FILE2 ...?
233177
** Options: --dotfiles, --ignore
234178
*/
235179
void add_cmd(void){
236
- int i;
237
- int vid;
238
- const char *zIgnoreFlag;
239
- Blob repo;
240
- Stmt ignoreTest; /* Test to see if a name should be ignored */
241
- Stmt *pIgnore; /* Pointer to ignoreTest or to NULL */
180
+ int i; /* Loop counter */
181
+ int vid; /* Currently checked out version */
182
+ int nRoot; /* Full path characters in g.zLocalRoot */
183
+ const char *zIgnoreFlag; /* The --ignore option or ignore-glob setting */
184
+ Glob *pIgnore; /* Ignore everything matching this glob pattern */
242185
243186
zIgnoreFlag = find_option("ignore",0,1);
244187
includeDotFiles = find_option("dotfiles",0,0)!=0;
245188
db_must_be_within_tree();
246189
if( zIgnoreFlag==0 ){
@@ -249,101 +192,49 @@
249192
vid = db_lget_int("checkout",0);
250193
if( vid==0 ){
251194
fossil_panic("no checkout to add to");
252195
}
253196
db_begin_transaction();
254
- if( !file_tree_name(g.zRepositoryName, &repo, 0) ){
255
- blob_zero(&repo);
256
- }
257197
db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)");
258198
#if defined(_WIN32)
259199
db_multi_exec(
260200
"CREATE INDEX IF NOT EXISTS vfile_pathname "
261201
" ON vfile(pathname COLLATE nocase)"
262202
);
263203
#endif
264
- if( zIgnoreFlag && zIgnoreFlag[0] ){
265
- db_prepare(&ignoreTest, "SELECT %s", glob_expr(":x", zIgnoreFlag));
266
- pIgnore = &ignoreTest;
267
- }else{
268
- pIgnore = 0;
269
- }
204
+ pIgnore = glob_create(zIgnoreFlag);
205
+ nRoot = strlen(g.zLocalRoot);
206
+
207
+ /* Load the names of all files that are to be added into sfile temp table */
270208
for(i=2; i<g.argc; i++){
271209
char *zName;
272210
int isDir;
211
+ Blob fullName;
273212
274
- zName = mprintf("%/", g.argv[i]);
213
+ file_canonical_name(g.argv[i], &fullName);
214
+ zName = blob_str(&fullName);
275215
isDir = file_isdir(zName);
276216
if( isDir==1 ){
277
- int sz = strlen(zName);
278
- if( sz>0 && zName[sz-1]=='/' ){ zName[sz-1] = 0; }
279
- add_directory(zName, vid, &repo, pIgnore);
217
+ vfile_scan(&fullName, nRoot-1, includeDotFiles, pIgnore);
280218
}else if( isDir==0 ){
281219
fossil_fatal("not found: %s", zName);
282220
}else if( access(zName, R_OK) ){
283221
fossil_fatal("cannot open %s", zName);
284222
}else{
285
- add_one_file(zName, vid, &repo);
223
+ char *zTreeName = &zName[nRoot];
224
+ db_multi_exec(
225
+ "INSERT OR IGNORE INTO sfile(x)"
226
+ " SELECT %Q WHERE NOT EXISTS(SELECT 1 FROM vfile WHERE pathname=%Q)",
227
+ zTreeName, zTreeName
228
+ );
286229
}
287230
free(zName);
288231
}
289
- if( pIgnore ) db_finalize(pIgnore);
290
- db_end_transaction(0);
291
-}
292
-
293
-
294
-/*
295
-** Unmangage a single file.
296
-*/
297
-void delete_one_file(const char *zName){
298
- char *zPath;
299
- Blob pathname;
300
- file_tree_name(zName, &pathname, 1);
301
- zPath = blob_str(&pathname);
302
- if( !db_exists(
303
- "SELECT 1 FROM vfile WHERE pathname=%Q AND NOT deleted", zPath) ){
304
- fossil_fatal("not in the repository: %s", zName);
305
- }else{
306
- db_multi_exec("UPDATE vfile SET deleted=1 WHERE pathname=%Q", zPath);
307
- printf("DELETED %s\n", zPath);
308
- }
309
- blob_reset(&pathname);
310
-}
311
-
312
-/*
313
-** Remove all contents of zDir
314
-*/
315
-void del_directory_content(const char *zDir){
316
- DIR *d;
317
- int origSize;
318
- struct dirent *pEntry;
319
- Blob path;
320
-
321
- blob_zero(&path);
322
- blob_append(&path, zDir, -1);
323
- origSize = blob_size(&path);
324
- d = opendir(zDir);
325
- if( d ){
326
- while( (pEntry=readdir(d))!=0 ){
327
- char *zPath;
328
- if( pEntry->d_name[0]=='.'){
329
- if( !includeDotFiles ) continue;
330
- if( pEntry->d_name[1]==0 ) continue;
331
- if( pEntry->d_name[1]=='.' && pEntry->d_name[2]==0 ) continue;
332
- }
333
- blob_appendf(&path, "/%s", pEntry->d_name);
334
- zPath = blob_str(&path);
335
- if( file_isdir(zPath)==1 ){
336
- del_directory_content(zPath);
337
- }else if( file_isfile(zPath) ){
338
- delete_one_file(zPath);
339
- }
340
- blob_resize(&path, origSize);
341
- }
342
- closedir(d);
343
- }
344
- blob_reset(&path);
232
+ glob_free(pIgnore);
233
+
234
+ add_files_in_sfile(vid);
235
+ db_end_transaction(0);
345236
}
346237
347238
/*
348239
** COMMAND: rm
349240
** COMMAND: delete
@@ -361,31 +252,45 @@
361252
** or: fossil delete FILE1 ?FILE2 ...?
362253
*/
363254
void delete_cmd(void){
364255
int i;
365256
int vid;
257
+ Stmt loop;
366258
367259
db_must_be_within_tree();
368260
vid = db_lget_int("checkout", 0);
369261
if( vid==0 ){
370262
fossil_panic("no checkout to remove from");
371263
}
372264
db_begin_transaction();
265
+ db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)");
373266
for(i=2; i<g.argc; i++){
374
- char *zName;
375
-
376
- zName = mprintf("%/", g.argv[i]);
377
- if( file_isdir(zName) == 1 ){
378
- int sz = strlen(zName);
379
- if( sz>0 && zName[sz-1]=='/' ){ zName[sz-1] = 0; }
380
- del_directory_content(zName);
381
- } else {
382
- delete_one_file(zName);
383
- }
384
- free(zName);
385
- }
386
- db_multi_exec("DELETE FROM vfile WHERE deleted AND rid=0");
267
+ Blob treeName;
268
+ char *zTreeName;
269
+
270
+ file_tree_name(g.argv[i], &treeName, 1);
271
+ zTreeName = blob_str(&treeName);
272
+ db_multi_exec(
273
+ "INSERT OR IGNORE INTO sfile"
274
+ " SELECT pathname FROM vfile"
275
+ " WHERE (pathname=%Q"
276
+ " OR (pathname>'%q/' AND pathname<'%q0'))"
277
+ " AND NOT deleted",
278
+ zTreeName, zTreeName, zTreeName
279
+ );
280
+ blob_reset(&treeName);
281
+ }
282
+
283
+ db_prepare(&loop, "SELECT x FROM sfile");
284
+ while( db_step(&loop)==SQLITE_ROW ){
285
+ printf("DELETED %s\n", db_column_text(&loop, 0));
286
+ }
287
+ db_finalize(&loop);
288
+ db_multi_exec(
289
+ "UPDATE vfile SET deleted=1 WHERE pathname IN sfile;"
290
+ "DELETE FROM vfile WHERE rid=0 AND deleted;"
291
+ );
387292
db_end_transaction(0);
388293
}
389294
390295
/*
391296
** COMMAND: addremove
@@ -426,13 +331,13 @@
426331
int allFlag = find_option("dotfiles",0,0)!=0;
427332
int isTest = find_option("test",0,0)!=0;
428333
int n;
429334
Stmt q;
430335
int vid;
431
- Blob repo;
432336
int nAdd = 0;
433337
int nDelete = 0;
338
+ Glob *pIgnore;
434339
435340
db_must_be_within_tree();
436341
if( zIgnoreFlag==0 ){
437342
zIgnoreFlag = db_get("ignore-glob", 0);
438343
}
@@ -439,38 +344,30 @@
439344
vid = db_lget_int("checkout",0);
440345
if( vid==0 ){
441346
fossil_panic("no checkout to add to");
442347
}
443348
db_begin_transaction();
349
+
350
+ /* step 1:
351
+ ** Populate the temp table "sfile" with the names of all unmanged
352
+ ** files currently in the check-out, except for files that match the
353
+ ** --ignore or ignore-glob patterns and dot-files. Then add all of
354
+ ** the files in the sfile temp table to the set of managed files.
355
+ */
444356
db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)");
445357
n = strlen(g.zLocalRoot);
446358
blob_init(&path, g.zLocalRoot, n-1);
447359
/* now we read the complete file structure into a temp table */
448
- vfile_scan(0, &path, blob_size(&path), allFlag);
449
- if( file_tree_name(g.zRepositoryName, &repo, 0) ){
450
- db_multi_exec("DELETE FROM sfile WHERE x=%B", &repo);
451
- }
452
-
453
- /* step 1: search for extra files */
454
- db_prepare(&q,
455
- "SELECT x, %Q || x FROM sfile"
456
- " WHERE x NOT IN (%s)"
457
- " AND NOT %s"
458
- " ORDER BY 1",
459
- g.zLocalRoot,
460
- fossil_all_reserved_names(),
461
- glob_expr("x", zIgnoreFlag)
462
- );
463
- while( db_step(&q)==SQLITE_ROW ){
464
- add_one_file(db_column_text(&q, 1), vid, 0);
465
- nAdd++;
466
- }
467
- db_finalize(&q);
360
+ pIgnore = glob_create(zIgnoreFlag);
361
+ vfile_scan(&path, blob_size(&path), allFlag, pIgnore);
362
+ glob_free(pIgnore);
363
+ nAdd = add_files_in_sfile(vid);
364
+
468365
/* step 2: search for missing files */
469366
db_prepare(&q,
470
- "SELECT pathname,%Q || pathname,deleted FROM vfile"
471
- " WHERE deleted!=1"
367
+ "SELECT pathname, %Q || pathname, deleted FROM vfile"
368
+ " WHERE NOT deleted"
472369
" ORDER BY 1",
473370
g.zLocalRoot
474371
);
475372
while( db_step(&q)==SQLITE_ROW ){
476373
const char * zFile;
@@ -572,13 +469,13 @@
572469
zOrig = blob_str(&orig);
573470
nOrig = blob_size(&orig);
574471
db_prepare(&q,
575472
"SELECT pathname FROM vfile"
576473
" WHERE vid=%d"
577
- " AND (pathname='%s' OR pathname GLOB '%s/*')"
474
+ " AND (pathname='%q' OR (pathname>'%q/' AND pathname<'%q0'))"
578475
" ORDER BY 1",
579
- vid, zOrig, zOrig
476
+ vid, zOrig, zOrig, zOrig
580477
);
581478
while( db_step(&q)==SQLITE_ROW ){
582479
const char *zPath = db_column_text(&q, 0);
583480
int nPath = db_column_bytes(&q, 0);
584481
const char *zTail;
585482
--- src/add.c
+++ src/add.c
@@ -85,132 +85,77 @@
85 zAll = blob_str(&x);
86 }
87 return zAll;
88 }
89
90
91 /*
92 ** The pIgnore statement is query of the form:
93 **
94 ** SELECT (:x GLOB ... OR :x GLOB ... OR ...)
95 **
96 ** In other words, it is a query that returns true if the :x value
97 ** should be ignored. Evaluate the query and return true to ignore
98 ** and false to not ignore.
99 **
100 ** If pIgnore is NULL, then do not ignore.
101 */
102 static int shouldBeIgnored(Stmt *pIgnore, const char *zName){
103 int rc = 0;
104 if( pIgnore ){
105 db_bind_text(pIgnore, ":x", zName);
106 db_step(pIgnore);
107 rc = db_column_int(pIgnore, 0);
108 db_reset(pIgnore);
109 }
110 return rc;
111 }
112
113
114 /*
115 ** Add a single file named zName to the VFILE table with vid.
116 **
117 ** Omit any file whose name is pOmit.
118 */
119 static void add_one_file(
120 const char *zName, /* Name of file to add */
121 int vid, /* Add to this VFILE */
122 Blob *pOmit
123 ){
124 Blob pathname;
125 const char *zPath;
126 int i;
127 const char *zReserved;
128
129 file_tree_name(zName, &pathname, 1);
130 zPath = blob_str(&pathname);
131 for(i=0; (zReserved = fossil_reserved_name(i))!=0; i++){
132 if( fossil_strcmp(zPath, zReserved)==0 ) break;
133 }
134 if( zReserved || (pOmit && blob_compare(&pathname, pOmit)==0) ){
135 fossil_warning("cannot add %s", zPath);
136 }else{
137 if( !file_is_simple_pathname(zPath) ){
138 fossil_fatal("filename contains illegal characters: %s", zPath);
139 }
140 #if defined(_WIN32)
141 if( db_exists("SELECT 1 FROM vfile"
142 " WHERE pathname=%Q COLLATE nocase", zPath) ){
143 db_multi_exec("UPDATE vfile SET deleted=0"
144 " WHERE pathname=%Q COLLATE nocase", zPath);
145 }
146 #else
147 if( db_exists("SELECT 1 FROM vfile WHERE pathname=%Q", zPath) ){
148 db_multi_exec("UPDATE vfile SET deleted=0 WHERE pathname=%Q", zPath);
149 }
150 #endif
151 else{
152 db_multi_exec(
153 "INSERT INTO vfile(vid,deleted,rid,mrid,pathname,isexe)"
154 "VALUES(%d,0,0,0,%Q,%d)",
155 vid, zPath,file_isexe(zName));
156 }
157 printf("ADDED %s\n", zPath);
158 }
159 blob_reset(&pathname);
160 }
161
162 /*
163 ** All content of the zDir directory to the SFILE table.
164 */
165 void add_directory_content(const char *zDir, Stmt *pIgnore){
166 DIR *d;
167 int origSize;
168 struct dirent *pEntry;
169 Blob path;
170
171 blob_zero(&path);
172 blob_append(&path, zDir, -1);
173 origSize = blob_size(&path);
174 d = opendir(zDir);
175 if( d ){
176 while( (pEntry=readdir(d))!=0 ){
177 char *zPath;
178 if( pEntry->d_name[0]=='.' ){
179 if( !includeDotFiles ) continue;
180 if( pEntry->d_name[1]==0 ) continue;
181 if( pEntry->d_name[1]=='.' && pEntry->d_name[2]==0 ) continue;
182 }
183 blob_appendf(&path, "/%s", pEntry->d_name);
184 zPath = blob_str(&path);
185 if( shouldBeIgnored(pIgnore, zPath) ){
186 /* Noop */
187 }else if( file_isdir(zPath)==1 ){
188 add_directory_content(zPath, pIgnore);
189 }else if( file_isfile(zPath) ){
190 db_multi_exec("INSERT INTO sfile VALUES(%Q)", zPath);
191 }
192 blob_resize(&path, origSize);
193 }
194 closedir(d);
195 }
196 blob_reset(&path);
197 }
198
199 /*
200 ** Add all content of a directory.
201 */
202 void add_directory(const char *zDir, int vid, Blob *pOmit, Stmt *pIgnore){
203 Stmt q;
204 add_directory_content(zDir, pIgnore);
205 db_prepare(&q, "SELECT x FROM sfile ORDER BY x");
206 while( db_step(&q)==SQLITE_ROW ){
207 const char *zName = db_column_text(&q, 0);
208 add_one_file(zName, vid, pOmit);
209 }
210 db_finalize(&q);
211 db_multi_exec("DELETE FROM sfile");
212 }
213
214 /*
215 ** COMMAND: add
216 **
@@ -221,26 +166,24 @@
221 **
222 ** When adding files or directories recursively, filenames that begin
223 ** with "." are excluded by default. To include such files, add
224 ** the "--dotfiles" option to the command-line.
225 **
226 ** The --ignore option specifies the patterns for files to be excluded,
227 ** like *.o,*.obj,*.exe. If not specified, the "ignore-glob" setting is
228 ** used. See ** documentation on the "settings" command for further
229 ** information.
230 **
231 **
232 ** SUMMARY: fossil add ?OPTIONS? FILE1 ?FILE2 ...?
233 ** Options: --dotfiles, --ignore
234 */
235 void add_cmd(void){
236 int i;
237 int vid;
238 const char *zIgnoreFlag;
239 Blob repo;
240 Stmt ignoreTest; /* Test to see if a name should be ignored */
241 Stmt *pIgnore; /* Pointer to ignoreTest or to NULL */
242
243 zIgnoreFlag = find_option("ignore",0,1);
244 includeDotFiles = find_option("dotfiles",0,0)!=0;
245 db_must_be_within_tree();
246 if( zIgnoreFlag==0 ){
@@ -249,101 +192,49 @@
249 vid = db_lget_int("checkout",0);
250 if( vid==0 ){
251 fossil_panic("no checkout to add to");
252 }
253 db_begin_transaction();
254 if( !file_tree_name(g.zRepositoryName, &repo, 0) ){
255 blob_zero(&repo);
256 }
257 db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)");
258 #if defined(_WIN32)
259 db_multi_exec(
260 "CREATE INDEX IF NOT EXISTS vfile_pathname "
261 " ON vfile(pathname COLLATE nocase)"
262 );
263 #endif
264 if( zIgnoreFlag && zIgnoreFlag[0] ){
265 db_prepare(&ignoreTest, "SELECT %s", glob_expr(":x", zIgnoreFlag));
266 pIgnore = &ignoreTest;
267 }else{
268 pIgnore = 0;
269 }
270 for(i=2; i<g.argc; i++){
271 char *zName;
272 int isDir;
 
273
274 zName = mprintf("%/", g.argv[i]);
 
275 isDir = file_isdir(zName);
276 if( isDir==1 ){
277 int sz = strlen(zName);
278 if( sz>0 && zName[sz-1]=='/' ){ zName[sz-1] = 0; }
279 add_directory(zName, vid, &repo, pIgnore);
280 }else if( isDir==0 ){
281 fossil_fatal("not found: %s", zName);
282 }else if( access(zName, R_OK) ){
283 fossil_fatal("cannot open %s", zName);
284 }else{
285 add_one_file(zName, vid, &repo);
 
 
 
 
 
286 }
287 free(zName);
288 }
289 if( pIgnore ) db_finalize(pIgnore);
290 db_end_transaction(0);
291 }
292
293
294 /*
295 ** Unmangage a single file.
296 */
297 void delete_one_file(const char *zName){
298 char *zPath;
299 Blob pathname;
300 file_tree_name(zName, &pathname, 1);
301 zPath = blob_str(&pathname);
302 if( !db_exists(
303 "SELECT 1 FROM vfile WHERE pathname=%Q AND NOT deleted", zPath) ){
304 fossil_fatal("not in the repository: %s", zName);
305 }else{
306 db_multi_exec("UPDATE vfile SET deleted=1 WHERE pathname=%Q", zPath);
307 printf("DELETED %s\n", zPath);
308 }
309 blob_reset(&pathname);
310 }
311
312 /*
313 ** Remove all contents of zDir
314 */
315 void del_directory_content(const char *zDir){
316 DIR *d;
317 int origSize;
318 struct dirent *pEntry;
319 Blob path;
320
321 blob_zero(&path);
322 blob_append(&path, zDir, -1);
323 origSize = blob_size(&path);
324 d = opendir(zDir);
325 if( d ){
326 while( (pEntry=readdir(d))!=0 ){
327 char *zPath;
328 if( pEntry->d_name[0]=='.'){
329 if( !includeDotFiles ) continue;
330 if( pEntry->d_name[1]==0 ) continue;
331 if( pEntry->d_name[1]=='.' && pEntry->d_name[2]==0 ) continue;
332 }
333 blob_appendf(&path, "/%s", pEntry->d_name);
334 zPath = blob_str(&path);
335 if( file_isdir(zPath)==1 ){
336 del_directory_content(zPath);
337 }else if( file_isfile(zPath) ){
338 delete_one_file(zPath);
339 }
340 blob_resize(&path, origSize);
341 }
342 closedir(d);
343 }
344 blob_reset(&path);
345 }
346
347 /*
348 ** COMMAND: rm
349 ** COMMAND: delete
@@ -361,31 +252,45 @@
361 ** or: fossil delete FILE1 ?FILE2 ...?
362 */
363 void delete_cmd(void){
364 int i;
365 int vid;
 
366
367 db_must_be_within_tree();
368 vid = db_lget_int("checkout", 0);
369 if( vid==0 ){
370 fossil_panic("no checkout to remove from");
371 }
372 db_begin_transaction();
 
373 for(i=2; i<g.argc; i++){
374 char *zName;
375
376 zName = mprintf("%/", g.argv[i]);
377 if( file_isdir(zName) == 1 ){
378 int sz = strlen(zName);
379 if( sz>0 && zName[sz-1]=='/' ){ zName[sz-1] = 0; }
380 del_directory_content(zName);
381 } else {
382 delete_one_file(zName);
383 }
384 free(zName);
385 }
386 db_multi_exec("DELETE FROM vfile WHERE deleted AND rid=0");
 
 
 
 
 
 
 
 
 
 
 
 
387 db_end_transaction(0);
388 }
389
390 /*
391 ** COMMAND: addremove
@@ -426,13 +331,13 @@
426 int allFlag = find_option("dotfiles",0,0)!=0;
427 int isTest = find_option("test",0,0)!=0;
428 int n;
429 Stmt q;
430 int vid;
431 Blob repo;
432 int nAdd = 0;
433 int nDelete = 0;
 
434
435 db_must_be_within_tree();
436 if( zIgnoreFlag==0 ){
437 zIgnoreFlag = db_get("ignore-glob", 0);
438 }
@@ -439,38 +344,30 @@
439 vid = db_lget_int("checkout",0);
440 if( vid==0 ){
441 fossil_panic("no checkout to add to");
442 }
443 db_begin_transaction();
 
 
 
 
 
 
 
444 db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)");
445 n = strlen(g.zLocalRoot);
446 blob_init(&path, g.zLocalRoot, n-1);
447 /* now we read the complete file structure into a temp table */
448 vfile_scan(0, &path, blob_size(&path), allFlag);
449 if( file_tree_name(g.zRepositoryName, &repo, 0) ){
450 db_multi_exec("DELETE FROM sfile WHERE x=%B", &repo);
451 }
452
453 /* step 1: search for extra files */
454 db_prepare(&q,
455 "SELECT x, %Q || x FROM sfile"
456 " WHERE x NOT IN (%s)"
457 " AND NOT %s"
458 " ORDER BY 1",
459 g.zLocalRoot,
460 fossil_all_reserved_names(),
461 glob_expr("x", zIgnoreFlag)
462 );
463 while( db_step(&q)==SQLITE_ROW ){
464 add_one_file(db_column_text(&q, 1), vid, 0);
465 nAdd++;
466 }
467 db_finalize(&q);
468 /* step 2: search for missing files */
469 db_prepare(&q,
470 "SELECT pathname,%Q || pathname,deleted FROM vfile"
471 " WHERE deleted!=1"
472 " ORDER BY 1",
473 g.zLocalRoot
474 );
475 while( db_step(&q)==SQLITE_ROW ){
476 const char * zFile;
@@ -572,13 +469,13 @@
572 zOrig = blob_str(&orig);
573 nOrig = blob_size(&orig);
574 db_prepare(&q,
575 "SELECT pathname FROM vfile"
576 " WHERE vid=%d"
577 " AND (pathname='%s' OR pathname GLOB '%s/*')"
578 " ORDER BY 1",
579 vid, zOrig, zOrig
580 );
581 while( db_step(&q)==SQLITE_ROW ){
582 const char *zPath = db_column_text(&q, 0);
583 int nPath = db_column_bytes(&q, 0);
584 const char *zTail;
585
--- src/add.c
+++ src/add.c
@@ -85,132 +85,77 @@
85 zAll = blob_str(&x);
86 }
87 return zAll;
88 }
89
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
90 /*
91 ** Add a single file named zName to the VFILE table with vid.
92 **
93 ** Omit any file whose name is pOmit.
94 */
95 static int add_one_file(
96 const char *zPath, /* Tree-name of file to add. */
97 int vid /* Add to this VFILE */
98 ){
99 if( !file_is_simple_pathname(zPath) ){
100 fossil_fatal("filename contains illegal characters: %s", zPath);
101 }
102 #if defined(_WIN32)
103 if( db_exists("SELECT 1 FROM vfile"
104 " WHERE pathname=%Q COLLATE nocase", zPath) ){
105 db_multi_exec("UPDATE vfile SET deleted=0"
106 " WHERE pathname=%Q COLLATE nocase", zPath);
107 }
108 #else
109 if( db_exists("SELECT 1 FROM vfile WHERE pathname=%Q", zPath) ){
110 db_multi_exec("UPDATE vfile SET deleted=0 WHERE pathname=%Q", zPath);
111 }
112 #endif
113 else{
114 char *zFullname = mprintf("%s%s", g.zLocalRoot, zPath);
115 db_multi_exec(
116 "INSERT INTO vfile(vid,deleted,rid,mrid,pathname,isexe)"
117 "VALUES(%d,0,0,0,%Q,%d)",
118 vid, zPath, file_isexe(zFullname));
119 fossil_free(zFullname);
120 }
121 printf("ADDED %s\n", zPath);
122 return 1;
123 }
124
125 /*
126 ** Add all files in the sfile temp table.
127 **
128 ** Automatically exclude the repository file.
129 */
130 static int add_files_in_sfile(int vid){
131 const char *zRepo; /* Name of the repository database file */
132 int nAdd = 0; /* Number of files added */
133 int i; /* Loop counter */
134 const char *zReserved; /* Name of a reserved file */
135 Blob repoName; /* Treename of the repository */
136 Stmt loop; /* SQL to loop over all files to add */
137
138 if( !file_tree_name(g.zRepositoryName, &repoName, 0) ){
139 blob_zero(&repoName);
140 zRepo = "";
141 }else{
142 zRepo = blob_str(&repoName);
143 }
144 db_prepare(&loop, "SELECT x FROM sfile ORDER BY x");
145 while( db_step(&loop)==SQLITE_ROW ){
146 const char *zToAdd = db_column_text(&loop, 0);
147 if( fossil_strcmp(zToAdd, zRepo)==0 ) continue;
148 for(i=0; (zReserved = fossil_reserved_name(i))!=0; i++){
149 if( fossil_strcmp(zToAdd, zReserved)==0 ) break;
150 }
151 if( zReserved ) continue;
152 nAdd += add_one_file(zToAdd, vid);
153 }
154 db_finalize(&loop);
155 blob_reset(&repoName);
156 return nAdd;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
157 }
158
159 /*
160 ** COMMAND: add
161 **
@@ -221,26 +166,24 @@
166 **
167 ** When adding files or directories recursively, filenames that begin
168 ** with "." are excluded by default. To include such files, add
169 ** the "--dotfiles" option to the command-line.
170 **
171 ** The --ignore option is a comma-separate list of glob patterns for files
172 ** to be excluded. Example: '*.o,*.obj,*.exe' If the --ignore option
173 ** does not appear on the command line then the "ignore-glob" setting is
174 ** used.
 
175 **
176 ** SUMMARY: fossil add ?OPTIONS? FILE1 ?FILE2 ...?
177 ** Options: --dotfiles, --ignore
178 */
179 void add_cmd(void){
180 int i; /* Loop counter */
181 int vid; /* Currently checked out version */
182 int nRoot; /* Full path characters in g.zLocalRoot */
183 const char *zIgnoreFlag; /* The --ignore option or ignore-glob setting */
184 Glob *pIgnore; /* Ignore everything matching this glob pattern */
 
185
186 zIgnoreFlag = find_option("ignore",0,1);
187 includeDotFiles = find_option("dotfiles",0,0)!=0;
188 db_must_be_within_tree();
189 if( zIgnoreFlag==0 ){
@@ -249,101 +192,49 @@
192 vid = db_lget_int("checkout",0);
193 if( vid==0 ){
194 fossil_panic("no checkout to add to");
195 }
196 db_begin_transaction();
 
 
 
197 db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)");
198 #if defined(_WIN32)
199 db_multi_exec(
200 "CREATE INDEX IF NOT EXISTS vfile_pathname "
201 " ON vfile(pathname COLLATE nocase)"
202 );
203 #endif
204 pIgnore = glob_create(zIgnoreFlag);
205 nRoot = strlen(g.zLocalRoot);
206
207 /* Load the names of all files that are to be added into sfile temp table */
 
 
208 for(i=2; i<g.argc; i++){
209 char *zName;
210 int isDir;
211 Blob fullName;
212
213 file_canonical_name(g.argv[i], &fullName);
214 zName = blob_str(&fullName);
215 isDir = file_isdir(zName);
216 if( isDir==1 ){
217 vfile_scan(&fullName, nRoot-1, includeDotFiles, pIgnore);
 
 
218 }else if( isDir==0 ){
219 fossil_fatal("not found: %s", zName);
220 }else if( access(zName, R_OK) ){
221 fossil_fatal("cannot open %s", zName);
222 }else{
223 char *zTreeName = &zName[nRoot];
224 db_multi_exec(
225 "INSERT OR IGNORE INTO sfile(x)"
226 " SELECT %Q WHERE NOT EXISTS(SELECT 1 FROM vfile WHERE pathname=%Q)",
227 zTreeName, zTreeName
228 );
229 }
230 free(zName);
231 }
232 glob_free(pIgnore);
233
234 add_files_in_sfile(vid);
235 db_end_transaction(0);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
236 }
237
238 /*
239 ** COMMAND: rm
240 ** COMMAND: delete
@@ -361,31 +252,45 @@
252 ** or: fossil delete FILE1 ?FILE2 ...?
253 */
254 void delete_cmd(void){
255 int i;
256 int vid;
257 Stmt loop;
258
259 db_must_be_within_tree();
260 vid = db_lget_int("checkout", 0);
261 if( vid==0 ){
262 fossil_panic("no checkout to remove from");
263 }
264 db_begin_transaction();
265 db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)");
266 for(i=2; i<g.argc; i++){
267 Blob treeName;
268 char *zTreeName;
269
270 file_tree_name(g.argv[i], &treeName, 1);
271 zTreeName = blob_str(&treeName);
272 db_multi_exec(
273 "INSERT OR IGNORE INTO sfile"
274 " SELECT pathname FROM vfile"
275 " WHERE (pathname=%Q"
276 " OR (pathname>'%q/' AND pathname<'%q0'))"
277 " AND NOT deleted",
278 zTreeName, zTreeName, zTreeName
279 );
280 blob_reset(&treeName);
281 }
282
283 db_prepare(&loop, "SELECT x FROM sfile");
284 while( db_step(&loop)==SQLITE_ROW ){
285 printf("DELETED %s\n", db_column_text(&loop, 0));
286 }
287 db_finalize(&loop);
288 db_multi_exec(
289 "UPDATE vfile SET deleted=1 WHERE pathname IN sfile;"
290 "DELETE FROM vfile WHERE rid=0 AND deleted;"
291 );
292 db_end_transaction(0);
293 }
294
295 /*
296 ** COMMAND: addremove
@@ -426,13 +331,13 @@
331 int allFlag = find_option("dotfiles",0,0)!=0;
332 int isTest = find_option("test",0,0)!=0;
333 int n;
334 Stmt q;
335 int vid;
 
336 int nAdd = 0;
337 int nDelete = 0;
338 Glob *pIgnore;
339
340 db_must_be_within_tree();
341 if( zIgnoreFlag==0 ){
342 zIgnoreFlag = db_get("ignore-glob", 0);
343 }
@@ -439,38 +344,30 @@
344 vid = db_lget_int("checkout",0);
345 if( vid==0 ){
346 fossil_panic("no checkout to add to");
347 }
348 db_begin_transaction();
349
350 /* step 1:
351 ** Populate the temp table "sfile" with the names of all unmanged
352 ** files currently in the check-out, except for files that match the
353 ** --ignore or ignore-glob patterns and dot-files. Then add all of
354 ** the files in the sfile temp table to the set of managed files.
355 */
356 db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)");
357 n = strlen(g.zLocalRoot);
358 blob_init(&path, g.zLocalRoot, n-1);
359 /* now we read the complete file structure into a temp table */
360 pIgnore = glob_create(zIgnoreFlag);
361 vfile_scan(&path, blob_size(&path), allFlag, pIgnore);
362 glob_free(pIgnore);
363 nAdd = add_files_in_sfile(vid);
364
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
365 /* step 2: search for missing files */
366 db_prepare(&q,
367 "SELECT pathname, %Q || pathname, deleted FROM vfile"
368 " WHERE NOT deleted"
369 " ORDER BY 1",
370 g.zLocalRoot
371 );
372 while( db_step(&q)==SQLITE_ROW ){
373 const char * zFile;
@@ -572,13 +469,13 @@
469 zOrig = blob_str(&orig);
470 nOrig = blob_size(&orig);
471 db_prepare(&q,
472 "SELECT pathname FROM vfile"
473 " WHERE vid=%d"
474 " AND (pathname='%q' OR (pathname>'%q/' AND pathname<'%q0'))"
475 " ORDER BY 1",
476 vid, zOrig, zOrig, zOrig
477 );
478 while( db_step(&q)==SQLITE_ROW ){
479 const char *zPath = db_column_text(&q, 0);
480 int nPath = db_column_bytes(&q, 0);
481 const char *zTail;
482
+12 -7
--- src/checkin.c
+++ src/checkin.c
@@ -221,27 +221,28 @@
221221
Stmt q;
222222
int n;
223223
const char *zIgnoreFlag = find_option("ignore",0,1);
224224
int allFlag = find_option("dotfiles",0,0)!=0;
225225
int outputManifest;
226
+ Glob *pIgnore;
226227
227228
db_must_be_within_tree();
228229
outputManifest = db_get_boolean("manifest",0);
229230
db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)");
230231
n = strlen(g.zLocalRoot);
231232
blob_init(&path, g.zLocalRoot, n-1);
232233
if( zIgnoreFlag==0 ){
233234
zIgnoreFlag = db_get("ignore-glob", 0);
234235
}
235
- vfile_scan(0, &path, blob_size(&path), allFlag);
236
+ pIgnore = glob_create(zIgnoreFlag);
237
+ vfile_scan(&path, blob_size(&path), allFlag, pIgnore);
238
+ glob_free(pIgnore);
236239
db_prepare(&q,
237240
"SELECT x FROM sfile"
238241
" WHERE x NOT IN (%s)"
239
- " AND NOT %s"
240242
" ORDER BY 1",
241
- fossil_all_reserved_names(),
242
- glob_expr("x", zIgnoreFlag)
243
+ fossil_all_reserved_names()
243244
);
244245
if( file_tree_name(g.zRepositoryName, &repo, 0) ){
245246
db_multi_exec("DELETE FROM sfile WHERE x=%B", &repo);
246247
}
247248
while( db_step(&q)==SQLITE_ROW ){
@@ -278,23 +279,27 @@
278279
Stmt q;
279280
int n;
280281
allFlag = find_option("force","f",0)!=0;
281282
dotfilesFlag = find_option("dotfiles",0,0)!=0;
282283
zIgnoreFlag = find_option("ignore",0,1);
284
+ Glob *pIgnore;
285
+
283286
db_must_be_within_tree();
284287
if( zIgnoreFlag==0 ){
285288
zIgnoreFlag = db_get("ignore-glob", 0);
286289
}
287290
db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)");
288291
n = strlen(g.zLocalRoot);
289292
blob_init(&path, g.zLocalRoot, n-1);
290
- vfile_scan(0, &path, blob_size(&path), dotfilesFlag);
293
+ pIgnore = glob_create(zIgnoreFlag);
294
+ vfile_scan(&path, blob_size(&path), dotfilesFlag, pIgnore);
295
+ glob_free(pIgnore);
291296
db_prepare(&q,
292297
"SELECT %Q || x FROM sfile"
293
- " WHERE x NOT IN (%s) AND NOT %s"
298
+ " WHERE x NOT IN (%s)"
294299
" ORDER BY 1",
295
- g.zLocalRoot, fossil_all_reserved_names(), glob_expr("x",zIgnoreFlag)
300
+ g.zLocalRoot, fossil_all_reserved_names()
296301
);
297302
if( file_tree_name(g.zRepositoryName, &repo, 0) ){
298303
db_multi_exec("DELETE FROM sfile WHERE x=%B", &repo);
299304
}
300305
while( db_step(&q)==SQLITE_ROW ){
301306
--- src/checkin.c
+++ src/checkin.c
@@ -221,27 +221,28 @@
221 Stmt q;
222 int n;
223 const char *zIgnoreFlag = find_option("ignore",0,1);
224 int allFlag = find_option("dotfiles",0,0)!=0;
225 int outputManifest;
 
226
227 db_must_be_within_tree();
228 outputManifest = db_get_boolean("manifest",0);
229 db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)");
230 n = strlen(g.zLocalRoot);
231 blob_init(&path, g.zLocalRoot, n-1);
232 if( zIgnoreFlag==0 ){
233 zIgnoreFlag = db_get("ignore-glob", 0);
234 }
235 vfile_scan(0, &path, blob_size(&path), allFlag);
 
 
236 db_prepare(&q,
237 "SELECT x FROM sfile"
238 " WHERE x NOT IN (%s)"
239 " AND NOT %s"
240 " ORDER BY 1",
241 fossil_all_reserved_names(),
242 glob_expr("x", zIgnoreFlag)
243 );
244 if( file_tree_name(g.zRepositoryName, &repo, 0) ){
245 db_multi_exec("DELETE FROM sfile WHERE x=%B", &repo);
246 }
247 while( db_step(&q)==SQLITE_ROW ){
@@ -278,23 +279,27 @@
278 Stmt q;
279 int n;
280 allFlag = find_option("force","f",0)!=0;
281 dotfilesFlag = find_option("dotfiles",0,0)!=0;
282 zIgnoreFlag = find_option("ignore",0,1);
 
 
283 db_must_be_within_tree();
284 if( zIgnoreFlag==0 ){
285 zIgnoreFlag = db_get("ignore-glob", 0);
286 }
287 db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)");
288 n = strlen(g.zLocalRoot);
289 blob_init(&path, g.zLocalRoot, n-1);
290 vfile_scan(0, &path, blob_size(&path), dotfilesFlag);
 
 
291 db_prepare(&q,
292 "SELECT %Q || x FROM sfile"
293 " WHERE x NOT IN (%s) AND NOT %s"
294 " ORDER BY 1",
295 g.zLocalRoot, fossil_all_reserved_names(), glob_expr("x",zIgnoreFlag)
296 );
297 if( file_tree_name(g.zRepositoryName, &repo, 0) ){
298 db_multi_exec("DELETE FROM sfile WHERE x=%B", &repo);
299 }
300 while( db_step(&q)==SQLITE_ROW ){
301
--- src/checkin.c
+++ src/checkin.c
@@ -221,27 +221,28 @@
221 Stmt q;
222 int n;
223 const char *zIgnoreFlag = find_option("ignore",0,1);
224 int allFlag = find_option("dotfiles",0,0)!=0;
225 int outputManifest;
226 Glob *pIgnore;
227
228 db_must_be_within_tree();
229 outputManifest = db_get_boolean("manifest",0);
230 db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)");
231 n = strlen(g.zLocalRoot);
232 blob_init(&path, g.zLocalRoot, n-1);
233 if( zIgnoreFlag==0 ){
234 zIgnoreFlag = db_get("ignore-glob", 0);
235 }
236 pIgnore = glob_create(zIgnoreFlag);
237 vfile_scan(&path, blob_size(&path), allFlag, pIgnore);
238 glob_free(pIgnore);
239 db_prepare(&q,
240 "SELECT x FROM sfile"
241 " WHERE x NOT IN (%s)"
 
242 " ORDER BY 1",
243 fossil_all_reserved_names()
 
244 );
245 if( file_tree_name(g.zRepositoryName, &repo, 0) ){
246 db_multi_exec("DELETE FROM sfile WHERE x=%B", &repo);
247 }
248 while( db_step(&q)==SQLITE_ROW ){
@@ -278,23 +279,27 @@
279 Stmt q;
280 int n;
281 allFlag = find_option("force","f",0)!=0;
282 dotfilesFlag = find_option("dotfiles",0,0)!=0;
283 zIgnoreFlag = find_option("ignore",0,1);
284 Glob *pIgnore;
285
286 db_must_be_within_tree();
287 if( zIgnoreFlag==0 ){
288 zIgnoreFlag = db_get("ignore-glob", 0);
289 }
290 db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)");
291 n = strlen(g.zLocalRoot);
292 blob_init(&path, g.zLocalRoot, n-1);
293 pIgnore = glob_create(zIgnoreFlag);
294 vfile_scan(&path, blob_size(&path), dotfilesFlag, pIgnore);
295 glob_free(pIgnore);
296 db_prepare(&q,
297 "SELECT %Q || x FROM sfile"
298 " WHERE x NOT IN (%s)"
299 " ORDER BY 1",
300 g.zLocalRoot, fossil_all_reserved_names()
301 );
302 if( file_tree_name(g.zRepositoryName, &repo, 0) ){
303 db_multi_exec("DELETE FROM sfile WHERE x=%B", &repo);
304 }
305 while( db_step(&q)==SQLITE_ROW ){
306
+39 -8
--- src/vfile.c
+++ src/vfile.c
@@ -298,21 +298,43 @@
298298
** Load into table SFILE the name of every ordinary file in
299299
** the directory pPath. Omit the first nPrefix characters of
300300
** of pPath when inserting into the SFILE table.
301301
**
302302
** Subdirectories are scanned recursively.
303
-** Omit files named in VFILE.vid
303
+** Omit files named in VFILE.
304
+**
305
+** Files whose names begin with "." are omitted unless allFlag is true.
306
+**
307
+** Any files or directories that match the glob pattern pIgnore are
308
+** excluded from the scan. Name matching occurs after the first
309
+** nPrefix characters are elided from the filename.
304310
*/
305
-void vfile_scan(int vid, Blob *pPath, int nPrefix, int allFlag){
311
+void vfile_scan(Blob *pPath, int nPrefix, int allFlag, Glob *pIgnore){
306312
DIR *d;
307313
int origSize;
308314
const char *zDir;
309315
struct dirent *pEntry;
310
- static const char *zSql = "SELECT 1 FROM vfile "
311
- " WHERE pathname=%Q AND NOT deleted";
316
+ int skipAll = 0;
317
+ static Stmt ins;
318
+ static int depth = 0;
312319
313320
origSize = blob_size(pPath);
321
+ if( pIgnore ){
322
+ blob_appendf(pPath, "/");
323
+ if( glob_match(pIgnore, &blob_str(pPath)[nPrefix+1]) ) skipAll = 1;
324
+ blob_resize(pPath, origSize);
325
+ }
326
+ if( skipAll ) return;
327
+
328
+ if( depth==0 ){
329
+ db_prepare(&ins,
330
+ "INSERT OR IGNORE INTO sfile(x) SELECT :file"
331
+ " WHERE NOT EXISTS(SELECT 1 FROM vfile WHERE pathname=:file)"
332
+ );
333
+ }
334
+ depth++;
335
+
314336
zDir = blob_str(pPath);
315337
d = opendir(zDir);
316338
if( d ){
317339
while( (pEntry=readdir(d))!=0 ){
318340
char *zPath;
@@ -321,19 +343,28 @@
321343
if( pEntry->d_name[1]==0 ) continue;
322344
if( pEntry->d_name[1]=='.' && pEntry->d_name[2]==0 ) continue;
323345
}
324346
blob_appendf(pPath, "/%s", pEntry->d_name);
325347
zPath = blob_str(pPath);
326
- if( file_isdir(zPath)==1 ){
327
- vfile_scan(vid, pPath, nPrefix, allFlag);
328
- }else if( file_isfile(zPath) && !db_exists(zSql, &zPath[nPrefix+1]) ){
329
- db_multi_exec("INSERT INTO sfile VALUES(%Q)", &zPath[nPrefix+1]);
348
+ if( glob_match(pIgnore, &zPath[nPrefix+1]) ){
349
+ /* do nothing */
350
+ }else if( file_isdir(zPath)==1 ){
351
+ vfile_scan(pPath, nPrefix, allFlag, pIgnore);
352
+ }else if( file_isfile(zPath) ){
353
+ db_bind_text(&ins, ":file", &zPath[nPrefix+1]);
354
+ db_step(&ins);
355
+ db_reset(&ins);
330356
}
331357
blob_resize(pPath, origSize);
332358
}
333359
closedir(d);
334360
}
361
+
362
+ depth--;
363
+ if( depth==0 ){
364
+ db_finalize(&ins);
365
+ }
335366
}
336367
337368
/*
338369
** Compute an aggregate MD5 checksum over the disk image of every
339370
** file in vid. The file names are part of the checksum. The resulting
340371
--- src/vfile.c
+++ src/vfile.c
@@ -298,21 +298,43 @@
298 ** Load into table SFILE the name of every ordinary file in
299 ** the directory pPath. Omit the first nPrefix characters of
300 ** of pPath when inserting into the SFILE table.
301 **
302 ** Subdirectories are scanned recursively.
303 ** Omit files named in VFILE.vid
 
 
 
 
 
 
304 */
305 void vfile_scan(int vid, Blob *pPath, int nPrefix, int allFlag){
306 DIR *d;
307 int origSize;
308 const char *zDir;
309 struct dirent *pEntry;
310 static const char *zSql = "SELECT 1 FROM vfile "
311 " WHERE pathname=%Q AND NOT deleted";
 
312
313 origSize = blob_size(pPath);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
314 zDir = blob_str(pPath);
315 d = opendir(zDir);
316 if( d ){
317 while( (pEntry=readdir(d))!=0 ){
318 char *zPath;
@@ -321,19 +343,28 @@
321 if( pEntry->d_name[1]==0 ) continue;
322 if( pEntry->d_name[1]=='.' && pEntry->d_name[2]==0 ) continue;
323 }
324 blob_appendf(pPath, "/%s", pEntry->d_name);
325 zPath = blob_str(pPath);
326 if( file_isdir(zPath)==1 ){
327 vfile_scan(vid, pPath, nPrefix, allFlag);
328 }else if( file_isfile(zPath) && !db_exists(zSql, &zPath[nPrefix+1]) ){
329 db_multi_exec("INSERT INTO sfile VALUES(%Q)", &zPath[nPrefix+1]);
 
 
 
 
330 }
331 blob_resize(pPath, origSize);
332 }
333 closedir(d);
334 }
 
 
 
 
 
335 }
336
337 /*
338 ** Compute an aggregate MD5 checksum over the disk image of every
339 ** file in vid. The file names are part of the checksum. The resulting
340
--- src/vfile.c
+++ src/vfile.c
@@ -298,21 +298,43 @@
298 ** Load into table SFILE the name of every ordinary file in
299 ** the directory pPath. Omit the first nPrefix characters of
300 ** of pPath when inserting into the SFILE table.
301 **
302 ** Subdirectories are scanned recursively.
303 ** Omit files named in VFILE.
304 **
305 ** Files whose names begin with "." are omitted unless allFlag is true.
306 **
307 ** Any files or directories that match the glob pattern pIgnore are
308 ** excluded from the scan. Name matching occurs after the first
309 ** nPrefix characters are elided from the filename.
310 */
311 void vfile_scan(Blob *pPath, int nPrefix, int allFlag, Glob *pIgnore){
312 DIR *d;
313 int origSize;
314 const char *zDir;
315 struct dirent *pEntry;
316 int skipAll = 0;
317 static Stmt ins;
318 static int depth = 0;
319
320 origSize = blob_size(pPath);
321 if( pIgnore ){
322 blob_appendf(pPath, "/");
323 if( glob_match(pIgnore, &blob_str(pPath)[nPrefix+1]) ) skipAll = 1;
324 blob_resize(pPath, origSize);
325 }
326 if( skipAll ) return;
327
328 if( depth==0 ){
329 db_prepare(&ins,
330 "INSERT OR IGNORE INTO sfile(x) SELECT :file"
331 " WHERE NOT EXISTS(SELECT 1 FROM vfile WHERE pathname=:file)"
332 );
333 }
334 depth++;
335
336 zDir = blob_str(pPath);
337 d = opendir(zDir);
338 if( d ){
339 while( (pEntry=readdir(d))!=0 ){
340 char *zPath;
@@ -321,19 +343,28 @@
343 if( pEntry->d_name[1]==0 ) continue;
344 if( pEntry->d_name[1]=='.' && pEntry->d_name[2]==0 ) continue;
345 }
346 blob_appendf(pPath, "/%s", pEntry->d_name);
347 zPath = blob_str(pPath);
348 if( glob_match(pIgnore, &zPath[nPrefix+1]) ){
349 /* do nothing */
350 }else if( file_isdir(zPath)==1 ){
351 vfile_scan(pPath, nPrefix, allFlag, pIgnore);
352 }else if( file_isfile(zPath) ){
353 db_bind_text(&ins, ":file", &zPath[nPrefix+1]);
354 db_step(&ins);
355 db_reset(&ins);
356 }
357 blob_resize(pPath, origSize);
358 }
359 closedir(d);
360 }
361
362 depth--;
363 if( depth==0 ){
364 db_finalize(&ins);
365 }
366 }
367
368 /*
369 ** Compute an aggregate MD5 checksum over the disk image of every
370 ** file in vid. The file names are part of the checksum. The resulting
371

Keyboard Shortcuts

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