Index: src/checkin.c ================================================================== --- src/checkin.c +++ src/checkin.c @@ -236,11 +236,11 @@ int verboseFlag; int showAge; char *zOrderBy = "pathname"; verboseFlag = find_option("verbose","v", 0)!=0; - if(!verboseFlag){ + if( !verboseFlag ){ verboseFlag = find_option("l","l", 0)!=0; /* deprecated */ } showAge = find_option("age",0,0)!=0; db_must_be_within_tree(); vid = db_lget_int("checkout", 0); @@ -381,11 +381,13 @@ ** COMMAND: clean ** Usage: %fossil clean ?OPTIONS? ** ** Delete all "extra" files in the source tree. "Extra" files are ** files that are not officially part of the checkout. This operation -** cannot be undone. +** cannot be undone. Normally, only files unknown to fossil are +** removed, but if the -x option is specified, ignored files are +** removed as well. ** ** You will be prompted before removing each eligible file unless the ** --force flag is in use or it matches the --clean option. The ** GLOBPATTERN specified by the "ignore-glob" setting is used if the ** --ignore option is omitted, the same with "clean-glob" and --clean @@ -410,23 +412,27 @@ ** --keep keep files matching this comma separated ** list of glob patterns. ** -n|--dry-run If given, display instead of run actions ** --temp Remove only Fossil-generated temporary files ** -v|--verbose Show all files as they are removed +** -x Remove everything unkown to fossil, +** including files matching --ignore. +** Compatibile with "git clean -x". ** ** See also: addremove, extra, status */ void clean_cmd(void){ - int allFlag, dryRunFlag, verboseFlag; + int allFlag, dryRunFlag, verboseFlag, xFlag; unsigned scanFlags = 0; const char *zIgnoreFlag, *zKeepFlag, *zCleanFlag; Blob path, repo; Stmt q; int n; Glob *pIgnore, *pKeep, *pClean; dryRunFlag = find_option("dry-run","n",0)!=0; + xFlag = find_option("x","x",0)!=0; if( !dryRunFlag ){ dryRunFlag = find_option("test",0,0)!=0; /* deprecated */ } allFlag = find_option("force","f",0)!=0 || dryRunFlag; if( find_option("dotfiles",0,0)!=0 ) scanFlags |= SCAN_ALL; @@ -452,13 +458,12 @@ n = strlen(g.zLocalRoot); blob_init(&path, g.zLocalRoot, n-1); pIgnore = glob_create(zIgnoreFlag); pKeep = glob_create(zKeepFlag); pClean = glob_create(zCleanFlag); - vfile_scan2(&path, blob_size(&path), scanFlags, pIgnore, pKeep); + vfile_scan2(&path, blob_size(&path), scanFlags, xFlag?0:pIgnore, pKeep); glob_free(pKeep); - glob_free(pIgnore); db_prepare(&q, "SELECT %Q || x FROM sfile" " WHERE x NOT IN (%s)" " ORDER BY 1", g.zLocalRoot, fossil_all_reserved_names(0) @@ -467,11 +472,12 @@ db_multi_exec("DELETE FROM sfile WHERE x=%B", &repo); } db_multi_exec("DELETE FROM sfile WHERE x IN (SELECT pathname FROM vfile)"); while( db_step(&q)==SQLITE_ROW ){ const char *zName = db_column_text(&q, 0); - if( !allFlag && !glob_match(pClean, zName+n) ){ + if( !allFlag && !glob_match(pClean, zName+n) + && (!xFlag || !glob_match(pIgnore, zName+n))){ Blob ans; char cReply; char *prompt = mprintf("remove unmanaged file \"%s\" (a=all/y/N)? ", zName+n); blob_zero(&ans); @@ -488,10 +494,11 @@ } if( !dryRunFlag ){ file_delete(zName); } } + glob_free(pIgnore); glob_free(pClean); db_finalize(&q); } /*