|
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 |
} |