Fossil SCM

fossil-scm / src / add.c
Source Blame History 1163 lines
dbda8d6… drh 1 /*
c19f34c… drh 2 ** Copyright (c) 2007 D. Richard Hipp
dbda8d6… drh 3 **
dbda8d6… drh 4 ** This program is free software; you can redistribute it and/or
c06edd2… drh 5 ** modify it under the terms of the Simplified BSD License (also
c06edd2… drh 6 ** known as the "2-Clause License" or "FreeBSD License".)
c06edd2… drh 7
dbda8d6… drh 8 ** This program is distributed in the hope that it will be useful,
c06edd2… drh 9 ** but without any warranty; without even the implied warranty of
c06edd2… drh 10 ** merchantability or fitness for a particular purpose.
dbda8d6… drh 11 **
dbda8d6… drh 12 ** Author contact information:
dbda8d6… drh 13 ** [email protected]
dbda8d6… drh 14 ** http://www.hwaci.com/drh/
dbda8d6… drh 15 **
dbda8d6… drh 16 *******************************************************************************
dbda8d6… drh 17 **
dbda8d6… drh 18 ** This file contains code used to check-out versions of the project
dbda8d6… drh 19 ** from the local repository.
dbda8d6… drh 20 */
dbda8d6… drh 21 #include "config.h"
dbda8d6… drh 22 #include "add.h"
dbda8d6… drh 23 #include <assert.h>
8c4e72e… drh 24 #include <dirent.h>
816e893… mistachkin 25 #include "cygsup.h"
56d69db… drh 26
56d69db… drh 27 /*
bc36fdc… danield 28 ** This routine returns the names of files in a working check-out that
56d69db… drh 29 ** are created by Fossil itself, and hence should not be added, deleted,
7afbb70… mistachkin 30 ** or merge, and should be omitted from "clean" and "extras" lists.
56d69db… drh 31 **
56d69db… drh 32 ** Return the N-th name. The first name has N==0. When all names have
56d69db… drh 33 ** been used, return 0.
56d69db… drh 34 */
fcdeaa2… drh 35 const char *fossil_reserved_name(int N, int omitRepo){
bc36fdc… danield 36 /* Possible names of the local per-check-out database file and
56d69db… drh 37 ** its associated journals
56d69db… drh 38 */
6032dd5… jan.nijtmans 39 static const char *const azName[] = {
56d69db… drh 40 "_FOSSIL_",
56d69db… drh 41 "_FOSSIL_-journal",
56d69db… drh 42 "_FOSSIL_-wal",
56d69db… drh 43 "_FOSSIL_-shm",
f9a200f… drh 44 ".fslckout",
f9a200f… drh 45 ".fslckout-journal",
f9a200f… drh 46 ".fslckout-wal",
f9a200f… drh 47 ".fslckout-shm",
f9a200f… drh 48
bc36fdc… danield 49 /* The use of ".fos" as the name of the check-out database is
f9a200f… drh 50 ** deprecated. Use ".fslckout" instead. At some point, the following
f9a200f… drh 51 ** entries should be removed. 2012-02-04 */
56d69db… drh 52 ".fos",
56d69db… drh 53 ".fos-journal",
56d69db… drh 54 ".fos-wal",
56d69db… drh 55 ".fos-shm",
56d69db… drh 56 };
56d69db… drh 57
189bfc2… jan 58 /* Possible names of auxiliary files generated when the "manifest" property
189bfc2… jan 59 ** is used
56d69db… drh 60 */
189bfc2… jan 61 static const struct {
189bfc2… jan 62 const char *fname;
189bfc2… jan 63 int flg;
189bfc2… jan 64 }aManifestflags[] = {
189bfc2… jan 65 { "manifest", MFESTFLG_RAW },
189bfc2… jan 66 { "manifest.uuid", MFESTFLG_UUID },
189bfc2… jan 67 { "manifest.tags", MFESTFLG_TAGS }
56d69db… drh 68 };
189bfc2… jan 69 static const char *azManifests[3];
8b06be7… drh 70
8b06be7… drh 71 /*
bc36fdc… danield 72 ** Names of repository files, if they exist in the check-out.
8b06be7… drh 73 */
8b06be7… drh 74 static const char *azRepo[4] = { 0, 0, 0, 0 };
a369dc7… dmitry 75
a369dc7… dmitry 76 /* Cached setting "manifest" */
a369dc7… dmitry 77 static int cachedManifest = -1;
189bfc2… jan 78 static int numManifests;
a369dc7… dmitry 79
a369dc7… dmitry 80 if( cachedManifest == -1 ){
189bfc2… jan 81 int i;
8b06be7… drh 82 Blob repo;
dfc0f1b… drh 83 cachedManifest = db_get_manifest_setting(0);
189bfc2… jan 84 numManifests = 0;
189bfc2… jan 85 for(i=0; i<count(aManifestflags); i++){
189bfc2… jan 86 if( cachedManifest&aManifestflags[i].flg ) {
189bfc2… jan 87 azManifests[numManifests++] = aManifestflags[i].fname;
189bfc2… jan 88 }
189bfc2… jan 89 }
8b06be7… drh 90 blob_zero(&repo);
c56a387… mistachkin 91 if( file_tree_name(g.zRepositoryName, &repo, 0, 0) ){
8b06be7… drh 92 const char *zRepo = blob_str(&repo);
8b06be7… drh 93 azRepo[0] = zRepo;
8b06be7… drh 94 azRepo[1] = mprintf("%s-journal", zRepo);
8b06be7… drh 95 azRepo[2] = mprintf("%s-wal", zRepo);
8b06be7… drh 96 azRepo[3] = mprintf("%s-shm", zRepo);
8b06be7… drh 97 }
a369dc7… dmitry 98 }
56d69db… drh 99
8b06be7… drh 100 if( N<0 ) return 0;
8b06be7… drh 101 if( N<count(azName) ) return azName[N];
8b06be7… drh 102 N -= count(azName);
8b06be7… drh 103 if( cachedManifest ){
189bfc2… jan 104 if( N<numManifests ) return azManifests[N];
189bfc2… jan 105 N -= numManifests;
56d69db… drh 106 }
fcdeaa2… drh 107 if( !omitRepo && N<count(azRepo) ) return azRepo[N];
56d69db… drh 108 return 0;
56d69db… drh 109 }
56d69db… drh 110
56d69db… drh 111 /*
56d69db… drh 112 ** Return a list of all reserved filenames as an SQL list.
56d69db… drh 113 */
fcdeaa2… drh 114 const char *fossil_all_reserved_names(int omitRepo){
56d69db… drh 115 static char *zAll = 0;
56d69db… drh 116 if( zAll==0 ){
56d69db… drh 117 Blob x;
56d69db… drh 118 int i;
56d69db… drh 119 const char *z;
56d69db… drh 120 blob_zero(&x);
fcdeaa2… drh 121 for(i=0; (z = fossil_reserved_name(i, omitRepo))!=0; i++){
56d69db… drh 122 if( i>0 ) blob_append(&x, ",", 1);
e766df0… drh 123 blob_appendf(&x, "'%q'", z);
56d69db… drh 124 }
56d69db… drh 125 zAll = blob_str(&x);
56d69db… drh 126 }
56d69db… drh 127 return zAll;
e766df0… drh 128 }
e766df0… drh 129
e766df0… drh 130 /*
8b06be7… drh 131 ** COMMAND: test-reserved-names
8b06be7… drh 132 **
fcdeaa2… drh 133 ** Usage: %fossil test-reserved-names [-omitrepo]
fcdeaa2… drh 134 **
8b06be7… drh 135 ** Show all reserved filenames for the current check-out.
8b06be7… drh 136 */
8b06be7… drh 137 void test_reserved_names(void){
8b06be7… drh 138 int i;
8b06be7… drh 139 const char *z;
fcdeaa2… drh 140 int omitRepo = find_option("omitrepo",0,0)!=0;
4e18dba… jan.nijtmans 141
74ac0c9… drh 142 /* We should be done with options.. */
74ac0c9… drh 143 verify_all_options();
74ac0c9… drh 144
8b06be7… drh 145 db_must_be_within_tree();
fcdeaa2… drh 146 for(i=0; (z = fossil_reserved_name(i, omitRepo))!=0; i++){
8b06be7… drh 147 fossil_print("%3d: %s\n", i, z);
8b06be7… drh 148 }
fcdeaa2… drh 149 fossil_print("ALL: (%s)\n", fossil_all_reserved_names(omitRepo));
8b06be7… drh 150 }
8b06be7… drh 151
8b06be7… drh 152 /*
be3d215… drh 153 ** Add a single file named zName to the VFILE table with vid.
be3d215… drh 154 **
be3d215… drh 155 ** Omit any file whose name is pOmit.
be3d215… drh 156 */
8ae9173… drh 157 static int add_one_file(
8ae9173… drh 158 const char *zPath, /* Tree-name of file to add. */
3c781f4… jan.nijtmans 159 int vid /* Add to this VFILE */
be3d215… drh 160 ){
f741baa… drh 161 int doSkip = 0;
d48399b… drh 162 if( !file_is_simple_pathname(zPath, 1) ){
897dfa4… drh 163 fossil_warning("filename contains illegal characters: %s", zPath);
897dfa4… drh 164 return 0;
8ae9173… drh 165 }
8ae9173… drh 166 if( db_exists("SELECT 1 FROM vfile"
3c781f4… jan.nijtmans 167 " WHERE pathname=%Q %s", zPath, filename_collation()) ){
8ae9173… drh 168 db_multi_exec("UPDATE vfile SET deleted=0"
d252cfd… drh 169 " WHERE pathname=%Q %s AND deleted",
d252cfd… drh 170 zPath, filename_collation());
874d0ca… drh 171 }else{
8ae9173… drh 172 char *zFullname = mprintf("%s%s", g.zLocalRoot, zPath);
1772357… drh 173 int isExe = file_isexe(zFullname, RepoFILE);
9d75d6a… andygoth 174 int isLink = file_islink(0);
f741baa… drh 175 if( file_nondir_objects_on_path(g.zLocalRoot, zFullname) ){
f741baa… drh 176 /* Do not add unsafe files to the vfile */
f741baa… drh 177 doSkip = 1;
f741baa… drh 178 }else{
f741baa… drh 179 db_multi_exec(
f741baa… drh 180 "INSERT INTO vfile(vid,deleted,rid,mrid,pathname,isexe,islink,mhash)"
f741baa… drh 181 "VALUES(%d,0,0,0,%Q,%d,%d,NULL)",
9d75d6a… andygoth 182 vid, zPath, isExe, isLink);
f741baa… drh 183 }
8ae9173… drh 184 fossil_free(zFullname);
8ae9173… drh 185 }
f741baa… drh 186 if( db_changes() && !doSkip ){
874d0ca… drh 187 fossil_print("ADDED %s\n", zPath);
874d0ca… drh 188 return 1;
874d0ca… drh 189 }else{
874d0ca… drh 190 fossil_print("SKIP %s\n", zPath);
874d0ca… drh 191 return 0;
874d0ca… drh 192 }
8ae9173… drh 193 }
8ae9173… drh 194
8ae9173… drh 195 /*
8ae9173… drh 196 ** Add all files in the sfile temp table.
8ae9173… drh 197 **
f741baa… drh 198 ** Automatically exclude the repository file and any other files
0537925… andygoth 199 ** with reserved names. Also exclude files that are beneath an
f741baa… drh 200 ** existing symlink.
8ae9173… drh 201 */
3c781f4… jan.nijtmans 202 static int add_files_in_sfile(int vid){
8ae9173… drh 203 const char *zRepo; /* Name of the repository database file */
8ae9173… drh 204 int nAdd = 0; /* Number of files added */
8ae9173… drh 205 int i; /* Loop counter */
8ae9173… drh 206 const char *zReserved; /* Name of a reserved file */
8ae9173… drh 207 Blob repoName; /* Treename of the repository */
8ae9173… drh 208 Stmt loop; /* SQL to loop over all files to add */
874d0ca… drh 209 int (*xCmp)(const char*,const char*);
4e18dba… jan.nijtmans 210
c56a387… mistachkin 211 if( !file_tree_name(g.zRepositoryName, &repoName, 0, 0) ){
8ae9173… drh 212 blob_zero(&repoName);
8ae9173… drh 213 zRepo = "";
8ae9173… drh 214 }else{
8ae9173… drh 215 zRepo = blob_str(&repoName);
8ae9173… drh 216 }
3c781f4… jan.nijtmans 217 if( filenames_are_case_sensitive() ){
874d0ca… drh 218 xCmp = fossil_strcmp;
874d0ca… drh 219 }else{
874d0ca… drh 220 xCmp = fossil_stricmp;
874d0ca… drh 221 }
0537925… andygoth 222 db_prepare(&loop,
f741baa… drh 223 "SELECT pathname FROM sfile"
f741baa… drh 224 " WHERE pathname NOT IN ("
f741baa… drh 225 "SELECT sfile.pathname FROM vfile, sfile"
f741baa… drh 226 " WHERE vfile.islink"
f741baa… drh 227 " AND NOT vfile.deleted"
f741baa… drh 228 " AND sfile.pathname>(vfile.pathname||'/')"
f741baa… drh 229 " AND sfile.pathname<(vfile.pathname||'0'))"
f741baa… drh 230 " ORDER BY pathname");
8ae9173… drh 231 while( db_step(&loop)==SQLITE_ROW ){
8ae9173… drh 232 const char *zToAdd = db_column_text(&loop, 0);
8ae9173… drh 233 if( fossil_strcmp(zToAdd, zRepo)==0 ) continue;
f741baa… drh 234 if( strchr(zToAdd,'/') ){
f741baa… drh 235 if( file_is_reserved_name(zToAdd, -1) ) continue;
f741baa… drh 236 }else{
f741baa… drh 237 for(i=0; (zReserved = fossil_reserved_name(i, 0))!=0; i++){
f741baa… drh 238 if( xCmp(zToAdd, zReserved)==0 ) break;
f741baa… drh 239 }
f741baa… drh 240 if( zReserved ) continue;
8ae9173… drh 241 }
3c781f4… jan.nijtmans 242 nAdd += add_one_file(zToAdd, vid);
8ae9173… drh 243 }
8ae9173… drh 244 db_finalize(&loop);
8ae9173… drh 245 blob_reset(&repoName);
8ae9173… drh 246 return nAdd;
8ae9173… drh 247 }
8ae9173… drh 248
8ae9173… drh 249 /*
bc36fdc… danield 250 ** Resets the ADDED/DELETED state of a check-out, such that all
e0fc98c… stephan 251 ** newly-added (but not yet committed) files are no longer added and
e0fc98c… stephan 252 ** newly-removed (but not yet committed) files are no longer
e0fc98c… stephan 253 ** removed. If bIsAdd is true, it operates on the "add" state, else it
e0fc98c… stephan 254 ** operates on the "rm" state.
e0fc98c… stephan 255 **
e0fc98c… stephan 256 ** If bDryRun is true it outputs what it would have done, but does not
e0fc98c… stephan 257 ** actually do it. In this case it rolls back the transaction it
e0fc98c… stephan 258 ** starts (so don't start a transaction before calling this).
e0fc98c… stephan 259 **
e0fc98c… stephan 260 ** If bVerbose is true it outputs the name of each reset entry.
e0fc98c… stephan 261 **
e0fc98c… stephan 262 ** This is intended to be called only in the context of the
e0fc98c… stephan 263 ** add/rm/addremove commands, after a call to verify_all_options().
e0fc98c… stephan 264 **
e0fc98c… stephan 265 ** Un-added files are not modified but any un-rm'd files which are
bc36fdc… danield 266 ** missing from the check-out are restored from the repo. un-rm'd files
bc36fdc… danield 267 ** which exist in the check-out are left as-is, rather than restoring
e0fc98c… stephan 268 ** them using vfile_to_disk(), to avoid overwriting any local changes
e0fc98c… stephan 269 ** made to those files.
e0fc98c… stephan 270 */
e0fc98c… stephan 271 static void addremove_reset(int bIsAdd, int bDryRun, int bVerbose){
e0fc98c… stephan 272 int nReset = 0; /* # of entries which get reset */
e0fc98c… stephan 273 Stmt stmt; /* vfile loop query */
e0fc98c… stephan 274
e0fc98c… stephan 275 db_begin_transaction();
e0fc98c… stephan 276 db_prepare(&stmt, "SELECT id, pathname FROM vfile "
e0fc98c… stephan 277 "WHERE %s ORDER BY pathname",
e0fc98c… stephan 278 bIsAdd==0 ? "deleted<>0" : "rid=0"/*safe-for-%s*/);
e0fc98c… stephan 279 while( db_step(&stmt)==SQLITE_ROW ){
e0fc98c… stephan 280 /* This loop exists only so we can restore the contents of un-rm'd
e0fc98c… stephan 281 ** files and support verbose mode. All manipulation of vfile's
e0fc98c… stephan 282 ** contents happens after the loop. For the ADD case in non-verbose
e0fc98c… stephan 283 ** mode we "could" skip this loop entirely.
e0fc98c… stephan 284 */
e0fc98c… stephan 285 int const id = db_column_int(&stmt, 0);
e0fc98c… stephan 286 char const * zPathname = db_column_text(&stmt, 1);
e0fc98c… stephan 287 Blob relName = empty_blob;
e0fc98c… stephan 288 if(bIsAdd==0 || bVerbose!=0){
e0fc98c… stephan 289 /* Make filename relative... */
e0fc98c… stephan 290 char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname);
e0fc98c… stephan 291 file_relative_name(zFullName, &relName, 0);
e0fc98c… stephan 292 fossil_free(zFullName);
e0fc98c… stephan 293 }
e0fc98c… stephan 294 if(bIsAdd==0){
e0fc98c… stephan 295 /* Restore contents of missing un-rm'd files. We don't do this
e0fc98c… stephan 296 ** unconditionally because we might cause data loss if a file
e0fc98c… stephan 297 ** is modified, rm'd, then un-rm'd.
e0fc98c… stephan 298 */
e0fc98c… stephan 299 ++nReset;
e0fc98c… stephan 300 if(!file_isfile_or_link(blob_str(&relName))){
e0fc98c… stephan 301 if(bDryRun==0){
e0fc98c… stephan 302 vfile_to_disk(0, id, 0, 0);
e0fc98c… stephan 303 if(bVerbose){
e0fc98c… stephan 304 fossil_print("Restored missing file: %b\n", &relName);
e0fc98c… stephan 305 }
e0fc98c… stephan 306 }else{
e0fc98c… stephan 307 fossil_print("Dry-run: not restoring missing file: %b\n", &relName);
e0fc98c… stephan 308 }
e0fc98c… stephan 309 }
e0fc98c… stephan 310 if(bVerbose){
e0fc98c… stephan 311 fossil_print("Un-removed: %b\n", &relName);
e0fc98c… stephan 312 }
e0fc98c… stephan 313 }else{
e0fc98c… stephan 314 /* un-add... */
e0fc98c… stephan 315 ++nReset;
e0fc98c… stephan 316 if(bVerbose){
e0fc98c… stephan 317 fossil_print("Un-added: %b\n", &relName);
e0fc98c… stephan 318 }
e0fc98c… stephan 319 }
e0fc98c… stephan 320 blob_reset(&relName);
e0fc98c… stephan 321 }
e0fc98c… stephan 322 db_finalize(&stmt);
e0fc98c… stephan 323 if(nReset>0){
e0fc98c… stephan 324 if(bIsAdd==0){
e0fc98c… stephan 325 if(bDryRun==0){
e0fc98c… stephan 326 db_exec_sql("UPDATE vfile SET deleted=0 WHERE deleted<>0");
e0fc98c… stephan 327 }
e0fc98c… stephan 328 fossil_print("Un-removed %d file(s).\n", nReset);
e0fc98c… stephan 329 }else{
e0fc98c… stephan 330 if(bDryRun==0){
e0fc98c… stephan 331 db_exec_sql("DELETE FROM vfile WHERE rid=0");
e0fc98c… stephan 332 }
e0fc98c… stephan 333 fossil_print("Un-added %d file(s).\n", nReset);
e0fc98c… stephan 334 }
e0fc98c… stephan 335 }
e0fc98c… stephan 336 db_end_transaction(bDryRun ? 1 : 0);
e0fc98c… stephan 337 }
e0fc98c… stephan 338
e0fc98c… stephan 339
e0fc98c… stephan 340 /*
dbda8d6… drh 341 ** COMMAND: add
dbda8d6… drh 342 **
b0d1510… drh 343 ** Usage: %fossil add ?OPTIONS? FILE1 ?FILE2 ...?
b0d1510… drh 344 **
b0d1510… drh 345 ** Make arrangements to add one or more files or directories to the
bc36fdc… danield 346 ** current check-out at the next [[commit]].
b0d1510… drh 347 **
b0d1510… drh 348 ** When adding files or directories recursively, filenames that begin
b0d1510… drh 349 ** with "." are excluded by default. To include such files, add
b0d1510… drh 350 ** the "--dotfiles" option to the command-line.
b0d1510… drh 351 **
862d630… drh 352 ** The --ignore and --clean options are comma-separated lists of glob patterns
155acff… mistachkin 353 ** for files to be excluded. Example: '*.o,*.obj,*.exe' If the --ignore
155acff… mistachkin 354 ** option does not appear on the command line then the "ignore-glob" setting
155acff… mistachkin 355 ** is used. If the --clean option does not appear on the command line then
155acff… mistachkin 356 ** the "clean-glob" setting is used.
6ec21b5… jan.nijtmans 357 **
e2bdc10… danield 358 ** When attempting to explicitly add files on the command line, and if those
6ec21b5… jan.nijtmans 359 ** match "ignore-glob", a confirmation is asked first. This can be prevented
6ec21b5… jan.nijtmans 360 ** using the -f|--force option.
5f6b495… drh 361 **
5f6b495… drh 362 ** The --case-sensitive option determines whether or not filenames should
5f6b495… drh 363 ** be treated case sensitive or not. If the option is not given, the default
5f6b495… drh 364 ** depends on the global setting, or the operating system default, if not set.
2210be1… drh 365 **
2210be1… drh 366 ** Options:
4cb50c4… stephan 367 ** --case-sensitive BOOL Override the case-sensitive setting
4cb50c4… stephan 368 ** --dotfiles Include files beginning with a dot (".")
6ec21b5… jan.nijtmans 369 ** -f|--force Add files without prompting
e58c76a… drh 370 ** --ignore CSG Ignore unmanaged files matching patterns from
e58c76a… drh 371 ** the Comma Separated Glob (CSG) pattern list
e58c76a… drh 372 ** --clean CSG Also ignore files matching patterns from
e58c76a… drh 373 ** the Comma Separated Glob (CSG) list
bc36fdc… danield 374 ** --reset Reset the ADDED state of a check-out, such
e0fc98c… stephan 375 ** that all newly-added (but not yet committed)
e0fc98c… stephan 376 ** files are no longer added. No flags other
e0fc98c… stephan 377 ** than --verbose and --dry-run may be used
e0fc98c… stephan 378 ** with --reset.
922b5c4… drh 379 ** --allow-reserved Permit filenames which are reserved on
922b5c4… drh 380 ** Windows platforms. Such files cannot be
922b5c4… drh 381 ** checked out on Windows, so use with care.
e0fc98c… stephan 382 **
e0fc98c… stephan 383 ** The following options are only valid with --reset:
4cb50c4… stephan 384 ** -v|--verbose Output information about each --reset file
4cb50c4… stephan 385 ** -n|--dry-run Display instead of run actions
4e18dba… jan.nijtmans 386 **
c965636… drh 387 ** See also: [[addremove]], [[rm]]
dbda8d6… drh 388 */
dbda8d6… drh 389 void add_cmd(void){
8ae9173… drh 390 int i; /* Loop counter */
bc36fdc… danield 391 int vid; /* Currently checked-out version */
8ae9173… drh 392 int nRoot; /* Full path characters in g.zLocalRoot */
155acff… mistachkin 393 const char *zCleanFlag; /* The --clean option or clean-glob setting */
8ae9173… drh 394 const char *zIgnoreFlag; /* The --ignore option or ignore-glob setting */
155acff… mistachkin 395 Glob *pIgnore, *pClean; /* Ignore everything matching the glob patterns */
3206b64… drh 396 unsigned scanFlags = 0; /* Flags passed to vfile_scan() */
6ec21b5… jan.nijtmans 397 int forceFlag;
922b5c4… drh 398 int allowReservedFlag = 0; /* --allow-reserved flag */
e0fc98c… stephan 399
e0fc98c… stephan 400 if(0!=find_option("reset",0,0)){
e0fc98c… stephan 401 int const verboseFlag = find_option("verbose","v",0)!=0;
e0fc98c… stephan 402 int const dryRunFlag = find_option("dry-run","n",0)!=0;
e0fc98c… stephan 403 db_must_be_within_tree();
e0fc98c… stephan 404 verify_all_options();
e0fc98c… stephan 405 addremove_reset(1, dryRunFlag, verboseFlag);
e0fc98c… stephan 406 return;
e0fc98c… stephan 407 }
be3d215… drh 408
155acff… mistachkin 409 zCleanFlag = find_option("clean",0,1);
be3d215… drh 410 zIgnoreFlag = find_option("ignore",0,1);
6ec21b5… jan.nijtmans 411 forceFlag = find_option("force","f",0)!=0;
3206b64… drh 412 if( find_option("dotfiles",0,0)!=0 ) scanFlags |= SCAN_ALL;
922b5c4… drh 413 allowReservedFlag = find_option("allow-reserved",0,0)!=0;
74ac0c9… drh 414
74ac0c9… drh 415 /* We should be done with options.. */
74ac0c9… drh 416 verify_all_options();
74ac0c9… drh 417
dbda8d6… drh 418 db_must_be_within_tree();
155acff… mistachkin 419 if( zCleanFlag==0 ){
155acff… mistachkin 420 zCleanFlag = db_get("clean-glob", 0);
155acff… mistachkin 421 }
be3d215… drh 422 if( zIgnoreFlag==0 ){
be3d215… drh 423 zIgnoreFlag = db_get("ignore-glob", 0);
dbda8d6… drh 424 }
e1e0ec5… drh 425 if( db_get_boolean("dotfiles", 0) ) scanFlags |= SCAN_ALL;
be3d215… drh 426 vid = db_lget_int("checkout",0);
e1962ef… drh 427 db_begin_transaction();
e776494… andygoth 428 db_multi_exec("CREATE TEMP TABLE sfile(pathname TEXT PRIMARY KEY %s)",
7ae19e5… jan.nijtmans 429 filename_collation());
155acff… mistachkin 430 pClean = glob_create(zCleanFlag);
8ae9173… drh 431 pIgnore = glob_create(zIgnoreFlag);
8ae9173… drh 432 nRoot = strlen(g.zLocalRoot);
4e18dba… jan.nijtmans 433
8ae9173… drh 434 /* Load the names of all files that are to be added into sfile temp table */
dbda8d6… drh 435 for(i=2; i<g.argc; i++){
dbda8d6… drh 436 char *zName;
8c4e72e… drh 437 int isDir;
922b5c4… drh 438 Blob fullName = empty_blob;
8c4e72e… drh 439
c6f32a2… drh 440 /* file_tree_name() throws a fatal error if g.argv[i] is outside of the
bc36fdc… danield 441 ** check-out. */
c56a387… mistachkin 442 file_tree_name(g.argv[i], &fullName, 0, 1);
c6f32a2… drh 443 blob_reset(&fullName);
135ed93… drh 444 file_canonical_name(g.argv[i], &fullName, 0);
8ae9173… drh 445 zName = blob_str(&fullName);
1772357… drh 446 isDir = file_isdir(zName, RepoFILE);
8c4e72e… drh 447 if( isDir==1 ){
a3bc655… drh 448 vfile_scan(&fullName, nRoot-1, scanFlags, pClean, pIgnore, RepoFILE);
8c4e72e… drh 449 }else if( isDir==0 ){
810976a… drh 450 fossil_warning("not found: %s", zName);
8c4e72e… drh 451 }else{
78e6399… drh 452 char *zTreeName = file_case_preferred_name(g.zLocalRoot,&zName[nRoot]);
6ec21b5… jan.nijtmans 453 if( !forceFlag && glob_match(pIgnore, zTreeName) ){
6ec21b5… jan.nijtmans 454 Blob ans;
6ec21b5… jan.nijtmans 455 char cReply;
6ec21b5… jan.nijtmans 456 char *prompt = mprintf("file \"%s\" matches \"ignore-glob\". "
6ec21b5… jan.nijtmans 457 "Add it (a=all/y/N)? ", zTreeName);
6ec21b5… jan.nijtmans 458 prompt_user(prompt, &ans);
e5e0940… stephan 459 fossil_free(prompt);
6ec21b5… jan.nijtmans 460 cReply = blob_str(&ans)[0];
6ec21b5… jan.nijtmans 461 blob_reset(&ans);
6ec21b5… jan.nijtmans 462 if( cReply=='a' || cReply=='A' ){
6ec21b5… jan.nijtmans 463 forceFlag = 1;
6ec21b5… jan.nijtmans 464 }else if( cReply!='y' && cReply!='Y' ){
6ec21b5… jan.nijtmans 465 blob_reset(&fullName);
6ec21b5… jan.nijtmans 466 continue;
6ec21b5… jan.nijtmans 467 }
6ec21b5… jan.nijtmans 468 }
8ae9173… drh 469 db_multi_exec(
e776494… andygoth 470 "INSERT OR IGNORE INTO sfile(pathname) VALUES(%Q)",
feed623… drh 471 zTreeName
8ae9173… drh 472 );
78e6399… drh 473 fossil_free(zTreeName);
8ae9173… drh 474 }
ed5c19c… drh 475 blob_reset(&fullName);
8ae9173… drh 476 }
8ae9173… drh 477 glob_free(pIgnore);
155acff… mistachkin 478 glob_free(pClean);
8ae9173… drh 479
d0a8582… stephan 480 /** Check for Windows-reserved names and warn or exit, as
e2bdc10… danield 481 ** appropriate. Note that the 'add' internal machinery already
d0a8582… stephan 482 ** _silently_ skips over any names for which
d0a8582… stephan 483 ** file_is_reserved_name() returns true or which is in the
d0a8582… stephan 484 ** fossil_reserved_name() list. We do not need to warn for those,
d0a8582… stephan 485 ** as they're outright verboten. */
d0a8582… stephan 486 if(db_exists("SELECT 1 FROM sfile WHERE win_reserved(pathname)")){
da9f362… ashepilko 487 int reservedCount = 0;
d0a8582… stephan 488 Stmt q = empty_Stmt;
d0a8582… stephan 489 db_prepare(&q,"SELECT pathname FROM sfile "
d0a8582… stephan 490 "WHERE win_reserved(pathname)");
d0a8582… stephan 491 while( db_step(&q)==SQLITE_ROW ){
d0a8582… stephan 492 const char * zName = db_column_text(&q, 0);
d0a8582… stephan 493 ++reservedCount;
d0a8582… stephan 494 if(allowReservedFlag){
d0a8582… stephan 495 fossil_warning("WARNING: Windows-reserved "
d0a8582… stephan 496 "filename: %s", zName);
d0a8582… stephan 497 }else{
d0a8582… stephan 498 fossil_warning("ERROR: Windows-reserved filename: %s", zName);
d0a8582… stephan 499 }
d0a8582… stephan 500 }
d0a8582… stephan 501 db_finalize(&q);
d0a8582… stephan 502 if(allowReservedFlag==0){
d0a8582… stephan 503 fossil_fatal("ERROR: %d Windows-reserved filename(s) added. "
d0a8582… stephan 504 "Use --allow-reserved to permit such names.",
d0a8582… stephan 505 reservedCount);
d0a8582… stephan 506 }
d0a8582… stephan 507 }
3c781f4… jan.nijtmans 508 add_files_in_sfile(vid);
8c4e72e… drh 509 db_end_transaction(0);
3c941dd… drh 510 }
3c941dd… drh 511
3c941dd… drh 512 /*
3c941dd… drh 513 ** This function adds a file to list of files to delete from disk after
3c941dd… drh 514 ** the other actions required for the parent operation have completed
3c941dd… drh 515 ** successfully. The first time it is called for the current process,
3c941dd… drh 516 ** it creates a temporary table named "fremove", to keep track of these
3c941dd… drh 517 ** files.
3c941dd… drh 518 */
3c941dd… drh 519 static void add_file_to_remove(
3c941dd… drh 520 const char *zOldName /* The old name of the file on disk. */
3c941dd… drh 521 ){
3c941dd… drh 522 static int tableCreated = 0;
3c941dd… drh 523 Blob fullOldName;
3c941dd… drh 524 if( !tableCreated ){
3c941dd… drh 525 db_multi_exec("CREATE TEMP TABLE fremove(x TEXT PRIMARY KEY %s)",
3c941dd… drh 526 filename_collation());
3c941dd… drh 527 tableCreated = 1;
3c941dd… drh 528 }
c56a387… mistachkin 529 file_tree_name(zOldName, &fullOldName, 1, 1);
3c941dd… drh 530 db_multi_exec("INSERT INTO fremove VALUES('%q');", blob_str(&fullOldName));
3c941dd… drh 531 blob_reset(&fullOldName);
3c941dd… drh 532 }
3c941dd… drh 533
3c941dd… drh 534 /*
bc36fdc… danield 535 ** This function deletes files from the check-out, using the file names
3c941dd… drh 536 ** contained in the temporary table "fremove". The temporary table is
3c941dd… drh 537 ** created on demand by the add_file_to_remove() function.
3c941dd… drh 538 **
3c941dd… drh 539 ** If dryRunFlag is non-zero, no files will be removed; however, their
3c941dd… drh 540 ** names will still be output.
3c941dd… drh 541 **
3c941dd… drh 542 ** The temporary table "fremove" is dropped after being processed.
3c941dd… drh 543 */
3c941dd… drh 544 static void process_files_to_remove(
3c941dd… drh 545 int dryRunFlag /* Zero to actually operate on the file-system. */
3c941dd… drh 546 ){
3c941dd… drh 547 Stmt remove;
06aec61… drh 548 if( db_table_exists("temp", "fremove") ){
c56a387… mistachkin 549 db_prepare(&remove, "SELECT x FROM fremove ORDER BY x;");
c56a387… mistachkin 550 while( db_step(&remove)==SQLITE_ROW ){
c56a387… mistachkin 551 const char *zOldName = db_column_text(&remove, 0);
c56a387… mistachkin 552 if( !dryRunFlag ){
c56a387… mistachkin 553 file_delete(zOldName);
c56a387… mistachkin 554 }
c56a387… mistachkin 555 fossil_print("DELETED_FILE %s\n", zOldName);
c56a387… mistachkin 556 }
c56a387… mistachkin 557 db_finalize(&remove);
c56a387… mistachkin 558 db_multi_exec("DROP TABLE fremove;");
c56a387… mistachkin 559 }
8cf976d… jan.nijtmans 560 }
8cf976d… jan.nijtmans 561
8cf976d… jan.nijtmans 562 /*
dbda8d6… drh 563 ** COMMAND: rm
8cf976d… jan.nijtmans 564 ** COMMAND: delete
8cf976d… jan.nijtmans 565 ** COMMAND: forget*
b0d1510… drh 566 **
8cf976d… jan.nijtmans 567 ** Usage: %fossil rm|delete|forget FILE1 ?FILE2 ...?
b0d1510… drh 568 **
b0d1510… drh 569 ** Remove one or more files or directories from the repository.
b0d1510… drh 570 **
3c941dd… drh 571 ** The 'rm' and 'delete' commands do NOT normally remove the files from
3c941dd… drh 572 ** disk. They just mark the files as no longer being part of the project.
3c941dd… drh 573 ** In other words, future changes to the named files will not be versioned.
9951fd7… mistachkin 574 ** However, the default behavior of this command may be overridden via the
9951fd7… mistachkin 575 ** command line options listed below and/or the 'mv-rm-files' setting.
3c941dd… drh 576 **
3c941dd… drh 577 ** The 'forget' command never removes files from disk, even when the command
3c941dd… drh 578 ** line options and/or the 'mv-rm-files' setting would otherwise require it
3c941dd… drh 579 ** to do so.
3c941dd… drh 580 **
9951fd7… mistachkin 581 ** WARNING: If the "--hard" option is specified -OR- the "mv-rm-files"
9951fd7… mistachkin 582 ** setting is non-zero, files WILL BE removed from disk as well.
9951fd7… mistachkin 583 ** This does NOT apply to the 'forget' command.
9951fd7… mistachkin 584 **
7ae19e5… jan.nijtmans 585 ** Options:
bc36fdc… danield 586 ** --soft Skip removing files from the check-out.
3c941dd… drh 587 ** This supersedes the --hard option.
2e56ef4… km 588 ** --hard Remove files from the check-out
2e56ef4… km 589 ** --case-sensitive BOOL Override the case-sensitive setting
3c941dd… drh 590 ** -n|--dry-run If given, display instead of run actions.
bc36fdc… danield 591 ** --reset Reset the DELETED state of a check-out, such
e0fc98c… stephan 592 ** that all newly-rm'd (but not yet committed)
e0fc98c… stephan 593 ** files are no longer removed. No flags other
e0fc98c… stephan 594 ** than --verbose or --dry-run may be used with
e0fc98c… stephan 595 ** --reset.
7f3c728… jamsek 596 ** -v|--verbose Outputs information about each --reset file.
e0fc98c… stephan 597 ** Only usable with --reset.
b0d1510… drh 598 **
c965636… drh 599 ** See also: [[addremove]], [[add]]
e146d80… drh 600 */
e3fb8dc… drh 601 void delete_cmd(void){
e146d80… drh 602 int i;
3c941dd… drh 603 int removeFiles;
e0fc98c… stephan 604 int dryRunFlag = find_option("dry-run","n",0)!=0;
86212ec… mistachkin 605 int softFlag;
86212ec… mistachkin 606 int hardFlag;
8ae9173… drh 607 Stmt loop;
3c941dd… drh 608
e0fc98c… stephan 609 if(0!=find_option("reset",0,0)){
e0fc98c… stephan 610 int const verboseFlag = find_option("verbose","v",0)!=0;
e0fc98c… stephan 611 db_must_be_within_tree();
e0fc98c… stephan 612 verify_all_options();
e0fc98c… stephan 613 addremove_reset(0, dryRunFlag, verboseFlag);
e0fc98c… stephan 614 return;
e0fc98c… stephan 615 }
e0fc98c… stephan 616
86212ec… mistachkin 617 softFlag = find_option("soft",0,0)!=0;
86212ec… mistachkin 618 hardFlag = find_option("hard",0,0)!=0;
4e18dba… jan.nijtmans 619
74ac0c9… drh 620 /* We should be done with options.. */
74ac0c9… drh 621 verify_all_options();
74ac0c9… drh 622
aef638b… jan.nijtmans 623 db_must_be_within_tree();
e1962ef… drh 624 db_begin_transaction();
3c941dd… drh 625 if( g.argv[1][0]=='f' ){ /* i.e. "forget" */
3c941dd… drh 626 removeFiles = 0;
86212ec… mistachkin 627 }else if( softFlag ){
86212ec… mistachkin 628 removeFiles = 0;
86212ec… mistachkin 629 }else if( hardFlag ){
86212ec… mistachkin 630 removeFiles = 1;
3c941dd… drh 631 }else{
3c941dd… drh 632 removeFiles = db_get_boolean("mv-rm-files",0);
3c941dd… drh 633 }
e776494… andygoth 634 db_multi_exec("CREATE TEMP TABLE sfile(pathname TEXT PRIMARY KEY %s)",
7ae19e5… jan.nijtmans 635 filename_collation());
e146d80… drh 636 for(i=2; i<g.argc; i++){
8ae9173… drh 637 Blob treeName;
8ae9173… drh 638 char *zTreeName;
8ae9173… drh 639
c56a387… mistachkin 640 file_tree_name(g.argv[i], &treeName, 0, 1);
8ae9173… drh 641 zTreeName = blob_str(&treeName);
8ae9173… drh 642 db_multi_exec(
8ae9173… drh 643 "INSERT OR IGNORE INTO sfile"
8ae9173… drh 644 " SELECT pathname FROM vfile"
7ae19e5… jan.nijtmans 645 " WHERE (pathname=%Q %s"
fa6311a… jan.nijtmans 646 " OR (pathname>'%q/' %s AND pathname<'%q0' %s))"
8ae9173… drh 647 " AND NOT deleted",
fa6311a… jan.nijtmans 648 zTreeName, filename_collation(), zTreeName,
fa6311a… jan.nijtmans 649 filename_collation(), zTreeName, filename_collation()
8ae9173… drh 650 );
8ae9173… drh 651 blob_reset(&treeName);
8ae9173… drh 652 }
4e18dba… jan.nijtmans 653
e776494… andygoth 654 db_prepare(&loop, "SELECT pathname FROM sfile");
8ae9173… drh 655 while( db_step(&loop)==SQLITE_ROW ){
d8ec765… drh 656 fossil_print("DELETED %s\n", db_column_text(&loop, 0));
3c941dd… drh 657 if( removeFiles ) add_file_to_remove(db_column_text(&loop, 0));
8ae9173… drh 658 }
8ae9173… drh 659 db_finalize(&loop);
3c941dd… drh 660 if( !dryRunFlag ){
3c941dd… drh 661 db_multi_exec(
3c941dd… drh 662 "UPDATE vfile SET deleted=1 WHERE pathname IN sfile;"
3c941dd… drh 663 "DELETE FROM vfile WHERE rid=0 AND deleted;"
3c941dd… drh 664 );
3c941dd… drh 665 }
e146d80… drh 666 db_end_transaction(0);
3c941dd… drh 667 if( removeFiles ) process_files_to_remove(dryRunFlag);
874d0ca… drh 668 }
874d0ca… drh 669
874d0ca… drh 670 /*
874d0ca… drh 671 ** Capture the command-line --case-sensitive option.
874d0ca… drh 672 */
874d0ca… drh 673 static const char *zCaseSensitive = 0;
874d0ca… drh 674 void capture_case_sensitive_option(void){
874d0ca… drh 675 if( zCaseSensitive==0 ){
874d0ca… drh 676 zCaseSensitive = find_option("case-sensitive",0,1);
874d0ca… drh 677 }
874d0ca… drh 678 }
874d0ca… drh 679
874d0ca… drh 680 /*
874d0ca… drh 681 ** This routine determines if files should be case-sensitive or not.
874d0ca… drh 682 ** In other words, this routine determines if two filenames that
874d0ca… drh 683 ** differ only in case should be considered the same name or not.
874d0ca… drh 684 **
874d0ca… drh 685 ** The case-sensitive setting determines the default value. If
874d0ca… drh 686 ** the case-sensitive setting is undefined, then case sensitivity
68f8aaf… jan.nijtmans 687 ** defaults off for Cygwin, Mac and Windows and on for all other unix.
9359b41… jan.nijtmans 688 ** If case-sensitivity is enabled in the windows kernel, the Cygwin port
9359b41… jan.nijtmans 689 ** of fossil.exe can detect that, and modifies the default to 'on'.
874d0ca… drh 690 **
11384f1… drh 691 ** The "--case-sensitive BOOL" command-line option overrides any
874d0ca… drh 692 ** setting.
874d0ca… drh 693 */
874d0ca… drh 694 int filenames_are_case_sensitive(void){
9c90b0f… drh 695 static int caseSensitive;
9c90b0f… drh 696 static int once = 1;
874d0ca… drh 697
9c90b0f… drh 698 if( once ){
9c90b0f… drh 699 once = 0;
9c90b0f… drh 700 if( zCaseSensitive ){
9c90b0f… drh 701 caseSensitive = is_truth(zCaseSensitive);
9c90b0f… drh 702 }else{
9359b41… jan.nijtmans 703 #if defined(_WIN32) || defined(__DARWIN__) || defined(__APPLE__)
9359b41… jan.nijtmans 704 caseSensitive = 0; /* Mac and Windows */
9359b41… jan.nijtmans 705 #elif defined(__CYGWIN__)
9359b41… jan.nijtmans 706 /* Cygwin can be configured to be case-sensitive, check this. */
9359b41… jan.nijtmans 707 void *hKey;
9359b41… jan.nijtmans 708 int value = 1, length = sizeof(int);
9359b41… jan.nijtmans 709 caseSensitive = 0; /* Cygwin default */
9359b41… jan.nijtmans 710 if( (RegOpenKeyExW((void *)0x80000002, L"SYSTEM\\CurrentControlSet\\"
9359b41… jan.nijtmans 711 "Control\\Session Manager\\kernel", 0, 1, (void *)&hKey)
9359b41… jan.nijtmans 712 == 0) && (RegQueryValueExW(hKey, L"obcaseinsensitive",
9359b41… jan.nijtmans 713 0, NULL, (void *)&value, (void *)&length) == 0) && !value ){
9359b41… jan.nijtmans 714 caseSensitive = 1;
9359b41… jan.nijtmans 715 }
874d0ca… drh 716 #else
9359b41… jan.nijtmans 717 caseSensitive = 1; /* Unix */
874d0ca… drh 718 #endif
9c90b0f… drh 719 caseSensitive = db_get_boolean("case-sensitive",caseSensitive);
9359b41… jan.nijtmans 720 }
30da8e8… drh 721 if( !caseSensitive && g.localOpen ){
3c781f4… jan.nijtmans 722 db_multi_exec(
06aec61… drh 723 "CREATE INDEX IF NOT EXISTS localdb.vfile_nocase"
06aec61… drh 724 " ON vfile(pathname COLLATE nocase)"
3c781f4… jan.nijtmans 725 );
3c781f4… jan.nijtmans 726 }
874d0ca… drh 727 }
874d0ca… drh 728 return caseSensitive;
9c90b0f… drh 729 }
9c90b0f… drh 730
9c90b0f… drh 731 /*
9c90b0f… drh 732 ** Return one of two things:
9c90b0f… drh 733 **
9c90b0f… drh 734 ** "" (empty string) if filenames are case sensitive
9c90b0f… drh 735 **
9c90b0f… drh 736 ** "COLLATE nocase" if filenames are not case sensitive.
9c90b0f… drh 737 */
9c90b0f… drh 738 const char *filename_collation(void){
9c90b0f… drh 739 return filenames_are_case_sensitive() ? "" : "COLLATE nocase";
2210be1… drh 740 }
2210be1… drh 741
2210be1… drh 742 /*
ceab537… drh 743 ** COMMAND: addremove
ceab537… drh 744 **
2210be1… drh 745 ** Usage: %fossil addremove ?OPTIONS?
2210be1… drh 746 **
c965636… drh 747 ** Do all necessary "[[add]]" and "[[rm]]" commands to synchronize the
bc36fdc… danield 748 ** repository with the content of the working check-out:
7afbb70… mistachkin 749 **
bc36fdc… danield 750 ** * All files in the check-out but not in the repository (that is,
7afbb70… mistachkin 751 ** all files displayed using the "extras" command) are added as
c965636… drh 752 ** if by the "[[add]]" command.
7afbb70… mistachkin 753 **
bc36fdc… danield 754 ** * All files in the repository but missing from the check-out (that is,
ceab537… drh 755 ** all files that show as MISSING with the "status" command) are
c965636… drh 756 ** removed as if by the "[[rm]]" command.
ceab537… drh 757 **
3d2f188… brickviking 758 ** Note that this command does not "commit", as that is a separate step.
ceab537… drh 759 **
ceab537… drh 760 ** Files and directories whose names begin with "." are ignored unless
ceab537… drh 761 ** the --dotfiles option is used.
ceab537… drh 762 **
155acff… mistachkin 763 ** The --ignore option overrides the "ignore-glob" setting, as do the
155acff… mistachkin 764 ** --case-sensitive option with the "case-sensitive" setting and the
155acff… mistachkin 765 ** --clean option with the "clean-glob" setting. See the documentation
155acff… mistachkin 766 ** on the "settings" command for further information.
ceab537… drh 767 **
a97404e… mistachkin 768 ** The -n|--dry-run option shows what would happen without actually doing
a97404e… mistachkin 769 ** anything.
ceab537… drh 770 **
ceab537… drh 771 ** This command can be used to track third party software.
4e18dba… jan.nijtmans 772 **
4e18dba… jan.nijtmans 773 ** Options:
2e56ef4… km 774 ** --case-sensitive BOOL Override the case-sensitive setting
a97404e… mistachkin 775 ** --dotfiles Include files beginning with a dot (".")
e58c76a… drh 776 ** --ignore CSG Ignore unmanaged files matching patterns from
e58c76a… drh 777 ** the Comma Separated Glob (CSG) list
e58c76a… drh 778 ** --clean CSG Also ignore files matching patterns from
e58c76a… drh 779 ** the Comma Separated Glob (CSG) list
2e56ef4… km 780 ** -n|--dry-run If given, display instead of run actions
bc36fdc… danield 781 ** --reset Reset the ADDED/DELETED state of a check-out,
e0fc98c… stephan 782 ** such that all newly-added (but not yet committed)
e0fc98c… stephan 783 ** files are no longer added and all newly-removed
e0fc98c… stephan 784 ** (but not yet committed) files are no longer
e0fc98c… stephan 785 ** removed. No flags other than --verbose and
e0fc98c… stephan 786 ** --dry-run may be used with --reset.
7f3c728… jamsek 787 ** -v|--verbose Outputs information about each --reset file.
e0fc98c… stephan 788 ** Only usable with --reset.
0b86639… jan.nijtmans 789 **
c965636… drh 790 ** See also: [[add]], [[rm]]
ceab537… drh 791 */
874d0ca… drh 792 void addremove_cmd(void){
ceab537… drh 793 Blob path;
e0fc98c… stephan 794 const char *zCleanFlag;
e0fc98c… stephan 795 const char *zIgnoreFlag;
e0fc98c… stephan 796 unsigned scanFlags;
0b86639… jan.nijtmans 797 int dryRunFlag = find_option("dry-run","n",0)!=0;
ceab537… drh 798 int n;
ceab537… drh 799 Stmt q;
ceab537… drh 800 int vid;
ceab537… drh 801 int nAdd = 0;
ceab537… drh 802 int nDelete = 0;
155acff… mistachkin 803 Glob *pIgnore, *pClean;
0b86639… jan.nijtmans 804
0b86639… jan.nijtmans 805 if( !dryRunFlag ){
0b86639… jan.nijtmans 806 dryRunFlag = find_option("test",0,0)!=0; /* deprecated */
0b86639… jan.nijtmans 807 }
0c51600… mistachkin 808
e0fc98c… stephan 809 if(0!=find_option("reset",0,0)){
e0fc98c… stephan 810 int const verboseFlag = find_option("verbose","v",0)!=0;
e0fc98c… stephan 811 db_must_be_within_tree();
e0fc98c… stephan 812 verify_all_options();
e0fc98c… stephan 813 addremove_reset(0, dryRunFlag, verboseFlag);
e0fc98c… stephan 814 addremove_reset(1, dryRunFlag, verboseFlag);
e0fc98c… stephan 815 return;
e0fc98c… stephan 816 }
e0fc98c… stephan 817
e0fc98c… stephan 818 zCleanFlag = find_option("clean",0,1);
e0fc98c… stephan 819 zIgnoreFlag = find_option("ignore",0,1);
e0fc98c… stephan 820 scanFlags = find_option("dotfiles",0,0)!=0 ? SCAN_ALL : 0;
e0fc98c… stephan 821
74ac0c9… drh 822 /* We should be done with options.. */
74ac0c9… drh 823 verify_all_options();
74ac0c9… drh 824
975600d… mgagnon 825 /* Fail if unprocessed arguments are present, in case user expect the
33c44fa… jan.nijtmans 826 ** addremove command to accept a list of file or directory.
975600d… mgagnon 827 */
975600d… mgagnon 828 if( g.argc>2 ){
975600d… mgagnon 829 fossil_fatal(
bc36fdc… danield 830 "%s: Can only work on the entire check-out, no arguments supported.",
975600d… mgagnon 831 g.argv[1]);
975600d… mgagnon 832 }
356e877… drh 833 db_must_be_within_tree();
155acff… mistachkin 834 if( zCleanFlag==0 ){
155acff… mistachkin 835 zCleanFlag = db_get("clean-glob", 0);
155acff… mistachkin 836 }
ceab537… drh 837 if( zIgnoreFlag==0 ){
ceab537… drh 838 zIgnoreFlag = db_get("ignore-glob", 0);
ceab537… drh 839 }
e1e0ec5… drh 840 if( db_get_boolean("dotfiles", 0) ) scanFlags |= SCAN_ALL;
ceab537… drh 841 vid = db_lget_int("checkout",0);
e1962ef… drh 842 db_begin_transaction();
8ae9173… drh 843
4e18dba… jan.nijtmans 844 /* step 1:
db0c512… drh 845 ** Populate the temp table "sfile" with the names of all unmanaged
8ae9173… drh 846 ** files currently in the check-out, except for files that match the
8ae9173… drh 847 ** --ignore or ignore-glob patterns and dot-files. Then add all of
8ae9173… drh 848 ** the files in the sfile temp table to the set of managed files.
8ae9173… drh 849 */
e776494… andygoth 850 db_multi_exec("CREATE TEMP TABLE sfile(pathname TEXT PRIMARY KEY %s)",
7ae19e5… jan.nijtmans 851 filename_collation());
ceab537… drh 852 n = strlen(g.zLocalRoot);
ceab537… drh 853 blob_init(&path, g.zLocalRoot, n-1);
ceab537… drh 854 /* now we read the complete file structure into a temp table */
155acff… mistachkin 855 pClean = glob_create(zCleanFlag);
8ae9173… drh 856 pIgnore = glob_create(zIgnoreFlag);
a3bc655… drh 857 vfile_scan(&path, blob_size(&path), scanFlags, pClean, pIgnore, RepoFILE);
8ae9173… drh 858 glob_free(pIgnore);
155acff… mistachkin 859 glob_free(pClean);
3c781f4… jan.nijtmans 860 nAdd = add_files_in_sfile(vid);
8ae9173… drh 861
ceab537… drh 862 /* step 2: search for missing files */
b0d1510… drh 863 db_prepare(&q,
8ae9173… drh 864 "SELECT pathname, %Q || pathname, deleted FROM vfile"
8ae9173… drh 865 " WHERE NOT deleted"
ceab537… drh 866 " ORDER BY 1",
ceab537… drh 867 g.zLocalRoot
ceab537… drh 868 );
ceab537… drh 869 while( db_step(&q)==SQLITE_ROW ){
4e18dba… jan.nijtmans 870 const char *zFile;
4e18dba… jan.nijtmans 871 const char *zPath;
ceab537… drh 872
ceab537… drh 873 zFile = db_column_text(&q, 0);
ceab537… drh 874 zPath = db_column_text(&q, 1);
1772357… drh 875 if( !file_isfile_or_link(zPath) ){
0b86639… jan.nijtmans 876 if( !dryRunFlag ){
ceab537… drh 877 db_multi_exec("UPDATE vfile SET deleted=1 WHERE pathname=%Q", zFile);
ceab537… drh 878 }
d8ec765… drh 879 fossil_print("DELETED %s\n", zFile);
ceab537… drh 880 nDelete++;
ceab537… drh 881 }
ceab537… drh 882 }
ceab537… drh 883 db_finalize(&q);
db0c512… drh 884 /* show command summary */
d8ec765… drh 885 fossil_print("added %d files, deleted %d files\n", nAdd, nDelete);
ef14017… stephan 886 if(dryRunFlag!=0){
ef14017… stephan 887 fossil_print("Dry-run mode: no changes were made.\n");
ef14017… stephan 888 }
0b86639… jan.nijtmans 889 db_end_transaction(dryRunFlag);
e146d80… drh 890 }
e146d80… drh 891
e146d80… drh 892 /*
b9d3b42… drh 893 ** Rename a single file.
e146d80… drh 894 **
e146d80… drh 895 ** The original name of the file is zOrig. The new filename is zNew.
e146d80… drh 896 */
a97404e… mistachkin 897 static void mv_one_file(
a97404e… mistachkin 898 int vid,
a97404e… mistachkin 899 const char *zOrig,
3c941dd… drh 900 const char *zNew,
31e75c3… danield 901 int dryRunFlag,
31e75c3… danield 902 int moveFiles
a97404e… mistachkin 903 ){
93f370a… jan.nijtmans 904 int x = db_int(-1, "SELECT deleted FROM vfile WHERE pathname=%Q %s",
b3e32c8… jan.nijtmans 905 zNew, filename_collation());
14fdae7… drh 906 if( x>=0 ){
14fdae7… drh 907 if( x==0 ){
fd2dbf4… drh 908 if( !filenames_are_case_sensitive() && fossil_stricmp(zOrig,zNew)==0 ){
fd2dbf4… drh 909 /* Case change only */
fd2dbf4… drh 910 }else{
fd2dbf4… drh 911 fossil_fatal("cannot rename '%s' to '%s' since another file named '%s'"
fd2dbf4… drh 912 " is currently under management", zOrig, zNew, zNew);
fd2dbf4… drh 913 }
14fdae7… drh 914 }else{
14fdae7… drh 915 fossil_fatal("cannot rename '%s' to '%s' since the delete of '%s' has "
14fdae7… drh 916 "not yet been committed", zOrig, zNew, zNew);
31e75c3… danield 917 }
31e75c3… danield 918 }
31e75c3… danield 919 if( moveFiles ){
31e75c3… danield 920 if( file_size(zNew, ExtFILE) != -1 ){
31e75c3… danield 921 fossil_fatal("cannot rename '%s' to '%s' on disk since another file"
31e75c3… danield 922 " named '%s' already exists", zOrig, zNew, zNew);
3c941dd… drh 923 }
3c941dd… drh 924 }
d8ec765… drh 925 fossil_print("RENAME %s %s\n", zOrig, zNew);
3c941dd… drh 926 if( !dryRunFlag ){
3c941dd… drh 927 db_multi_exec(
3c941dd… drh 928 "UPDATE vfile SET pathname='%q' WHERE pathname='%q' %s AND vid=%d",
3c941dd… drh 929 zNew, zOrig, filename_collation(), vid
3c941dd… drh 930 );
3c941dd… drh 931 }
3c941dd… drh 932 }
3c941dd… drh 933
3c941dd… drh 934 /*
3c941dd… drh 935 ** This function adds a file to list of files to move on disk after the
3c941dd… drh 936 ** other actions required for the parent operation have completed
3c941dd… drh 937 ** successfully. The first time it is called for the current process,
3c941dd… drh 938 ** it creates a temporary table named "fmove", to keep track of these
3c941dd… drh 939 ** files.
3c941dd… drh 940 */
3c941dd… drh 941 static void add_file_to_move(
3c941dd… drh 942 const char *zOldName, /* The old name of the file on disk. */
3c941dd… drh 943 const char *zNewName /* The new name of the file on disk. */
3c941dd… drh 944 ){
3c941dd… drh 945 static int tableCreated = 0;
3c941dd… drh 946 Blob fullOldName;
3c941dd… drh 947 Blob fullNewName;
fd2dbf4… drh 948 char *zOld, *zNew;
3c941dd… drh 949 if( !tableCreated ){
3c941dd… drh 950 db_multi_exec("CREATE TEMP TABLE fmove(x TEXT PRIMARY KEY %s, y TEXT %s)",
3c941dd… drh 951 filename_collation(), filename_collation());
3c941dd… drh 952 tableCreated = 1;
3c941dd… drh 953 }
c56a387… mistachkin 954 file_tree_name(zOldName, &fullOldName, 1, 1);
fd2dbf4… drh 955 zOld = blob_str(&fullOldName);
c56a387… mistachkin 956 file_tree_name(zNewName, &fullNewName, 1, 1);
fd2dbf4… drh 957 zNew = blob_str(&fullNewName);
fd2dbf4… drh 958 if( filenames_are_case_sensitive() || fossil_stricmp(zOld,zNew)!=0 ){
fd2dbf4… drh 959 db_multi_exec("INSERT INTO fmove VALUES('%q','%q');", zOld, zNew);
fd2dbf4… drh 960 }
3c941dd… drh 961 blob_reset(&fullNewName);
3c941dd… drh 962 blob_reset(&fullOldName);
3c941dd… drh 963 }
3c941dd… drh 964
3c941dd… drh 965 /*
bc36fdc… danield 966 ** This function moves files within the check-out, using the file names
3c941dd… drh 967 ** contained in the temporary table "fmove". The temporary table is
3c941dd… drh 968 ** created on demand by the add_file_to_move() function.
3c941dd… drh 969 **
3c941dd… drh 970 ** If dryRunFlag is non-zero, no files will be moved; however, their
3c941dd… drh 971 ** names will still be output.
3c941dd… drh 972 **
3c941dd… drh 973 ** The temporary table "fmove" is dropped after being processed.
3c941dd… drh 974 */
3c941dd… drh 975 static void process_files_to_move(
3c941dd… drh 976 int dryRunFlag /* Zero to actually operate on the file-system. */
3c941dd… drh 977 ){
3c941dd… drh 978 Stmt move;
06aec61… drh 979 if( db_table_exists("temp", "fmove") ){
c56a387… mistachkin 980 db_prepare(&move, "SELECT x, y FROM fmove ORDER BY x;");
c56a387… mistachkin 981 while( db_step(&move)==SQLITE_ROW ){
c56a387… mistachkin 982 const char *zOldName = db_column_text(&move, 0);
c56a387… mistachkin 983 const char *zNewName = db_column_text(&move, 1);
c56a387… mistachkin 984 if( !dryRunFlag ){
1772357… drh 985 int isOldDir = file_isdir(zOldName, RepoFILE);
1f694e1… mistachkin 986 if( isOldDir==1 ){
1772357… drh 987 int isNewDir = file_isdir(zNewName, RepoFILE);
1f694e1… mistachkin 988 if( isNewDir==0 ){
1f694e1… mistachkin 989 file_rename(zOldName, zNewName, isOldDir, isNewDir);
1f694e1… mistachkin 990 }
c56a387… mistachkin 991 }else{
1772357… drh 992 if( file_islink(zOldName) ){
1f694e1… mistachkin 993 symlink_copy(zOldName, zNewName);
1f694e1… mistachkin 994 }else{
1f694e1… mistachkin 995 file_copy(zOldName, zNewName);
1f694e1… mistachkin 996 }
1f694e1… mistachkin 997 file_delete(zOldName);
c56a387… mistachkin 998 }
c56a387… mistachkin 999 }
c56a387… mistachkin 1000 fossil_print("MOVED_FILE %s\n", zOldName);
c56a387… mistachkin 1001 }
c56a387… mistachkin 1002 db_finalize(&move);
c56a387… mistachkin 1003 db_multi_exec("DROP TABLE fmove;");
c56a387… mistachkin 1004 }
e146d80… drh 1005 }
e146d80… drh 1006
e146d80… drh 1007 /*
e146d80… drh 1008 ** COMMAND: mv
841772c… drh 1009 ** COMMAND: rename*
b0d1510… drh 1010 **
8725737… danield 1011 ** Usage: %fossil mv|rename ?OPTIONS? OLDNAME NEWNAME
8725737… danield 1012 ** or: %fossil mv|rename ?OPTIONS? OLDNAME... DIR
b0d1510… drh 1013 **
b0d1510… drh 1014 ** Move or rename one or more files or directories within the repository tree.
b0d1510… drh 1015 ** You can either rename a file or directory or move it to another subdirectory.
b0d1510… drh 1016 **
3c941dd… drh 1017 ** The 'mv' command does NOT normally rename or move the files on disk.
3c941dd… drh 1018 ** This command merely records the fact that file names have changed so
c965636… drh 1019 ** that appropriate notations can be made at the next [[commit]].
9951fd7… mistachkin 1020 ** However, the default behavior of this command may be overridden via
9951fd7… mistachkin 1021 ** command line options listed below and/or the 'mv-rm-files' setting.
3c941dd… drh 1022 **
3c941dd… drh 1023 ** The 'rename' command never renames or moves files on disk, even when the
3c941dd… drh 1024 ** command line options and/or the 'mv-rm-files' setting would otherwise
3c941dd… drh 1025 ** require it to do so.
3c941dd… drh 1026 **
9951fd7… mistachkin 1027 ** WARNING: If the "--hard" option is specified -OR- the "mv-rm-files"
9951fd7… mistachkin 1028 ** setting is non-zero, files WILL BE renamed or moved on disk
9951fd7… mistachkin 1029 ** as well. This does NOT apply to the 'rename' command.
9951fd7… mistachkin 1030 **
93f370a… jan.nijtmans 1031 ** Options:
bc36fdc… danield 1032 ** --soft Skip moving files within the check-out.
c965636… drh 1033 ** This supersedes the --hard option.
bc36fdc… danield 1034 ** --hard Move files within the check-out
4cb50c4… stephan 1035 ** --case-sensitive BOOL Override the case-sensitive setting
4cb50c4… stephan 1036 ** -n|--dry-run If given, display instead of run actions
b0d1510… drh 1037 **
c965636… drh 1038 ** See also: [[changes]], [[status]]
dbda8d6… drh 1039 */
e146d80… drh 1040 void mv_cmd(void){
dbda8d6… drh 1041 int i;
dbda8d6… drh 1042 int vid;
3c941dd… drh 1043 int moveFiles;
3c941dd… drh 1044 int dryRunFlag;
86212ec… mistachkin 1045 int softFlag;
86212ec… mistachkin 1046 int hardFlag;
0a34967… drh 1047 int origType;
0a34967… drh 1048 int destType;
e146d80… drh 1049 char *zDest;
e146d80… drh 1050 Blob dest;
e146d80… drh 1051 Stmt q;
dbda8d6… drh 1052
dbda8d6… drh 1053 db_must_be_within_tree();
3c941dd… drh 1054 dryRunFlag = find_option("dry-run","n",0)!=0;
86212ec… mistachkin 1055 softFlag = find_option("soft",0,0)!=0;
86212ec… mistachkin 1056 hardFlag = find_option("hard",0,0)!=0;
4e18dba… jan.nijtmans 1057
74ac0c9… drh 1058 /* We should be done with options.. */
74ac0c9… drh 1059 verify_all_options();
74ac0c9… drh 1060
dbda8d6… drh 1061 vid = db_lget_int("checkout", 0);
dbda8d6… drh 1062 if( vid==0 ){
bc36fdc… danield 1063 fossil_fatal("no check-out in which to rename files");
e146d80… drh 1064 }
e146d80… drh 1065 if( g.argc<4 ){
e146d80… drh 1066 usage("OLDNAME NEWNAME");
dbda8d6… drh 1067 }
859b00b… drh 1068 zDest = file_case_preferred_name(".",g.argv[g.argc-1]);
e1962ef… drh 1069 db_begin_transaction();
3c941dd… drh 1070 if( g.argv[1][0]=='r' ){ /* i.e. "rename" */
3c941dd… drh 1071 moveFiles = 0;
86212ec… mistachkin 1072 }else if( softFlag ){
86212ec… mistachkin 1073 moveFiles = 0;
86212ec… mistachkin 1074 }else if( hardFlag ){
86212ec… mistachkin 1075 moveFiles = 1;
86212ec… mistachkin 1076 }else{
86212ec… mistachkin 1077 moveFiles = db_get_boolean("mv-rm-files",0);
86212ec… mistachkin 1078 }
c56a387… mistachkin 1079 file_tree_name(zDest, &dest, 0, 1);
e146d80… drh 1080 db_multi_exec(
e146d80… drh 1081 "UPDATE vfile SET origname=pathname WHERE origname IS NULL;"
e146d80… drh 1082 );
e146d80… drh 1083 db_multi_exec(
e146d80… drh 1084 "CREATE TEMP TABLE mv(f TEXT UNIQUE ON CONFLICT IGNORE, t TEXT);"
e146d80… drh 1085 );
0a34967… drh 1086 if( g.argc!=4 ){
0a34967… drh 1087 origType = -1;
0a34967… drh 1088 }else{
0a34967… drh 1089 origType = (file_isdir(g.argv[2], RepoFILE) == 1);
0a34967… drh 1090 }
0a34967… drh 1091 destType = file_isdir(zDest, RepoFILE);
0a34967… drh 1092 if( origType==-1 && destType!=1 ){
0a34967… drh 1093 usage("OLDNAME NEWNAME");
0a34967… drh 1094 }else if( origType==1 && destType==2 ){
0a34967… drh 1095 fossil_fatal("cannot rename '%s' to '%s' since another file named"
0a34967… drh 1096 " '%s' exists", g.argv[2], zDest, zDest);
0a34967… drh 1097 }else if( origType==0 && destType!=1 ){
e146d80… drh 1098 Blob orig;
c56a387… mistachkin 1099 file_tree_name(g.argv[2], &orig, 0, 1);
e146d80… drh 1100 db_multi_exec(
e146d80… drh 1101 "INSERT INTO mv VALUES(%B,%B)", &orig, &dest
e146d80… drh 1102 );
e146d80… drh 1103 }else{
9fd8009… drh 1104 if( blob_eq(&dest, ".") ){
9fd8009… drh 1105 blob_reset(&dest);
9fd8009… drh 1106 }else{
9fd8009… drh 1107 blob_append(&dest, "/", 1);
9fd8009… drh 1108 }
e146d80… drh 1109 for(i=2; i<g.argc-1; i++){
e146d80… drh 1110 Blob orig;
e146d80… drh 1111 char *zOrig;
e146d80… drh 1112 int nOrig;
c56a387… mistachkin 1113 file_tree_name(g.argv[i], &orig, 0, 1);
e146d80… drh 1114 zOrig = blob_str(&orig);
e146d80… drh 1115 nOrig = blob_size(&orig);
e146d80… drh 1116 db_prepare(&q,
e146d80… drh 1117 "SELECT pathname FROM vfile"
e146d80… drh 1118 " WHERE vid=%d"
3f8cdaa… drh 1119 " AND (pathname='%q' %s OR (pathname>'%q/' %s AND pathname<'%q0' %s))"
e146d80… drh 1120 " ORDER BY 1",
fa6311a… jan.nijtmans 1121 vid, zOrig, filename_collation(), zOrig, filename_collation(),
fa6311a… jan.nijtmans 1122 zOrig, filename_collation()
e146d80… drh 1123 );
e146d80… drh 1124 while( db_step(&q)==SQLITE_ROW ){
e146d80… drh 1125 const char *zPath = db_column_text(&q, 0);
e146d80… drh 1126 int nPath = db_column_bytes(&q, 0);
e146d80… drh 1127 const char *zTail;
e146d80… drh 1128 if( nPath==nOrig ){
e146d80… drh 1129 zTail = file_tail(zPath);
709d2f8… ashepilko 1130 }else if( origType!=0 && destType==1 ){
0a34967… drh 1131 zTail = &zPath[nOrig-strlen(file_tail(zOrig))];
e146d80… drh 1132 }else{
e146d80… drh 1133 zTail = &zPath[nOrig+1];
e146d80… drh 1134 }
e146d80… drh 1135 db_multi_exec(
e766df0… drh 1136 "INSERT INTO mv VALUES('%q','%q%q')",
e146d80… drh 1137 zPath, blob_str(&dest), zTail
e146d80… drh 1138 );
e146d80… drh 1139 }
e146d80… drh 1140 db_finalize(&q);
dbda8d6… drh 1141 }
e146d80… drh 1142 }
e146d80… drh 1143 db_prepare(&q, "SELECT f, t FROM mv ORDER BY f");
e146d80… drh 1144 while( db_step(&q)==SQLITE_ROW ){
e146d80… drh 1145 const char *zFrom = db_column_text(&q, 0);
e146d80… drh 1146 const char *zTo = db_column_text(&q, 1);
31e75c3… danield 1147 mv_one_file(vid, zFrom, zTo, dryRunFlag, moveFiles);
3c941dd… drh 1148 if( moveFiles ) add_file_to_move(zFrom, zTo);
dbda8d6… drh 1149 }
e146d80… drh 1150 db_finalize(&q);
3f8cdaa… drh 1151 undo_reset();
dbda8d6… drh 1152 db_end_transaction(0);
3c941dd… drh 1153 if( moveFiles ) process_files_to_move(dryRunFlag);
859b00b… drh 1154 fossil_free(zDest);
db052aa… drh 1155 }
db052aa… drh 1156
db052aa… drh 1157 /*
db052aa… drh 1158 ** Function for stash_apply to be able to restore a file and indicate
db052aa… drh 1159 ** newly ADDED state.
db052aa… drh 1160 */
db052aa… drh 1161 int stash_add_files_in_sfile(int vid){
db052aa… drh 1162 return add_files_in_sfile(vid);
dbda8d6… drh 1163 }

Keyboard Shortcuts

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