| | @@ -297,10 +297,58 @@ |
| 297 | 297 | } |
| 298 | 298 | free(zFullName); |
| 299 | 299 | } |
| 300 | 300 | db_finalize(&q); |
| 301 | 301 | } |
| 302 | + |
| 303 | +/* |
| 304 | +** Create a TEMP table named SFILE and add all unmanaged files named on the command-line |
| 305 | +** to that table. If directories are named, then add all unmanged files contained |
| 306 | +** underneath those directories. If there are no files or directories named on the |
| 307 | +** command-line, then add all unmanaged files anywhere in the checkout. |
| 308 | +*/ |
| 309 | +static void locate_unmanaged_files( |
| 310 | + int argc, /* Number of command-line arguments to examine */ |
| 311 | + char **argv, /* values of command-line arguments */ |
| 312 | + unsigned scanFlags, /* Zero or more SCAN_xxx flags */ |
| 313 | + Glob *pIgnore1, /* Do not add files that match this GLOB */ |
| 314 | + Glob *pIgnore2 /* Omit files matching this GLOB too */ |
| 315 | +){ |
| 316 | + Blob name; /* Name of a candidate file or directory */ |
| 317 | + char *zName; /* Name of a candidate file or directory */ |
| 318 | + int isDir; /* 1 for a directory, 0 if doesn't exist, 2 for anything else */ |
| 319 | + int i; /* Loop counter */ |
| 320 | + int nRoot; /* length of g.zLocalRoot */ |
| 321 | + |
| 322 | + db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY %s)", |
| 323 | + filename_collation()); |
| 324 | + nRoot = (int)strlen(g.zLocalRoot); |
| 325 | + if( argc==0 ){ |
| 326 | + blob_init(&name, g.zLocalRoot, nRoot - 1); |
| 327 | + vfile_scan(&name, blob_size(&name), scanFlags, pIgnore1, pIgnore2); |
| 328 | + blob_reset(&name); |
| 329 | + }else{ |
| 330 | + for(i=0; i<argc; i++){ |
| 331 | + file_canonical_name(argv[i], &name, 0); |
| 332 | + zName = blob_str(&name); |
| 333 | + isDir = file_wd_isdir(zName); |
| 334 | + if( isDir==1 ){ |
| 335 | + vfile_scan(&name, nRoot-1, scanFlags, pIgnore1, pIgnore2); |
| 336 | + }else if( isDir==0 ){ |
| 337 | + fossil_warning("not found: %s", zName); |
| 338 | + }else if( file_access(zName, R_OK) ){ |
| 339 | + fossil_fatal("cannot open %s", zName); |
| 340 | + }else{ |
| 341 | + db_multi_exec( |
| 342 | + "INSERT OR IGNORE INTO sfile(x) VALUES(%Q)", |
| 343 | + &zName[nRoot] |
| 344 | + ); |
| 345 | + } |
| 346 | + blob_reset(&name); |
| 347 | + } |
| 348 | + } |
| 349 | +} |
| 302 | 350 | |
| 303 | 351 | /* |
| 304 | 352 | ** COMMAND: extras |
| 305 | 353 | ** Usage: %fossil extras ?OPTIONS? ?PATH1 ...? |
| 306 | 354 | ** |
| | @@ -327,13 +375,11 @@ |
| 327 | 375 | ** directory. |
| 328 | 376 | ** |
| 329 | 377 | ** See also: changes, clean, status |
| 330 | 378 | */ |
| 331 | 379 | void extra_cmd(void){ |
| 332 | | - Blob path; |
| 333 | 380 | Stmt q; |
| 334 | | - int n, i; |
| 335 | 381 | const char *zIgnoreFlag = find_option("ignore",0,1); |
| 336 | 382 | unsigned scanFlags = find_option("dotfiles",0,0)!=0 ? SCAN_ALL : 0; |
| 337 | 383 | int cwdRelative = 0; |
| 338 | 384 | Glob *pIgnore; |
| 339 | 385 | Blob rewrittenPathname; |
| | @@ -341,45 +387,15 @@ |
| 341 | 387 | |
| 342 | 388 | if( find_option("temp",0,0)!=0 ) scanFlags |= SCAN_TEMP; |
| 343 | 389 | capture_case_sensitive_option(); |
| 344 | 390 | db_must_be_within_tree(); |
| 345 | 391 | cwdRelative = determine_cwd_relative_option(); |
| 346 | | - db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY %s)", |
| 347 | | - filename_collation()); |
| 348 | | - n = strlen(g.zLocalRoot); |
| 349 | | - blob_init(&path, g.zLocalRoot, n-1); |
| 350 | 392 | if( zIgnoreFlag==0 ){ |
| 351 | 393 | zIgnoreFlag = db_get("ignore-glob", 0); |
| 352 | 394 | } |
| 353 | 395 | pIgnore = glob_create(zIgnoreFlag); |
| 354 | | - |
| 355 | | - /* Load the names of all files that are candidates to be listed into sfile temp table */ |
| 356 | | - if( g.argc < 3 ){ |
| 357 | | - vfile_scan(&path, blob_size(&path), scanFlags, pIgnore); |
| 358 | | - } |
| 359 | | - for( i=2; i<g.argc; i++ ){ |
| 360 | | - char *zName; |
| 361 | | - int isDir; |
| 362 | | - Blob fullName; |
| 363 | | - |
| 364 | | - file_canonical_name(g.argv[i], &fullName, 0); |
| 365 | | - zName = blob_str(&fullName); |
| 366 | | - isDir = file_wd_isdir(zName); |
| 367 | | - if( isDir==1 ){ |
| 368 | | - vfile_scan(&fullName, n-1, scanFlags, pIgnore); |
| 369 | | - }else if( isDir==0 ){ |
| 370 | | - fossil_warning("not found: %s", zName); |
| 371 | | - }else if( file_access(zName, R_OK) ){ |
| 372 | | - fossil_fatal("cannot open %s", zName); |
| 373 | | - }else{ |
| 374 | | - db_multi_exec( |
| 375 | | - "INSERT OR IGNORE INTO sfile(x) VALUES(%Q)", |
| 376 | | - &zName[n] |
| 377 | | - ); |
| 378 | | - } |
| 379 | | - blob_reset(&fullName); |
| 380 | | - } |
| 396 | + locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags, pIgnore, 0); |
| 381 | 397 | glob_free(pIgnore); |
| 382 | 398 | db_prepare(&q, |
| 383 | 399 | "SELECT x FROM sfile" |
| 384 | 400 | " WHERE x NOT IN (%s)" |
| 385 | 401 | " ORDER BY 1", |
| | @@ -445,14 +461,14 @@ |
| 445 | 461 | */ |
| 446 | 462 | void clean_cmd(void){ |
| 447 | 463 | int allFlag, dryRunFlag, verboseFlag; |
| 448 | 464 | unsigned scanFlags = 0; |
| 449 | 465 | const char *zIgnoreFlag, *zKeepFlag, *zCleanFlag; |
| 450 | | - Blob path, repo; |
| 466 | + Blob repo; |
| 451 | 467 | Stmt q; |
| 452 | | - int n, i; |
| 453 | 468 | Glob *pIgnore, *pKeep, *pClean; |
| 469 | + int nRoot; |
| 454 | 470 | |
| 455 | 471 | dryRunFlag = find_option("dry-run","n",0)!=0; |
| 456 | 472 | if( !dryRunFlag ){ |
| 457 | 473 | dryRunFlag = find_option("test",0,0)!=0; /* deprecated */ |
| 458 | 474 | } |
| | @@ -473,44 +489,14 @@ |
| 473 | 489 | } |
| 474 | 490 | if( zCleanFlag==0 ){ |
| 475 | 491 | zCleanFlag = db_get("clean-glob", 0); |
| 476 | 492 | } |
| 477 | 493 | verify_all_options(); |
| 478 | | - db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY %s)", |
| 479 | | - filename_collation()); |
| 480 | | - n = strlen(g.zLocalRoot); |
| 481 | | - blob_init(&path, g.zLocalRoot, n-1); |
| 482 | 494 | pIgnore = glob_create(zIgnoreFlag); |
| 483 | 495 | pKeep = glob_create(zKeepFlag); |
| 484 | 496 | pClean = glob_create(zCleanFlag); |
| 485 | | - |
| 486 | | - /* Load the names of all files that are candidates to be cleaned into sfile temp table */ |
| 487 | | - if( g.argc < 3 ){ |
| 488 | | - vfile_scan2(&path, blob_size(&path), scanFlags, pIgnore, pKeep); |
| 489 | | - } |
| 490 | | - for( i=2; i<g.argc; i++ ){ |
| 491 | | - char *zName; |
| 492 | | - int isDir; |
| 493 | | - Blob fullName; |
| 494 | | - |
| 495 | | - file_canonical_name(g.argv[i], &fullName, 0); |
| 496 | | - zName = blob_str(&fullName); |
| 497 | | - isDir = file_wd_isdir(zName); |
| 498 | | - if( isDir==1 ){ |
| 499 | | - vfile_scan2(&fullName, n-1, scanFlags, pIgnore, pKeep); |
| 500 | | - }else if( isDir==0 ){ |
| 501 | | - fossil_warning("not found: %s", zName); |
| 502 | | - }else if( file_access(zName, R_OK) ){ |
| 503 | | - fossil_fatal("cannot open %s", zName); |
| 504 | | - }else{ |
| 505 | | - db_multi_exec( |
| 506 | | - "INSERT OR IGNORE INTO sfile(x) VALUES(%Q)", |
| 507 | | - &zName[n] |
| 508 | | - ); |
| 509 | | - } |
| 510 | | - blob_reset(&fullName); |
| 511 | | - } |
| 497 | + locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags, pIgnore, pKeep); |
| 512 | 498 | glob_free(pKeep); |
| 513 | 499 | glob_free(pIgnore); |
| 514 | 500 | db_prepare(&q, |
| 515 | 501 | "SELECT %Q || x FROM sfile" |
| 516 | 502 | " WHERE x NOT IN (%s)" |
| | @@ -519,17 +505,18 @@ |
| 519 | 505 | ); |
| 520 | 506 | if( file_tree_name(g.zRepositoryName, &repo, 0) ){ |
| 521 | 507 | db_multi_exec("DELETE FROM sfile WHERE x=%B", &repo); |
| 522 | 508 | } |
| 523 | 509 | db_multi_exec("DELETE FROM sfile WHERE x IN (SELECT pathname FROM vfile)"); |
| 510 | + nRoot = (int)strlen(g.zLocalRoot); |
| 524 | 511 | while( db_step(&q)==SQLITE_ROW ){ |
| 525 | 512 | const char *zName = db_column_text(&q, 0); |
| 526 | | - if( !allFlag && !dryRunFlag && !glob_match(pClean, zName+n) ){ |
| 513 | + if( !allFlag && !dryRunFlag && !glob_match(pClean, zName+nRoot) ){ |
| 527 | 514 | Blob ans; |
| 528 | 515 | char cReply; |
| 529 | 516 | char *prompt = mprintf("Remove unmanaged file \"%s\" (a=all/y/N)? ", |
| 530 | | - zName+n); |
| 517 | + zName+nRoot); |
| 531 | 518 | blob_zero(&ans); |
| 532 | 519 | prompt_user(prompt, &ans); |
| 533 | 520 | cReply = blob_str(&ans)[0]; |
| 534 | 521 | if( cReply=='a' || cReply=='A' ){ |
| 535 | 522 | allFlag = 1; |
| | @@ -538,11 +525,11 @@ |
| 538 | 525 | continue; |
| 539 | 526 | } |
| 540 | 527 | blob_reset(&ans); |
| 541 | 528 | } |
| 542 | 529 | if( verboseFlag || dryRunFlag ){ |
| 543 | | - fossil_print("Removed unmanaged file: %s\n", zName+n); |
| 530 | + fossil_print("Removed unmanaged file: %s\n", zName+nRoot); |
| 544 | 531 | } |
| 545 | 532 | if( !dryRunFlag ){ |
| 546 | 533 | file_delete(zName); |
| 547 | 534 | } |
| 548 | 535 | } |
| 549 | 536 | |