Fossil SCM
All of the execute permission bit handling appears to be working now, though beta testing would be good. Ticket [baf9b6b11e08c1].
Commit
3ad119b7036f8f489eb7f309771093582f6f7eae
Parent
b57bc473b0cf763…
7 files changed
+3
-2
+8
-3
+19
-12
+4
-2
+15
-6
+40
-23
+12
-5
+3
-2
| --- src/add.c | ||
| +++ src/add.c | ||
| @@ -148,12 +148,13 @@ | ||
| 148 | 148 | db_multi_exec("UPDATE vfile SET deleted=0 WHERE pathname=%Q", zPath); |
| 149 | 149 | } |
| 150 | 150 | #endif |
| 151 | 151 | else{ |
| 152 | 152 | db_multi_exec( |
| 153 | - "INSERT INTO vfile(vid,deleted,rid,mrid,pathname)" | |
| 154 | - "VALUES(%d,0,0,0,%Q)", vid, zPath); | |
| 153 | + "INSERT INTO vfile(vid,deleted,rid,mrid,pathname,isexe)" | |
| 154 | + "VALUES(%d,0,0,0,%Q,%d)", | |
| 155 | + vid, zPath,file_isexe(zName)); | |
| 155 | 156 | } |
| 156 | 157 | printf("ADDED %s\n", zPath); |
| 157 | 158 | } |
| 158 | 159 | blob_reset(&pathname); |
| 159 | 160 | } |
| 160 | 161 |
| --- src/add.c | |
| +++ src/add.c | |
| @@ -148,12 +148,13 @@ | |
| 148 | db_multi_exec("UPDATE vfile SET deleted=0 WHERE pathname=%Q", zPath); |
| 149 | } |
| 150 | #endif |
| 151 | else{ |
| 152 | db_multi_exec( |
| 153 | "INSERT INTO vfile(vid,deleted,rid,mrid,pathname)" |
| 154 | "VALUES(%d,0,0,0,%Q)", vid, zPath); |
| 155 | } |
| 156 | printf("ADDED %s\n", zPath); |
| 157 | } |
| 158 | blob_reset(&pathname); |
| 159 | } |
| 160 |
| --- src/add.c | |
| +++ src/add.c | |
| @@ -148,12 +148,13 @@ | |
| 148 | db_multi_exec("UPDATE vfile SET deleted=0 WHERE pathname=%Q", zPath); |
| 149 | } |
| 150 | #endif |
| 151 | else{ |
| 152 | db_multi_exec( |
| 153 | "INSERT INTO vfile(vid,deleted,rid,mrid,pathname,isexe)" |
| 154 | "VALUES(%d,0,0,0,%Q,%d)", |
| 155 | vid, zPath,file_isexe(zName)); |
| 156 | } |
| 157 | printf("ADDED %s\n", zPath); |
| 158 | } |
| 159 | blob_reset(&pathname); |
| 160 | } |
| 161 |
+8
-3
| --- src/file.c | ||
| +++ src/file.c | ||
| @@ -178,26 +178,31 @@ | ||
| 178 | 178 | fclose(in); |
| 179 | 179 | fclose(out); |
| 180 | 180 | } |
| 181 | 181 | |
| 182 | 182 | /* |
| 183 | -** Set or clear the execute bit on a file. | |
| 183 | +** Set or clear the execute bit on a file. Return true if a change | |
| 184 | +** occurred and false if this routine is a no-op. | |
| 184 | 185 | */ |
| 185 | -void file_setexe(const char *zFilename, int onoff){ | |
| 186 | +int file_setexe(const char *zFilename, int onoff){ | |
| 187 | + int rc = 0; | |
| 186 | 188 | #if !defined(_WIN32) |
| 187 | 189 | struct stat buf; |
| 188 | - if( stat(zFilename, &buf)!=0 ) return; | |
| 190 | + if( stat(zFilename, &buf)!=0 ) return 0; | |
| 189 | 191 | if( onoff ){ |
| 190 | 192 | if( (buf.st_mode & 0111)!=0111 ){ |
| 191 | 193 | chmod(zFilename, buf.st_mode | 0111); |
| 194 | + rc = 1; | |
| 192 | 195 | } |
| 193 | 196 | }else{ |
| 194 | 197 | if( (buf.st_mode & 0111)!=0 ){ |
| 195 | 198 | chmod(zFilename, buf.st_mode & ~0111); |
| 199 | + rc = 1; | |
| 196 | 200 | } |
| 197 | 201 | } |
| 198 | 202 | #endif /* _WIN32 */ |
| 203 | + return rc; | |
| 199 | 204 | } |
| 200 | 205 | |
| 201 | 206 | /* |
| 202 | 207 | ** Create the directory named in the argument, if it does not already |
| 203 | 208 | ** exist. If forceFlag is 1, delete any prior non-directory object |
| 204 | 209 |
| --- src/file.c | |
| +++ src/file.c | |
| @@ -178,26 +178,31 @@ | |
| 178 | fclose(in); |
| 179 | fclose(out); |
| 180 | } |
| 181 | |
| 182 | /* |
| 183 | ** Set or clear the execute bit on a file. |
| 184 | */ |
| 185 | void file_setexe(const char *zFilename, int onoff){ |
| 186 | #if !defined(_WIN32) |
| 187 | struct stat buf; |
| 188 | if( stat(zFilename, &buf)!=0 ) return; |
| 189 | if( onoff ){ |
| 190 | if( (buf.st_mode & 0111)!=0111 ){ |
| 191 | chmod(zFilename, buf.st_mode | 0111); |
| 192 | } |
| 193 | }else{ |
| 194 | if( (buf.st_mode & 0111)!=0 ){ |
| 195 | chmod(zFilename, buf.st_mode & ~0111); |
| 196 | } |
| 197 | } |
| 198 | #endif /* _WIN32 */ |
| 199 | } |
| 200 | |
| 201 | /* |
| 202 | ** Create the directory named in the argument, if it does not already |
| 203 | ** exist. If forceFlag is 1, delete any prior non-directory object |
| 204 |
| --- src/file.c | |
| +++ src/file.c | |
| @@ -178,26 +178,31 @@ | |
| 178 | fclose(in); |
| 179 | fclose(out); |
| 180 | } |
| 181 | |
| 182 | /* |
| 183 | ** Set or clear the execute bit on a file. Return true if a change |
| 184 | ** occurred and false if this routine is a no-op. |
| 185 | */ |
| 186 | int file_setexe(const char *zFilename, int onoff){ |
| 187 | int rc = 0; |
| 188 | #if !defined(_WIN32) |
| 189 | struct stat buf; |
| 190 | if( stat(zFilename, &buf)!=0 ) return 0; |
| 191 | if( onoff ){ |
| 192 | if( (buf.st_mode & 0111)!=0111 ){ |
| 193 | chmod(zFilename, buf.st_mode | 0111); |
| 194 | rc = 1; |
| 195 | } |
| 196 | }else{ |
| 197 | if( (buf.st_mode & 0111)!=0 ){ |
| 198 | chmod(zFilename, buf.st_mode & ~0111); |
| 199 | rc = 1; |
| 200 | } |
| 201 | } |
| 202 | #endif /* _WIN32 */ |
| 203 | return rc; |
| 204 | } |
| 205 | |
| 206 | /* |
| 207 | ** Create the directory named in the argument, if it does not already |
| 208 | ** exist. If forceFlag is 1, delete any prior non-directory object |
| 209 |
+19
-12
| --- src/merge.c | ||
| +++ src/merge.c | ||
| @@ -158,20 +158,22 @@ | ||
| 158 | 158 | " idm INTEGER," /* VFILE entry for version merging in */ |
| 159 | 159 | " chnged BOOLEAN," /* True if current version has been edited */ |
| 160 | 160 | " ridv INTEGER," /* Record ID for current version */ |
| 161 | 161 | " ridp INTEGER," /* Record ID for pivot */ |
| 162 | 162 | " ridm INTEGER," /* Record ID for merge */ |
| 163 | + " isexe BOOLEAN," /* Execute permission enabled */ | |
| 163 | 164 | " fnp TEXT," /* The filename in the pivot */ |
| 164 | 165 | " fnm TEXT" /* the filename in the merged version */ |
| 165 | 166 | ");" |
| 166 | 167 | ); |
| 167 | 168 | |
| 168 | 169 | /* Add files found in V |
| 169 | 170 | */ |
| 170 | 171 | db_multi_exec( |
| 171 | - "INSERT OR IGNORE INTO fv(fn,fnp,fnm,idv,idp,idm,ridv,ridp,ridm,chnged)" | |
| 172 | - " SELECT pathname, pathname, pathname, id, 0, 0, rid, 0, 0, chnged " | |
| 172 | + "INSERT OR IGNORE" | |
| 173 | + " INTO fv(fn,fnp,fnm,idv,idp,idm,ridv,ridp,ridm,isexe,chnged)" | |
| 174 | + " SELECT pathname, pathname, pathname, id, 0, 0, rid, 0, 0, isexe, chnged " | |
| 173 | 175 | " FROM vfile WHERE vid=%d", |
| 174 | 176 | vid |
| 175 | 177 | ); |
| 176 | 178 | |
| 177 | 179 | /* |
| @@ -194,12 +196,13 @@ | ||
| 194 | 196 | } |
| 195 | 197 | |
| 196 | 198 | /* Add files found in P but not in V |
| 197 | 199 | */ |
| 198 | 200 | db_multi_exec( |
| 199 | - "INSERT OR IGNORE INTO fv(fn,fnp,fnm,idv,idp,idm,ridv,ridp,ridm,chnged)" | |
| 200 | - " SELECT pathname, pathname, pathname, 0, 0, 0, 0, 0, 0, 0 " | |
| 201 | + "INSERT OR IGNORE" | |
| 202 | + " INTO fv(fn,fnp,fnm,idv,idp,idm,ridv,ridp,ridm,isexe,chnged)" | |
| 203 | + " SELECT pathname, pathname, pathname, 0, 0, 0, 0, 0, 0, isexe, 0 " | |
| 201 | 204 | " FROM vfile" |
| 202 | 205 | " WHERE vid=%d AND pathname NOT IN (SELECT fnp FROM fv)", |
| 203 | 206 | pid |
| 204 | 207 | ); |
| 205 | 208 | |
| @@ -220,12 +223,13 @@ | ||
| 220 | 223 | } |
| 221 | 224 | |
| 222 | 225 | /* Add files found in M but not in P or V. |
| 223 | 226 | */ |
| 224 | 227 | db_multi_exec( |
| 225 | - "INSERT OR IGNORE INTO fv(fn,fnp,fnm,idv,idp,idm,ridv,ridp,ridm,chnged)" | |
| 226 | - " SELECT pathname, pathname, pathname, 0, 0, 0, 0, 0, 0, 0 " | |
| 228 | + "INSERT OR IGNORE" | |
| 229 | + " INTO fv(fn,fnp,fnm,idv,idp,idm,ridv,ridp,ridm,isexe,chnged)" | |
| 230 | + " SELECT pathname, pathname, pathname, 0, 0, 0, 0, 0, 0, isexe, 0 " | |
| 227 | 231 | " FROM vfile" |
| 228 | 232 | " WHERE vid=%d" |
| 229 | 233 | " AND pathname NOT IN (SELECT fnp FROM fv UNION SELECT fnm FROM fv)", |
| 230 | 234 | mid |
| 231 | 235 | ); |
| @@ -242,19 +246,20 @@ | ||
| 242 | 246 | pid, pid, mid, mid |
| 243 | 247 | ); |
| 244 | 248 | |
| 245 | 249 | if( debugFlag ){ |
| 246 | 250 | db_prepare(&q, |
| 247 | - "SELECT rowid, fn, fnp, fnm, chnged, ridv, ridp, ridm FROM fv" | |
| 251 | + "SELECT rowid, fn, fnp, fnm, chnged, ridv, ridp, ridm, isexe FROM fv" | |
| 248 | 252 | ); |
| 249 | 253 | while( db_step(&q)==SQLITE_ROW ){ |
| 250 | - printf("%3d: ridv=%-4d ridp=%-4d ridm=%-4d chnged=%d\n", | |
| 254 | + printf("%3d: ridv=%-4d ridp=%-4d ridm=%-4d chnged=%d isexe=%d\n", | |
| 251 | 255 | db_column_int(&q, 0), |
| 252 | 256 | db_column_int(&q, 5), |
| 253 | 257 | db_column_int(&q, 6), |
| 254 | 258 | db_column_int(&q, 7), |
| 255 | - db_column_int(&q, 4)); | |
| 259 | + db_column_int(&q, 4), | |
| 260 | + db_column_int(&q, 8)); | |
| 256 | 261 | printf(" fn = [%s]\n", db_column_text(&q, 1)); |
| 257 | 262 | printf(" fnp = [%s]\n", db_column_text(&q, 2)); |
| 258 | 263 | printf(" fnm = [%s]\n", db_column_text(&q, 3)); |
| 259 | 264 | } |
| 260 | 265 | db_finalize(&q); |
| @@ -288,12 +293,12 @@ | ||
| 288 | 293 | int idm = db_column_int(&q, 0); |
| 289 | 294 | int rowid = db_column_int(&q, 1); |
| 290 | 295 | int idv; |
| 291 | 296 | const char *zName; |
| 292 | 297 | db_multi_exec( |
| 293 | - "INSERT INTO vfile(vid,chnged,deleted,rid,mrid,pathname)" | |
| 294 | - " SELECT %d,3,0,rid,mrid,pathname FROM vfile WHERE id=%d", | |
| 298 | + "INSERT INTO vfile(vid,chnged,deleted,rid,mrid,isexe,pathname)" | |
| 299 | + " SELECT %d,3,0,rid,mrid,isexe,pathname FROM vfile WHERE id=%d", | |
| 295 | 300 | vid, idm |
| 296 | 301 | ); |
| 297 | 302 | idv = db_last_insert_rowid(); |
| 298 | 303 | db_multi_exec("UPDATE fv SET idv=%d WHERE rowid=%d", idv, rowid); |
| 299 | 304 | zName = db_column_text(&q, 2); |
| @@ -332,11 +337,11 @@ | ||
| 332 | 337 | |
| 333 | 338 | /* |
| 334 | 339 | ** Do a three-way merge on files that have changes on both P->M and P->V. |
| 335 | 340 | */ |
| 336 | 341 | db_prepare(&q, |
| 337 | - "SELECT ridm, idv, ridp, ridv, %s, fn FROM fv" | |
| 342 | + "SELECT ridm, idv, ridp, ridv, %s, fn, isexe FROM fv" | |
| 338 | 343 | " WHERE idp>0 AND idv>0 AND idm>0" |
| 339 | 344 | " AND ridm!=ridp AND (ridv!=ridp OR chnged)", |
| 340 | 345 | glob_expr("fv.fn", zBinGlob) |
| 341 | 346 | ); |
| 342 | 347 | while( db_step(&q)==SQLITE_ROW ){ |
| @@ -344,10 +349,11 @@ | ||
| 344 | 349 | int idv = db_column_int(&q, 1); |
| 345 | 350 | int ridp = db_column_int(&q, 2); |
| 346 | 351 | int ridv = db_column_int(&q, 3); |
| 347 | 352 | int isBinary = db_column_int(&q, 4); |
| 348 | 353 | const char *zName = db_column_text(&q, 5); |
| 354 | + int isExe = db_column_int(&q, 6); | |
| 349 | 355 | int rc; |
| 350 | 356 | char *zFullPath; |
| 351 | 357 | Blob m, p, r; |
| 352 | 358 | /* Do a 3-way merge of idp->idm into idp->idv. The results go into idv. */ |
| 353 | 359 | if( detailFlag ){ |
| @@ -366,10 +372,11 @@ | ||
| 366 | 372 | rc = merge_3way(&p, zFullPath, &m, &r); |
| 367 | 373 | } |
| 368 | 374 | if( rc>=0 ){ |
| 369 | 375 | if( !nochangeFlag ){ |
| 370 | 376 | blob_write_to_file(&r, zFullPath); |
| 377 | + file_setexe(zFullPath, isExe); | |
| 371 | 378 | } |
| 372 | 379 | db_multi_exec("UPDATE vfile SET mtime=0 WHERE id=%d", idv); |
| 373 | 380 | if( rc>0 ){ |
| 374 | 381 | printf("***** %d merge conflicts in %s\n", rc, zName); |
| 375 | 382 | nConflict++; |
| 376 | 383 |
| --- src/merge.c | |
| +++ src/merge.c | |
| @@ -158,20 +158,22 @@ | |
| 158 | " idm INTEGER," /* VFILE entry for version merging in */ |
| 159 | " chnged BOOLEAN," /* True if current version has been edited */ |
| 160 | " ridv INTEGER," /* Record ID for current version */ |
| 161 | " ridp INTEGER," /* Record ID for pivot */ |
| 162 | " ridm INTEGER," /* Record ID for merge */ |
| 163 | " fnp TEXT," /* The filename in the pivot */ |
| 164 | " fnm TEXT" /* the filename in the merged version */ |
| 165 | ");" |
| 166 | ); |
| 167 | |
| 168 | /* Add files found in V |
| 169 | */ |
| 170 | db_multi_exec( |
| 171 | "INSERT OR IGNORE INTO fv(fn,fnp,fnm,idv,idp,idm,ridv,ridp,ridm,chnged)" |
| 172 | " SELECT pathname, pathname, pathname, id, 0, 0, rid, 0, 0, chnged " |
| 173 | " FROM vfile WHERE vid=%d", |
| 174 | vid |
| 175 | ); |
| 176 | |
| 177 | /* |
| @@ -194,12 +196,13 @@ | |
| 194 | } |
| 195 | |
| 196 | /* Add files found in P but not in V |
| 197 | */ |
| 198 | db_multi_exec( |
| 199 | "INSERT OR IGNORE INTO fv(fn,fnp,fnm,idv,idp,idm,ridv,ridp,ridm,chnged)" |
| 200 | " SELECT pathname, pathname, pathname, 0, 0, 0, 0, 0, 0, 0 " |
| 201 | " FROM vfile" |
| 202 | " WHERE vid=%d AND pathname NOT IN (SELECT fnp FROM fv)", |
| 203 | pid |
| 204 | ); |
| 205 | |
| @@ -220,12 +223,13 @@ | |
| 220 | } |
| 221 | |
| 222 | /* Add files found in M but not in P or V. |
| 223 | */ |
| 224 | db_multi_exec( |
| 225 | "INSERT OR IGNORE INTO fv(fn,fnp,fnm,idv,idp,idm,ridv,ridp,ridm,chnged)" |
| 226 | " SELECT pathname, pathname, pathname, 0, 0, 0, 0, 0, 0, 0 " |
| 227 | " FROM vfile" |
| 228 | " WHERE vid=%d" |
| 229 | " AND pathname NOT IN (SELECT fnp FROM fv UNION SELECT fnm FROM fv)", |
| 230 | mid |
| 231 | ); |
| @@ -242,19 +246,20 @@ | |
| 242 | pid, pid, mid, mid |
| 243 | ); |
| 244 | |
| 245 | if( debugFlag ){ |
| 246 | db_prepare(&q, |
| 247 | "SELECT rowid, fn, fnp, fnm, chnged, ridv, ridp, ridm FROM fv" |
| 248 | ); |
| 249 | while( db_step(&q)==SQLITE_ROW ){ |
| 250 | printf("%3d: ridv=%-4d ridp=%-4d ridm=%-4d chnged=%d\n", |
| 251 | db_column_int(&q, 0), |
| 252 | db_column_int(&q, 5), |
| 253 | db_column_int(&q, 6), |
| 254 | db_column_int(&q, 7), |
| 255 | db_column_int(&q, 4)); |
| 256 | printf(" fn = [%s]\n", db_column_text(&q, 1)); |
| 257 | printf(" fnp = [%s]\n", db_column_text(&q, 2)); |
| 258 | printf(" fnm = [%s]\n", db_column_text(&q, 3)); |
| 259 | } |
| 260 | db_finalize(&q); |
| @@ -288,12 +293,12 @@ | |
| 288 | int idm = db_column_int(&q, 0); |
| 289 | int rowid = db_column_int(&q, 1); |
| 290 | int idv; |
| 291 | const char *zName; |
| 292 | db_multi_exec( |
| 293 | "INSERT INTO vfile(vid,chnged,deleted,rid,mrid,pathname)" |
| 294 | " SELECT %d,3,0,rid,mrid,pathname FROM vfile WHERE id=%d", |
| 295 | vid, idm |
| 296 | ); |
| 297 | idv = db_last_insert_rowid(); |
| 298 | db_multi_exec("UPDATE fv SET idv=%d WHERE rowid=%d", idv, rowid); |
| 299 | zName = db_column_text(&q, 2); |
| @@ -332,11 +337,11 @@ | |
| 332 | |
| 333 | /* |
| 334 | ** Do a three-way merge on files that have changes on both P->M and P->V. |
| 335 | */ |
| 336 | db_prepare(&q, |
| 337 | "SELECT ridm, idv, ridp, ridv, %s, fn FROM fv" |
| 338 | " WHERE idp>0 AND idv>0 AND idm>0" |
| 339 | " AND ridm!=ridp AND (ridv!=ridp OR chnged)", |
| 340 | glob_expr("fv.fn", zBinGlob) |
| 341 | ); |
| 342 | while( db_step(&q)==SQLITE_ROW ){ |
| @@ -344,10 +349,11 @@ | |
| 344 | int idv = db_column_int(&q, 1); |
| 345 | int ridp = db_column_int(&q, 2); |
| 346 | int ridv = db_column_int(&q, 3); |
| 347 | int isBinary = db_column_int(&q, 4); |
| 348 | const char *zName = db_column_text(&q, 5); |
| 349 | int rc; |
| 350 | char *zFullPath; |
| 351 | Blob m, p, r; |
| 352 | /* Do a 3-way merge of idp->idm into idp->idv. The results go into idv. */ |
| 353 | if( detailFlag ){ |
| @@ -366,10 +372,11 @@ | |
| 366 | rc = merge_3way(&p, zFullPath, &m, &r); |
| 367 | } |
| 368 | if( rc>=0 ){ |
| 369 | if( !nochangeFlag ){ |
| 370 | blob_write_to_file(&r, zFullPath); |
| 371 | } |
| 372 | db_multi_exec("UPDATE vfile SET mtime=0 WHERE id=%d", idv); |
| 373 | if( rc>0 ){ |
| 374 | printf("***** %d merge conflicts in %s\n", rc, zName); |
| 375 | nConflict++; |
| 376 |
| --- src/merge.c | |
| +++ src/merge.c | |
| @@ -158,20 +158,22 @@ | |
| 158 | " idm INTEGER," /* VFILE entry for version merging in */ |
| 159 | " chnged BOOLEAN," /* True if current version has been edited */ |
| 160 | " ridv INTEGER," /* Record ID for current version */ |
| 161 | " ridp INTEGER," /* Record ID for pivot */ |
| 162 | " ridm INTEGER," /* Record ID for merge */ |
| 163 | " isexe BOOLEAN," /* Execute permission enabled */ |
| 164 | " fnp TEXT," /* The filename in the pivot */ |
| 165 | " fnm TEXT" /* the filename in the merged version */ |
| 166 | ");" |
| 167 | ); |
| 168 | |
| 169 | /* Add files found in V |
| 170 | */ |
| 171 | db_multi_exec( |
| 172 | "INSERT OR IGNORE" |
| 173 | " INTO fv(fn,fnp,fnm,idv,idp,idm,ridv,ridp,ridm,isexe,chnged)" |
| 174 | " SELECT pathname, pathname, pathname, id, 0, 0, rid, 0, 0, isexe, chnged " |
| 175 | " FROM vfile WHERE vid=%d", |
| 176 | vid |
| 177 | ); |
| 178 | |
| 179 | /* |
| @@ -194,12 +196,13 @@ | |
| 196 | } |
| 197 | |
| 198 | /* Add files found in P but not in V |
| 199 | */ |
| 200 | db_multi_exec( |
| 201 | "INSERT OR IGNORE" |
| 202 | " INTO fv(fn,fnp,fnm,idv,idp,idm,ridv,ridp,ridm,isexe,chnged)" |
| 203 | " SELECT pathname, pathname, pathname, 0, 0, 0, 0, 0, 0, isexe, 0 " |
| 204 | " FROM vfile" |
| 205 | " WHERE vid=%d AND pathname NOT IN (SELECT fnp FROM fv)", |
| 206 | pid |
| 207 | ); |
| 208 | |
| @@ -220,12 +223,13 @@ | |
| 223 | } |
| 224 | |
| 225 | /* Add files found in M but not in P or V. |
| 226 | */ |
| 227 | db_multi_exec( |
| 228 | "INSERT OR IGNORE" |
| 229 | " INTO fv(fn,fnp,fnm,idv,idp,idm,ridv,ridp,ridm,isexe,chnged)" |
| 230 | " SELECT pathname, pathname, pathname, 0, 0, 0, 0, 0, 0, isexe, 0 " |
| 231 | " FROM vfile" |
| 232 | " WHERE vid=%d" |
| 233 | " AND pathname NOT IN (SELECT fnp FROM fv UNION SELECT fnm FROM fv)", |
| 234 | mid |
| 235 | ); |
| @@ -242,19 +246,20 @@ | |
| 246 | pid, pid, mid, mid |
| 247 | ); |
| 248 | |
| 249 | if( debugFlag ){ |
| 250 | db_prepare(&q, |
| 251 | "SELECT rowid, fn, fnp, fnm, chnged, ridv, ridp, ridm, isexe FROM fv" |
| 252 | ); |
| 253 | while( db_step(&q)==SQLITE_ROW ){ |
| 254 | printf("%3d: ridv=%-4d ridp=%-4d ridm=%-4d chnged=%d isexe=%d\n", |
| 255 | db_column_int(&q, 0), |
| 256 | db_column_int(&q, 5), |
| 257 | db_column_int(&q, 6), |
| 258 | db_column_int(&q, 7), |
| 259 | db_column_int(&q, 4), |
| 260 | db_column_int(&q, 8)); |
| 261 | printf(" fn = [%s]\n", db_column_text(&q, 1)); |
| 262 | printf(" fnp = [%s]\n", db_column_text(&q, 2)); |
| 263 | printf(" fnm = [%s]\n", db_column_text(&q, 3)); |
| 264 | } |
| 265 | db_finalize(&q); |
| @@ -288,12 +293,12 @@ | |
| 293 | int idm = db_column_int(&q, 0); |
| 294 | int rowid = db_column_int(&q, 1); |
| 295 | int idv; |
| 296 | const char *zName; |
| 297 | db_multi_exec( |
| 298 | "INSERT INTO vfile(vid,chnged,deleted,rid,mrid,isexe,pathname)" |
| 299 | " SELECT %d,3,0,rid,mrid,isexe,pathname FROM vfile WHERE id=%d", |
| 300 | vid, idm |
| 301 | ); |
| 302 | idv = db_last_insert_rowid(); |
| 303 | db_multi_exec("UPDATE fv SET idv=%d WHERE rowid=%d", idv, rowid); |
| 304 | zName = db_column_text(&q, 2); |
| @@ -332,11 +337,11 @@ | |
| 337 | |
| 338 | /* |
| 339 | ** Do a three-way merge on files that have changes on both P->M and P->V. |
| 340 | */ |
| 341 | db_prepare(&q, |
| 342 | "SELECT ridm, idv, ridp, ridv, %s, fn, isexe FROM fv" |
| 343 | " WHERE idp>0 AND idv>0 AND idm>0" |
| 344 | " AND ridm!=ridp AND (ridv!=ridp OR chnged)", |
| 345 | glob_expr("fv.fn", zBinGlob) |
| 346 | ); |
| 347 | while( db_step(&q)==SQLITE_ROW ){ |
| @@ -344,10 +349,11 @@ | |
| 349 | int idv = db_column_int(&q, 1); |
| 350 | int ridp = db_column_int(&q, 2); |
| 351 | int ridv = db_column_int(&q, 3); |
| 352 | int isBinary = db_column_int(&q, 4); |
| 353 | const char *zName = db_column_text(&q, 5); |
| 354 | int isExe = db_column_int(&q, 6); |
| 355 | int rc; |
| 356 | char *zFullPath; |
| 357 | Blob m, p, r; |
| 358 | /* Do a 3-way merge of idp->idm into idp->idv. The results go into idv. */ |
| 359 | if( detailFlag ){ |
| @@ -366,10 +372,11 @@ | |
| 372 | rc = merge_3way(&p, zFullPath, &m, &r); |
| 373 | } |
| 374 | if( rc>=0 ){ |
| 375 | if( !nochangeFlag ){ |
| 376 | blob_write_to_file(&r, zFullPath); |
| 377 | file_setexe(zFullPath, isExe); |
| 378 | } |
| 379 | db_multi_exec("UPDATE vfile SET mtime=0 WHERE id=%d", idv); |
| 380 | if( rc>0 ){ |
| 381 | printf("***** %d merge conflicts in %s\n", rc, zName); |
| 382 | nConflict++; |
| 383 |
+4
-2
| --- src/stash.c | ||
| +++ src/stash.c | ||
| @@ -92,13 +92,11 @@ | ||
| 92 | 92 | Blob content; |
| 93 | 93 | |
| 94 | 94 | db_bind_int(&ins, ":rid", rid); |
| 95 | 95 | db_bind_int(&ins, ":isadd", rid==0); |
| 96 | 96 | db_bind_int(&ins, ":isrm", deleted); |
| 97 | -#ifdef _WIN32 | |
| 98 | 97 | db_bind_int(&ins, ":isexe", db_column_int(&q, 1)); |
| 99 | -#endif | |
| 100 | 98 | db_bind_text(&ins, ":orig", zOrig); |
| 101 | 99 | db_bind_text(&ins, ":new", zName); |
| 102 | 100 | if( rid==0 ){ |
| 103 | 101 | /* A new file */ |
| 104 | 102 | blob_read_from_file(&content, zPath); |
| @@ -175,10 +173,11 @@ | ||
| 175 | 173 | stashid |
| 176 | 174 | ); |
| 177 | 175 | while( db_step(&q)==SQLITE_ROW ){ |
| 178 | 176 | int rid = db_column_int(&q, 0); |
| 179 | 177 | int isRemoved = db_column_int(&q, 1); |
| 178 | + int isExec = db_column_int(&q, 2); | |
| 180 | 179 | const char *zOrig = db_column_text(&q, 3); |
| 181 | 180 | const char *zNew = db_column_text(&q, 4); |
| 182 | 181 | char *zOPath = mprintf("%s%s", g.zLocalRoot, zOrig); |
| 183 | 182 | char *zNPath = mprintf("%s%s", g.zLocalRoot, zNew); |
| 184 | 183 | Blob delta; |
| @@ -185,10 +184,11 @@ | ||
| 185 | 184 | undo_save(zNew); |
| 186 | 185 | blob_zero(&delta); |
| 187 | 186 | if( rid==0 ){ |
| 188 | 187 | db_ephemeral_blob(&q, 5, &delta); |
| 189 | 188 | blob_write_to_file(&delta, zNPath); |
| 189 | + file_setexe(zNPath, isExec); | |
| 190 | 190 | printf("ADD %s\n", zNew); |
| 191 | 191 | }else if( isRemoved ){ |
| 192 | 192 | printf("DELETE %s\n", zOrig); |
| 193 | 193 | unlink(zOPath); |
| 194 | 194 | }else{ |
| @@ -197,14 +197,16 @@ | ||
| 197 | 197 | blob_read_from_file(&disk, zOPath); |
| 198 | 198 | content_get(rid, &a); |
| 199 | 199 | blob_delta_apply(&a, &delta, &b); |
| 200 | 200 | if( blob_compare(&disk, &a)==0 ){ |
| 201 | 201 | blob_write_to_file(&b, zNPath); |
| 202 | + file_setexe(zNPath, isExec); | |
| 202 | 203 | printf("UPDATE %s\n", zNew); |
| 203 | 204 | }else{ |
| 204 | 205 | int rc = merge_3way(&a, zOPath, &b, &out); |
| 205 | 206 | blob_write_to_file(&out, zNPath); |
| 207 | + file_setexe(zNPath, isExec); | |
| 206 | 208 | if( rc ){ |
| 207 | 209 | printf("CONFLICT %s\n", zNew); |
| 208 | 210 | nConflict++; |
| 209 | 211 | }else{ |
| 210 | 212 | printf("MERGE %s\n", zNew); |
| 211 | 213 |
| --- src/stash.c | |
| +++ src/stash.c | |
| @@ -92,13 +92,11 @@ | |
| 92 | Blob content; |
| 93 | |
| 94 | db_bind_int(&ins, ":rid", rid); |
| 95 | db_bind_int(&ins, ":isadd", rid==0); |
| 96 | db_bind_int(&ins, ":isrm", deleted); |
| 97 | #ifdef _WIN32 |
| 98 | db_bind_int(&ins, ":isexe", db_column_int(&q, 1)); |
| 99 | #endif |
| 100 | db_bind_text(&ins, ":orig", zOrig); |
| 101 | db_bind_text(&ins, ":new", zName); |
| 102 | if( rid==0 ){ |
| 103 | /* A new file */ |
| 104 | blob_read_from_file(&content, zPath); |
| @@ -175,10 +173,11 @@ | |
| 175 | stashid |
| 176 | ); |
| 177 | while( db_step(&q)==SQLITE_ROW ){ |
| 178 | int rid = db_column_int(&q, 0); |
| 179 | int isRemoved = db_column_int(&q, 1); |
| 180 | const char *zOrig = db_column_text(&q, 3); |
| 181 | const char *zNew = db_column_text(&q, 4); |
| 182 | char *zOPath = mprintf("%s%s", g.zLocalRoot, zOrig); |
| 183 | char *zNPath = mprintf("%s%s", g.zLocalRoot, zNew); |
| 184 | Blob delta; |
| @@ -185,10 +184,11 @@ | |
| 185 | undo_save(zNew); |
| 186 | blob_zero(&delta); |
| 187 | if( rid==0 ){ |
| 188 | db_ephemeral_blob(&q, 5, &delta); |
| 189 | blob_write_to_file(&delta, zNPath); |
| 190 | printf("ADD %s\n", zNew); |
| 191 | }else if( isRemoved ){ |
| 192 | printf("DELETE %s\n", zOrig); |
| 193 | unlink(zOPath); |
| 194 | }else{ |
| @@ -197,14 +197,16 @@ | |
| 197 | blob_read_from_file(&disk, zOPath); |
| 198 | content_get(rid, &a); |
| 199 | blob_delta_apply(&a, &delta, &b); |
| 200 | if( blob_compare(&disk, &a)==0 ){ |
| 201 | blob_write_to_file(&b, zNPath); |
| 202 | printf("UPDATE %s\n", zNew); |
| 203 | }else{ |
| 204 | int rc = merge_3way(&a, zOPath, &b, &out); |
| 205 | blob_write_to_file(&out, zNPath); |
| 206 | if( rc ){ |
| 207 | printf("CONFLICT %s\n", zNew); |
| 208 | nConflict++; |
| 209 | }else{ |
| 210 | printf("MERGE %s\n", zNew); |
| 211 |
| --- src/stash.c | |
| +++ src/stash.c | |
| @@ -92,13 +92,11 @@ | |
| 92 | Blob content; |
| 93 | |
| 94 | db_bind_int(&ins, ":rid", rid); |
| 95 | db_bind_int(&ins, ":isadd", rid==0); |
| 96 | db_bind_int(&ins, ":isrm", deleted); |
| 97 | db_bind_int(&ins, ":isexe", db_column_int(&q, 1)); |
| 98 | db_bind_text(&ins, ":orig", zOrig); |
| 99 | db_bind_text(&ins, ":new", zName); |
| 100 | if( rid==0 ){ |
| 101 | /* A new file */ |
| 102 | blob_read_from_file(&content, zPath); |
| @@ -175,10 +173,11 @@ | |
| 173 | stashid |
| 174 | ); |
| 175 | while( db_step(&q)==SQLITE_ROW ){ |
| 176 | int rid = db_column_int(&q, 0); |
| 177 | int isRemoved = db_column_int(&q, 1); |
| 178 | int isExec = db_column_int(&q, 2); |
| 179 | const char *zOrig = db_column_text(&q, 3); |
| 180 | const char *zNew = db_column_text(&q, 4); |
| 181 | char *zOPath = mprintf("%s%s", g.zLocalRoot, zOrig); |
| 182 | char *zNPath = mprintf("%s%s", g.zLocalRoot, zNew); |
| 183 | Blob delta; |
| @@ -185,10 +184,11 @@ | |
| 184 | undo_save(zNew); |
| 185 | blob_zero(&delta); |
| 186 | if( rid==0 ){ |
| 187 | db_ephemeral_blob(&q, 5, &delta); |
| 188 | blob_write_to_file(&delta, zNPath); |
| 189 | file_setexe(zNPath, isExec); |
| 190 | printf("ADD %s\n", zNew); |
| 191 | }else if( isRemoved ){ |
| 192 | printf("DELETE %s\n", zOrig); |
| 193 | unlink(zOPath); |
| 194 | }else{ |
| @@ -197,14 +197,16 @@ | |
| 197 | blob_read_from_file(&disk, zOPath); |
| 198 | content_get(rid, &a); |
| 199 | blob_delta_apply(&a, &delta, &b); |
| 200 | if( blob_compare(&disk, &a)==0 ){ |
| 201 | blob_write_to_file(&b, zNPath); |
| 202 | file_setexe(zNPath, isExec); |
| 203 | printf("UPDATE %s\n", zNew); |
| 204 | }else{ |
| 205 | int rc = merge_3way(&a, zOPath, &b, &out); |
| 206 | blob_write_to_file(&out, zNPath); |
| 207 | file_setexe(zNPath, isExec); |
| 208 | if( rc ){ |
| 209 | printf("CONFLICT %s\n", zNew); |
| 210 | nConflict++; |
| 211 | }else{ |
| 212 | printf("MERGE %s\n", zNew); |
| 213 |
+15
-6
| --- src/undo.c | ||
| +++ src/undo.c | ||
| @@ -30,27 +30,33 @@ | ||
| 30 | 30 | */ |
| 31 | 31 | static void undo_one(const char *zPathname, int redoFlag){ |
| 32 | 32 | Stmt q; |
| 33 | 33 | char *zFullname; |
| 34 | 34 | db_prepare(&q, |
| 35 | - "SELECT content, existsflag FROM undo WHERE pathname=%Q AND redoflag=%d", | |
| 35 | + "SELECT content, existsflag, isExe FROM undo" | |
| 36 | + " WHERE pathname=%Q AND redoflag=%d", | |
| 36 | 37 | zPathname, redoFlag |
| 37 | 38 | ); |
| 38 | 39 | if( db_step(&q)==SQLITE_ROW ){ |
| 39 | 40 | int old_exists; |
| 40 | 41 | int new_exists; |
| 42 | + int old_exe; | |
| 43 | + int new_exe; | |
| 41 | 44 | Blob current; |
| 42 | 45 | Blob new; |
| 43 | 46 | zFullname = mprintf("%s/%s", g.zLocalRoot, zPathname); |
| 44 | 47 | new_exists = file_size(zFullname)>=0; |
| 45 | 48 | if( new_exists ){ |
| 46 | 49 | blob_read_from_file(¤t, zFullname); |
| 50 | + new_exe = file_isexe(zFullname); | |
| 47 | 51 | }else{ |
| 48 | 52 | blob_zero(¤t); |
| 53 | + new_exe = 0; | |
| 49 | 54 | } |
| 50 | 55 | blob_zero(&new); |
| 51 | 56 | old_exists = db_column_int(&q, 1); |
| 57 | + old_exe = db_column_int(&q, 2); | |
| 52 | 58 | if( old_exists ){ |
| 53 | 59 | db_ephemeral_blob(&q, 0, &new); |
| 54 | 60 | } |
| 55 | 61 | if( old_exists ){ |
| 56 | 62 | if( new_exists ){ |
| @@ -57,21 +63,23 @@ | ||
| 57 | 63 | printf("%s %s\n", redoFlag ? "REDO" : "UNDO", zPathname); |
| 58 | 64 | }else{ |
| 59 | 65 | printf("NEW %s\n", zPathname); |
| 60 | 66 | } |
| 61 | 67 | blob_write_to_file(&new, zFullname); |
| 68 | + file_setexe(zFullname, old_exe); | |
| 62 | 69 | }else{ |
| 63 | 70 | printf("DELETE %s\n", zPathname); |
| 64 | 71 | unlink(zFullname); |
| 65 | 72 | } |
| 66 | 73 | blob_reset(&new); |
| 67 | 74 | free(zFullname); |
| 68 | 75 | db_finalize(&q); |
| 69 | 76 | db_prepare(&q, |
| 70 | - "UPDATE undo SET content=:c, existsflag=%d, redoflag=NOT redoflag" | |
| 77 | + "UPDATE undo SET content=:c, existsflag=%d, isExe=%d," | |
| 78 | + " redoflag=NOT redoflag" | |
| 71 | 79 | " WHERE pathname=%Q", |
| 72 | - new_exists, zPathname | |
| 80 | + new_exists, new_exe, zPathname | |
| 73 | 81 | ); |
| 74 | 82 | if( new_exists ){ |
| 75 | 83 | db_bind_blob(&q, ":c", ¤t); |
| 76 | 84 | } |
| 77 | 85 | db_step(&q); |
| @@ -200,10 +208,11 @@ | ||
| 200 | 208 | static const char zSql[] = |
| 201 | 209 | @ CREATE TABLE %s.undo( |
| 202 | 210 | @ pathname TEXT UNIQUE, -- Name of the file |
| 203 | 211 | @ redoflag BOOLEAN, -- 0 for undoable. 1 for redoable |
| 204 | 212 | @ existsflag BOOLEAN, -- True if the file exists |
| 213 | + @ isExe BOOLEAN, -- True if the file is executable | |
| 205 | 214 | @ content BLOB -- Saved content |
| 206 | 215 | @ ); |
| 207 | 216 | @ CREATE TABLE %s.undo_vfile AS SELECT * FROM vfile; |
| 208 | 217 | @ CREATE TABLE %s.undo_vmerge AS SELECT * FROM vmerge; |
| 209 | 218 | ; |
| @@ -246,13 +255,13 @@ | ||
| 246 | 255 | |
| 247 | 256 | if( !undoActive ) return; |
| 248 | 257 | zFullname = mprintf("%s%s", g.zLocalRoot, zPathname); |
| 249 | 258 | existsFlag = file_size(zFullname)>=0; |
| 250 | 259 | db_prepare(&q, |
| 251 | - "INSERT OR IGNORE INTO undo(pathname,redoflag,existsflag,content)" | |
| 252 | - " VALUES(%Q,0,%d,:c)", | |
| 253 | - zPathname, existsFlag | |
| 260 | + "INSERT OR IGNORE INTO undo(pathname,redoflag,existsflag,isExe,content)" | |
| 261 | + " VALUES(%Q,0,%d,%d,:c)", | |
| 262 | + zPathname, existsFlag, file_isexe(zFullname) | |
| 254 | 263 | ); |
| 255 | 264 | if( existsFlag ){ |
| 256 | 265 | blob_read_from_file(&content, zFullname); |
| 257 | 266 | db_bind_blob(&q, ":c", &content); |
| 258 | 267 | } |
| 259 | 268 |
| --- src/undo.c | |
| +++ src/undo.c | |
| @@ -30,27 +30,33 @@ | |
| 30 | */ |
| 31 | static void undo_one(const char *zPathname, int redoFlag){ |
| 32 | Stmt q; |
| 33 | char *zFullname; |
| 34 | db_prepare(&q, |
| 35 | "SELECT content, existsflag FROM undo WHERE pathname=%Q AND redoflag=%d", |
| 36 | zPathname, redoFlag |
| 37 | ); |
| 38 | if( db_step(&q)==SQLITE_ROW ){ |
| 39 | int old_exists; |
| 40 | int new_exists; |
| 41 | Blob current; |
| 42 | Blob new; |
| 43 | zFullname = mprintf("%s/%s", g.zLocalRoot, zPathname); |
| 44 | new_exists = file_size(zFullname)>=0; |
| 45 | if( new_exists ){ |
| 46 | blob_read_from_file(¤t, zFullname); |
| 47 | }else{ |
| 48 | blob_zero(¤t); |
| 49 | } |
| 50 | blob_zero(&new); |
| 51 | old_exists = db_column_int(&q, 1); |
| 52 | if( old_exists ){ |
| 53 | db_ephemeral_blob(&q, 0, &new); |
| 54 | } |
| 55 | if( old_exists ){ |
| 56 | if( new_exists ){ |
| @@ -57,21 +63,23 @@ | |
| 57 | printf("%s %s\n", redoFlag ? "REDO" : "UNDO", zPathname); |
| 58 | }else{ |
| 59 | printf("NEW %s\n", zPathname); |
| 60 | } |
| 61 | blob_write_to_file(&new, zFullname); |
| 62 | }else{ |
| 63 | printf("DELETE %s\n", zPathname); |
| 64 | unlink(zFullname); |
| 65 | } |
| 66 | blob_reset(&new); |
| 67 | free(zFullname); |
| 68 | db_finalize(&q); |
| 69 | db_prepare(&q, |
| 70 | "UPDATE undo SET content=:c, existsflag=%d, redoflag=NOT redoflag" |
| 71 | " WHERE pathname=%Q", |
| 72 | new_exists, zPathname |
| 73 | ); |
| 74 | if( new_exists ){ |
| 75 | db_bind_blob(&q, ":c", ¤t); |
| 76 | } |
| 77 | db_step(&q); |
| @@ -200,10 +208,11 @@ | |
| 200 | static const char zSql[] = |
| 201 | @ CREATE TABLE %s.undo( |
| 202 | @ pathname TEXT UNIQUE, -- Name of the file |
| 203 | @ redoflag BOOLEAN, -- 0 for undoable. 1 for redoable |
| 204 | @ existsflag BOOLEAN, -- True if the file exists |
| 205 | @ content BLOB -- Saved content |
| 206 | @ ); |
| 207 | @ CREATE TABLE %s.undo_vfile AS SELECT * FROM vfile; |
| 208 | @ CREATE TABLE %s.undo_vmerge AS SELECT * FROM vmerge; |
| 209 | ; |
| @@ -246,13 +255,13 @@ | |
| 246 | |
| 247 | if( !undoActive ) return; |
| 248 | zFullname = mprintf("%s%s", g.zLocalRoot, zPathname); |
| 249 | existsFlag = file_size(zFullname)>=0; |
| 250 | db_prepare(&q, |
| 251 | "INSERT OR IGNORE INTO undo(pathname,redoflag,existsflag,content)" |
| 252 | " VALUES(%Q,0,%d,:c)", |
| 253 | zPathname, existsFlag |
| 254 | ); |
| 255 | if( existsFlag ){ |
| 256 | blob_read_from_file(&content, zFullname); |
| 257 | db_bind_blob(&q, ":c", &content); |
| 258 | } |
| 259 |
| --- src/undo.c | |
| +++ src/undo.c | |
| @@ -30,27 +30,33 @@ | |
| 30 | */ |
| 31 | static void undo_one(const char *zPathname, int redoFlag){ |
| 32 | Stmt q; |
| 33 | char *zFullname; |
| 34 | db_prepare(&q, |
| 35 | "SELECT content, existsflag, isExe FROM undo" |
| 36 | " WHERE pathname=%Q AND redoflag=%d", |
| 37 | zPathname, redoFlag |
| 38 | ); |
| 39 | if( db_step(&q)==SQLITE_ROW ){ |
| 40 | int old_exists; |
| 41 | int new_exists; |
| 42 | int old_exe; |
| 43 | int new_exe; |
| 44 | Blob current; |
| 45 | Blob new; |
| 46 | zFullname = mprintf("%s/%s", g.zLocalRoot, zPathname); |
| 47 | new_exists = file_size(zFullname)>=0; |
| 48 | if( new_exists ){ |
| 49 | blob_read_from_file(¤t, zFullname); |
| 50 | new_exe = file_isexe(zFullname); |
| 51 | }else{ |
| 52 | blob_zero(¤t); |
| 53 | new_exe = 0; |
| 54 | } |
| 55 | blob_zero(&new); |
| 56 | old_exists = db_column_int(&q, 1); |
| 57 | old_exe = db_column_int(&q, 2); |
| 58 | if( old_exists ){ |
| 59 | db_ephemeral_blob(&q, 0, &new); |
| 60 | } |
| 61 | if( old_exists ){ |
| 62 | if( new_exists ){ |
| @@ -57,21 +63,23 @@ | |
| 63 | printf("%s %s\n", redoFlag ? "REDO" : "UNDO", zPathname); |
| 64 | }else{ |
| 65 | printf("NEW %s\n", zPathname); |
| 66 | } |
| 67 | blob_write_to_file(&new, zFullname); |
| 68 | file_setexe(zFullname, old_exe); |
| 69 | }else{ |
| 70 | printf("DELETE %s\n", zPathname); |
| 71 | unlink(zFullname); |
| 72 | } |
| 73 | blob_reset(&new); |
| 74 | free(zFullname); |
| 75 | db_finalize(&q); |
| 76 | db_prepare(&q, |
| 77 | "UPDATE undo SET content=:c, existsflag=%d, isExe=%d," |
| 78 | " redoflag=NOT redoflag" |
| 79 | " WHERE pathname=%Q", |
| 80 | new_exists, new_exe, zPathname |
| 81 | ); |
| 82 | if( new_exists ){ |
| 83 | db_bind_blob(&q, ":c", ¤t); |
| 84 | } |
| 85 | db_step(&q); |
| @@ -200,10 +208,11 @@ | |
| 208 | static const char zSql[] = |
| 209 | @ CREATE TABLE %s.undo( |
| 210 | @ pathname TEXT UNIQUE, -- Name of the file |
| 211 | @ redoflag BOOLEAN, -- 0 for undoable. 1 for redoable |
| 212 | @ existsflag BOOLEAN, -- True if the file exists |
| 213 | @ isExe BOOLEAN, -- True if the file is executable |
| 214 | @ content BLOB -- Saved content |
| 215 | @ ); |
| 216 | @ CREATE TABLE %s.undo_vfile AS SELECT * FROM vfile; |
| 217 | @ CREATE TABLE %s.undo_vmerge AS SELECT * FROM vmerge; |
| 218 | ; |
| @@ -246,13 +255,13 @@ | |
| 255 | |
| 256 | if( !undoActive ) return; |
| 257 | zFullname = mprintf("%s%s", g.zLocalRoot, zPathname); |
| 258 | existsFlag = file_size(zFullname)>=0; |
| 259 | db_prepare(&q, |
| 260 | "INSERT OR IGNORE INTO undo(pathname,redoflag,existsflag,isExe,content)" |
| 261 | " VALUES(%Q,0,%d,%d,:c)", |
| 262 | zPathname, existsFlag, file_isexe(zFullname) |
| 263 | ); |
| 264 | if( existsFlag ){ |
| 265 | blob_read_from_file(&content, zFullname); |
| 266 | db_bind_blob(&q, ":c", &content); |
| 267 | } |
| 268 |
+40
-23
| --- src/update.c | ||
| +++ src/update.c | ||
| @@ -197,19 +197,21 @@ | ||
| 197 | 197 | " idv INTEGER," /* VFILE entry for current version */ |
| 198 | 198 | " idt INTEGER," /* VFILE entry for target version */ |
| 199 | 199 | " chnged BOOLEAN," /* True if current version has been edited */ |
| 200 | 200 | " ridv INTEGER," /* Record ID for current version */ |
| 201 | 201 | " ridt INTEGER," /* Record ID for target */ |
| 202 | + " isexe BOOLEAN," /* Does target have execute permission? */ | |
| 202 | 203 | " fnt TEXT" /* Filename of same file on target version */ |
| 203 | 204 | ");" |
| 204 | 205 | ); |
| 205 | 206 | |
| 206 | 207 | /* Add files found in the current version |
| 207 | 208 | */ |
| 208 | 209 | db_multi_exec( |
| 209 | - "INSERT OR IGNORE INTO fv(fn,fnt,idv,idt,ridv,ridt,chnged)" | |
| 210 | - " SELECT pathname, pathname, id, 0, rid, 0, chnged FROM vfile WHERE vid=%d", | |
| 210 | + "INSERT OR IGNORE INTO fv(fn,fnt,idv,idt,ridv,ridt,isexe,chnged)" | |
| 211 | + " SELECT pathname, pathname, id, 0, rid, 0, isexe, chnged" | |
| 212 | + " FROM vfile WHERE vid=%d", | |
| 211 | 213 | vid |
| 212 | 214 | ); |
| 213 | 215 | |
| 214 | 216 | /* Compute file name changes on V->T. Record name changes in files that |
| 215 | 217 | ** have changed locally. |
| @@ -229,12 +231,12 @@ | ||
| 229 | 231 | |
| 230 | 232 | /* Add files found in the target version T but missing from the current |
| 231 | 233 | ** version V. |
| 232 | 234 | */ |
| 233 | 235 | db_multi_exec( |
| 234 | - "INSERT OR IGNORE INTO fv(fn,fnt,idv,idt,ridv,ridt,chnged)" | |
| 235 | - " SELECT pathname, pathname, 0, 0, 0, 0, 0 FROM vfile" | |
| 236 | + "INSERT OR IGNORE INTO fv(fn,fnt,idv,idt,ridv,ridt,isexe,chnged)" | |
| 237 | + " SELECT pathname, pathname, 0, 0, 0, 0, isexe, 0 FROM vfile" | |
| 236 | 238 | " WHERE vid=%d" |
| 237 | 239 | " AND pathname NOT IN (SELECT fnt FROM fv)", |
| 238 | 240 | tid |
| 239 | 241 | ); |
| 240 | 242 | |
| @@ -248,18 +250,19 @@ | ||
| 248 | 250 | tid, tid |
| 249 | 251 | ); |
| 250 | 252 | |
| 251 | 253 | if( debugFlag ){ |
| 252 | 254 | db_prepare(&q, |
| 253 | - "SELECT rowid, fn, fnt, chnged, ridv, ridt FROM fv" | |
| 255 | + "SELECT rowid, fn, fnt, chnged, ridv, ridt, isexe FROM fv" | |
| 254 | 256 | ); |
| 255 | 257 | while( db_step(&q)==SQLITE_ROW ){ |
| 256 | - printf("%3d: ridv=%-4d ridt=%-4d chnged=%d\n", | |
| 258 | + printf("%3d: ridv=%-4d ridt=%-4d chnged=%d isexe=%d\n", | |
| 257 | 259 | db_column_int(&q, 0), |
| 258 | 260 | db_column_int(&q, 4), |
| 259 | 261 | db_column_int(&q, 5), |
| 260 | - db_column_int(&q, 3)); | |
| 262 | + db_column_int(&q, 3), | |
| 263 | + db_column_int(&q, 6)); | |
| 261 | 264 | printf(" fnv = [%s]\n", db_column_text(&q, 1)); |
| 262 | 265 | printf(" fnt = [%s]\n", db_column_text(&q, 2)); |
| 263 | 266 | } |
| 264 | 267 | db_finalize(&q); |
| 265 | 268 | } |
| @@ -299,11 +302,11 @@ | ||
| 299 | 302 | /* |
| 300 | 303 | ** Alter the content of the checkout so that it conforms with the |
| 301 | 304 | ** target |
| 302 | 305 | */ |
| 303 | 306 | db_prepare(&q, |
| 304 | - "SELECT fn, idv, ridv, idt, ridt, chnged, fnt FROM fv ORDER BY 1" | |
| 307 | + "SELECT fn, idv, ridv, idt, ridt, chnged, fnt, isexe FROM fv ORDER BY 1" | |
| 305 | 308 | ); |
| 306 | 309 | db_prepare(&mtimeXfer, |
| 307 | 310 | "UPDATE vfile SET mtime=(SELECT mtime FROM vfile WHERE id=:idv)" |
| 308 | 311 | " WHERE id=:idt" |
| 309 | 312 | ); |
| @@ -316,10 +319,11 @@ | ||
| 316 | 319 | int ridv = db_column_int(&q, 2); /* RecordID for current */ |
| 317 | 320 | int idt = db_column_int(&q, 3); /* VFILE entry for target */ |
| 318 | 321 | int ridt = db_column_int(&q, 4); /* RecordID for target */ |
| 319 | 322 | int chnged = db_column_int(&q, 5); /* Current is edited */ |
| 320 | 323 | const char *zNewName = db_column_text(&q,6);/* New filename */ |
| 324 | + int isexe = db_column_int(&q, 6); /* EXE perm for new file */ | |
| 321 | 325 | char *zFullPath; /* Full pathname of the file */ |
| 322 | 326 | char *zFullNewPath; /* Full pathname of dest */ |
| 323 | 327 | char nameChng; /* True if the name changed */ |
| 324 | 328 | |
| 325 | 329 | zFullPath = mprintf("%s%s", g.zLocalRoot, zName); |
| @@ -374,17 +378,23 @@ | ||
| 374 | 378 | undo_save(zName); |
| 375 | 379 | content_get(ridt, &t); |
| 376 | 380 | content_get(ridv, &v); |
| 377 | 381 | rc = merge_3way(&v, zFullPath, &t, &r); |
| 378 | 382 | if( rc>=0 ){ |
| 379 | - if( !nochangeFlag ) blob_write_to_file(&r, zFullNewPath); | |
| 383 | + if( !nochangeFlag ){ | |
| 384 | + blob_write_to_file(&r, zFullNewPath); | |
| 385 | + file_setexe(zFullNewPath, isexe); | |
| 386 | + } | |
| 380 | 387 | if( rc>0 ){ |
| 381 | 388 | printf("***** %d merge conflicts in %s\n", rc, zNewName); |
| 382 | 389 | nConflict++; |
| 383 | 390 | } |
| 384 | 391 | }else{ |
| 385 | - if( !nochangeFlag ) blob_write_to_file(&t, zFullNewPath); | |
| 392 | + if( !nochangeFlag ){ | |
| 393 | + blob_write_to_file(&t, zFullNewPath); | |
| 394 | + file_setexe(zFullNewPath, isexe); | |
| 395 | + } | |
| 386 | 396 | printf("***** Cannot merge binary file %s\n", zNewName); |
| 387 | 397 | nConflict++; |
| 388 | 398 | } |
| 389 | 399 | if( nameChng && !nochangeFlag ) unlink(zFullPath); |
| 390 | 400 | blob_reset(&v); |
| @@ -554,33 +564,40 @@ | ||
| 554 | 564 | int vid = db_lget_int("checkout", 0); |
| 555 | 565 | zRevision = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", vid); |
| 556 | 566 | } |
| 557 | 567 | while( db_step(&q)==SQLITE_ROW ){ |
| 558 | 568 | int isExe = 0; |
| 569 | + char *zFull; | |
| 559 | 570 | zFile = db_column_text(&q, 0); |
| 571 | + zFull = mprintf("%/%/", g.zLocalRoot, zFile); | |
| 560 | 572 | errCode = historical_version_of_file(zRevision, zFile, &record, &isExe,2); |
| 561 | 573 | if( errCode==2 ){ |
| 562 | - fossil_warning("file not in repository: %s", zFile); | |
| 574 | + if( db_int(0, "SELECT rid FROM vfile WHERE pathname=%Q", zFile)==0 ){ | |
| 575 | + printf("UNMANAGE: %s\n", zFile); | |
| 576 | + }else{ | |
| 577 | + undo_save(zFile); | |
| 578 | + unlink(zFull); | |
| 579 | + printf("DELETE: %s\n", zFile); | |
| 580 | + } | |
| 581 | + db_multi_exec("DELETE FROM vfile WHERE pathname=%Q", zFile); | |
| 563 | 582 | }else{ |
| 564 | - char *zFull = mprintf("%/%/", g.zLocalRoot, zFile); | |
| 583 | + sqlite3_int64 mtime; | |
| 565 | 584 | undo_save(zFile); |
| 566 | 585 | blob_write_to_file(&record, zFull); |
| 567 | 586 | file_setexe(zFull, isExe); |
| 568 | 587 | printf("REVERTED: %s\n", zFile); |
| 569 | - if( zRevision==0 ){ | |
| 570 | - sqlite3_int64 mtime = file_mtime(zFull); | |
| 571 | - db_multi_exec( | |
| 572 | - "UPDATE vfile" | |
| 573 | - " SET mtime=%lld, chnged=0, deleted=0, isexe=%d," | |
| 574 | - " pathname=coalesce(origname,pathname), origname=NULL" | |
| 575 | - " WHERE pathname=%Q", | |
| 576 | - mtime, isExe, zFile | |
| 577 | - ); | |
| 578 | - } | |
| 579 | - free(zFull); | |
| 588 | + mtime = file_mtime(zFull); | |
| 589 | + db_multi_exec( | |
| 590 | + "UPDATE vfile" | |
| 591 | + " SET mtime=%lld, chnged=0, deleted=0, isexe=%d, mrid=rid," | |
| 592 | + " pathname=coalesce(origname,pathname), origname=NULL" | |
| 593 | + " WHERE pathname=%Q", | |
| 594 | + mtime, isExe, zFile | |
| 595 | + ); | |
| 580 | 596 | } |
| 581 | 597 | blob_reset(&record); |
| 598 | + free(zFull); | |
| 582 | 599 | } |
| 583 | 600 | db_finalize(&q); |
| 584 | 601 | undo_finish(); |
| 585 | 602 | db_end_transaction(0); |
| 586 | 603 | } |
| 587 | 604 |
| --- src/update.c | |
| +++ src/update.c | |
| @@ -197,19 +197,21 @@ | |
| 197 | " idv INTEGER," /* VFILE entry for current version */ |
| 198 | " idt INTEGER," /* VFILE entry for target version */ |
| 199 | " chnged BOOLEAN," /* True if current version has been edited */ |
| 200 | " ridv INTEGER," /* Record ID for current version */ |
| 201 | " ridt INTEGER," /* Record ID for target */ |
| 202 | " fnt TEXT" /* Filename of same file on target version */ |
| 203 | ");" |
| 204 | ); |
| 205 | |
| 206 | /* Add files found in the current version |
| 207 | */ |
| 208 | db_multi_exec( |
| 209 | "INSERT OR IGNORE INTO fv(fn,fnt,idv,idt,ridv,ridt,chnged)" |
| 210 | " SELECT pathname, pathname, id, 0, rid, 0, chnged FROM vfile WHERE vid=%d", |
| 211 | vid |
| 212 | ); |
| 213 | |
| 214 | /* Compute file name changes on V->T. Record name changes in files that |
| 215 | ** have changed locally. |
| @@ -229,12 +231,12 @@ | |
| 229 | |
| 230 | /* Add files found in the target version T but missing from the current |
| 231 | ** version V. |
| 232 | */ |
| 233 | db_multi_exec( |
| 234 | "INSERT OR IGNORE INTO fv(fn,fnt,idv,idt,ridv,ridt,chnged)" |
| 235 | " SELECT pathname, pathname, 0, 0, 0, 0, 0 FROM vfile" |
| 236 | " WHERE vid=%d" |
| 237 | " AND pathname NOT IN (SELECT fnt FROM fv)", |
| 238 | tid |
| 239 | ); |
| 240 | |
| @@ -248,18 +250,19 @@ | |
| 248 | tid, tid |
| 249 | ); |
| 250 | |
| 251 | if( debugFlag ){ |
| 252 | db_prepare(&q, |
| 253 | "SELECT rowid, fn, fnt, chnged, ridv, ridt FROM fv" |
| 254 | ); |
| 255 | while( db_step(&q)==SQLITE_ROW ){ |
| 256 | printf("%3d: ridv=%-4d ridt=%-4d chnged=%d\n", |
| 257 | db_column_int(&q, 0), |
| 258 | db_column_int(&q, 4), |
| 259 | db_column_int(&q, 5), |
| 260 | db_column_int(&q, 3)); |
| 261 | printf(" fnv = [%s]\n", db_column_text(&q, 1)); |
| 262 | printf(" fnt = [%s]\n", db_column_text(&q, 2)); |
| 263 | } |
| 264 | db_finalize(&q); |
| 265 | } |
| @@ -299,11 +302,11 @@ | |
| 299 | /* |
| 300 | ** Alter the content of the checkout so that it conforms with the |
| 301 | ** target |
| 302 | */ |
| 303 | db_prepare(&q, |
| 304 | "SELECT fn, idv, ridv, idt, ridt, chnged, fnt FROM fv ORDER BY 1" |
| 305 | ); |
| 306 | db_prepare(&mtimeXfer, |
| 307 | "UPDATE vfile SET mtime=(SELECT mtime FROM vfile WHERE id=:idv)" |
| 308 | " WHERE id=:idt" |
| 309 | ); |
| @@ -316,10 +319,11 @@ | |
| 316 | int ridv = db_column_int(&q, 2); /* RecordID for current */ |
| 317 | int idt = db_column_int(&q, 3); /* VFILE entry for target */ |
| 318 | int ridt = db_column_int(&q, 4); /* RecordID for target */ |
| 319 | int chnged = db_column_int(&q, 5); /* Current is edited */ |
| 320 | const char *zNewName = db_column_text(&q,6);/* New filename */ |
| 321 | char *zFullPath; /* Full pathname of the file */ |
| 322 | char *zFullNewPath; /* Full pathname of dest */ |
| 323 | char nameChng; /* True if the name changed */ |
| 324 | |
| 325 | zFullPath = mprintf("%s%s", g.zLocalRoot, zName); |
| @@ -374,17 +378,23 @@ | |
| 374 | undo_save(zName); |
| 375 | content_get(ridt, &t); |
| 376 | content_get(ridv, &v); |
| 377 | rc = merge_3way(&v, zFullPath, &t, &r); |
| 378 | if( rc>=0 ){ |
| 379 | if( !nochangeFlag ) blob_write_to_file(&r, zFullNewPath); |
| 380 | if( rc>0 ){ |
| 381 | printf("***** %d merge conflicts in %s\n", rc, zNewName); |
| 382 | nConflict++; |
| 383 | } |
| 384 | }else{ |
| 385 | if( !nochangeFlag ) blob_write_to_file(&t, zFullNewPath); |
| 386 | printf("***** Cannot merge binary file %s\n", zNewName); |
| 387 | nConflict++; |
| 388 | } |
| 389 | if( nameChng && !nochangeFlag ) unlink(zFullPath); |
| 390 | blob_reset(&v); |
| @@ -554,33 +564,40 @@ | |
| 554 | int vid = db_lget_int("checkout", 0); |
| 555 | zRevision = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", vid); |
| 556 | } |
| 557 | while( db_step(&q)==SQLITE_ROW ){ |
| 558 | int isExe = 0; |
| 559 | zFile = db_column_text(&q, 0); |
| 560 | errCode = historical_version_of_file(zRevision, zFile, &record, &isExe,2); |
| 561 | if( errCode==2 ){ |
| 562 | fossil_warning("file not in repository: %s", zFile); |
| 563 | }else{ |
| 564 | char *zFull = mprintf("%/%/", g.zLocalRoot, zFile); |
| 565 | undo_save(zFile); |
| 566 | blob_write_to_file(&record, zFull); |
| 567 | file_setexe(zFull, isExe); |
| 568 | printf("REVERTED: %s\n", zFile); |
| 569 | if( zRevision==0 ){ |
| 570 | sqlite3_int64 mtime = file_mtime(zFull); |
| 571 | db_multi_exec( |
| 572 | "UPDATE vfile" |
| 573 | " SET mtime=%lld, chnged=0, deleted=0, isexe=%d," |
| 574 | " pathname=coalesce(origname,pathname), origname=NULL" |
| 575 | " WHERE pathname=%Q", |
| 576 | mtime, isExe, zFile |
| 577 | ); |
| 578 | } |
| 579 | free(zFull); |
| 580 | } |
| 581 | blob_reset(&record); |
| 582 | } |
| 583 | db_finalize(&q); |
| 584 | undo_finish(); |
| 585 | db_end_transaction(0); |
| 586 | } |
| 587 |
| --- src/update.c | |
| +++ src/update.c | |
| @@ -197,19 +197,21 @@ | |
| 197 | " idv INTEGER," /* VFILE entry for current version */ |
| 198 | " idt INTEGER," /* VFILE entry for target version */ |
| 199 | " chnged BOOLEAN," /* True if current version has been edited */ |
| 200 | " ridv INTEGER," /* Record ID for current version */ |
| 201 | " ridt INTEGER," /* Record ID for target */ |
| 202 | " isexe BOOLEAN," /* Does target have execute permission? */ |
| 203 | " fnt TEXT" /* Filename of same file on target version */ |
| 204 | ");" |
| 205 | ); |
| 206 | |
| 207 | /* Add files found in the current version |
| 208 | */ |
| 209 | db_multi_exec( |
| 210 | "INSERT OR IGNORE INTO fv(fn,fnt,idv,idt,ridv,ridt,isexe,chnged)" |
| 211 | " SELECT pathname, pathname, id, 0, rid, 0, isexe, chnged" |
| 212 | " FROM vfile WHERE vid=%d", |
| 213 | vid |
| 214 | ); |
| 215 | |
| 216 | /* Compute file name changes on V->T. Record name changes in files that |
| 217 | ** have changed locally. |
| @@ -229,12 +231,12 @@ | |
| 231 | |
| 232 | /* Add files found in the target version T but missing from the current |
| 233 | ** version V. |
| 234 | */ |
| 235 | db_multi_exec( |
| 236 | "INSERT OR IGNORE INTO fv(fn,fnt,idv,idt,ridv,ridt,isexe,chnged)" |
| 237 | " SELECT pathname, pathname, 0, 0, 0, 0, isexe, 0 FROM vfile" |
| 238 | " WHERE vid=%d" |
| 239 | " AND pathname NOT IN (SELECT fnt FROM fv)", |
| 240 | tid |
| 241 | ); |
| 242 | |
| @@ -248,18 +250,19 @@ | |
| 250 | tid, tid |
| 251 | ); |
| 252 | |
| 253 | if( debugFlag ){ |
| 254 | db_prepare(&q, |
| 255 | "SELECT rowid, fn, fnt, chnged, ridv, ridt, isexe FROM fv" |
| 256 | ); |
| 257 | while( db_step(&q)==SQLITE_ROW ){ |
| 258 | printf("%3d: ridv=%-4d ridt=%-4d chnged=%d isexe=%d\n", |
| 259 | db_column_int(&q, 0), |
| 260 | db_column_int(&q, 4), |
| 261 | db_column_int(&q, 5), |
| 262 | db_column_int(&q, 3), |
| 263 | db_column_int(&q, 6)); |
| 264 | printf(" fnv = [%s]\n", db_column_text(&q, 1)); |
| 265 | printf(" fnt = [%s]\n", db_column_text(&q, 2)); |
| 266 | } |
| 267 | db_finalize(&q); |
| 268 | } |
| @@ -299,11 +302,11 @@ | |
| 302 | /* |
| 303 | ** Alter the content of the checkout so that it conforms with the |
| 304 | ** target |
| 305 | */ |
| 306 | db_prepare(&q, |
| 307 | "SELECT fn, idv, ridv, idt, ridt, chnged, fnt, isexe FROM fv ORDER BY 1" |
| 308 | ); |
| 309 | db_prepare(&mtimeXfer, |
| 310 | "UPDATE vfile SET mtime=(SELECT mtime FROM vfile WHERE id=:idv)" |
| 311 | " WHERE id=:idt" |
| 312 | ); |
| @@ -316,10 +319,11 @@ | |
| 319 | int ridv = db_column_int(&q, 2); /* RecordID for current */ |
| 320 | int idt = db_column_int(&q, 3); /* VFILE entry for target */ |
| 321 | int ridt = db_column_int(&q, 4); /* RecordID for target */ |
| 322 | int chnged = db_column_int(&q, 5); /* Current is edited */ |
| 323 | const char *zNewName = db_column_text(&q,6);/* New filename */ |
| 324 | int isexe = db_column_int(&q, 6); /* EXE perm for new file */ |
| 325 | char *zFullPath; /* Full pathname of the file */ |
| 326 | char *zFullNewPath; /* Full pathname of dest */ |
| 327 | char nameChng; /* True if the name changed */ |
| 328 | |
| 329 | zFullPath = mprintf("%s%s", g.zLocalRoot, zName); |
| @@ -374,17 +378,23 @@ | |
| 378 | undo_save(zName); |
| 379 | content_get(ridt, &t); |
| 380 | content_get(ridv, &v); |
| 381 | rc = merge_3way(&v, zFullPath, &t, &r); |
| 382 | if( rc>=0 ){ |
| 383 | if( !nochangeFlag ){ |
| 384 | blob_write_to_file(&r, zFullNewPath); |
| 385 | file_setexe(zFullNewPath, isexe); |
| 386 | } |
| 387 | if( rc>0 ){ |
| 388 | printf("***** %d merge conflicts in %s\n", rc, zNewName); |
| 389 | nConflict++; |
| 390 | } |
| 391 | }else{ |
| 392 | if( !nochangeFlag ){ |
| 393 | blob_write_to_file(&t, zFullNewPath); |
| 394 | file_setexe(zFullNewPath, isexe); |
| 395 | } |
| 396 | printf("***** Cannot merge binary file %s\n", zNewName); |
| 397 | nConflict++; |
| 398 | } |
| 399 | if( nameChng && !nochangeFlag ) unlink(zFullPath); |
| 400 | blob_reset(&v); |
| @@ -554,33 +564,40 @@ | |
| 564 | int vid = db_lget_int("checkout", 0); |
| 565 | zRevision = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", vid); |
| 566 | } |
| 567 | while( db_step(&q)==SQLITE_ROW ){ |
| 568 | int isExe = 0; |
| 569 | char *zFull; |
| 570 | zFile = db_column_text(&q, 0); |
| 571 | zFull = mprintf("%/%/", g.zLocalRoot, zFile); |
| 572 | errCode = historical_version_of_file(zRevision, zFile, &record, &isExe,2); |
| 573 | if( errCode==2 ){ |
| 574 | if( db_int(0, "SELECT rid FROM vfile WHERE pathname=%Q", zFile)==0 ){ |
| 575 | printf("UNMANAGE: %s\n", zFile); |
| 576 | }else{ |
| 577 | undo_save(zFile); |
| 578 | unlink(zFull); |
| 579 | printf("DELETE: %s\n", zFile); |
| 580 | } |
| 581 | db_multi_exec("DELETE FROM vfile WHERE pathname=%Q", zFile); |
| 582 | }else{ |
| 583 | sqlite3_int64 mtime; |
| 584 | undo_save(zFile); |
| 585 | blob_write_to_file(&record, zFull); |
| 586 | file_setexe(zFull, isExe); |
| 587 | printf("REVERTED: %s\n", zFile); |
| 588 | mtime = file_mtime(zFull); |
| 589 | db_multi_exec( |
| 590 | "UPDATE vfile" |
| 591 | " SET mtime=%lld, chnged=0, deleted=0, isexe=%d, mrid=rid," |
| 592 | " pathname=coalesce(origname,pathname), origname=NULL" |
| 593 | " WHERE pathname=%Q", |
| 594 | mtime, isExe, zFile |
| 595 | ); |
| 596 | } |
| 597 | blob_reset(&record); |
| 598 | free(zFull); |
| 599 | } |
| 600 | db_finalize(&q); |
| 601 | undo_finish(); |
| 602 | db_end_transaction(0); |
| 603 | } |
| 604 |
+12
-5
| --- src/vfile.c | ||
| +++ src/vfile.c | ||
| @@ -85,21 +85,22 @@ | ||
| 85 | 85 | db_begin_transaction(); |
| 86 | 86 | p = manifest_get(vid, CFTYPE_MANIFEST); |
| 87 | 87 | if( p==0 ) return; |
| 88 | 88 | db_multi_exec("DELETE FROM vfile WHERE vid=%d", vid); |
| 89 | 89 | db_prepare(&ins, |
| 90 | - "INSERT INTO vfile(vid,rid,mrid,pathname) " | |
| 91 | - " VALUES(:vid,:id,:id,:name)"); | |
| 90 | + "INSERT INTO vfile(vid,isexe,rid,mrid,pathname) " | |
| 91 | + " VALUES(:vid,:isexe,:id,:id,:name)"); | |
| 92 | 92 | db_bind_int(&ins, ":vid", vid); |
| 93 | 93 | manifest_file_rewind(p); |
| 94 | 94 | while( (pFile = manifest_file_next(p,0))!=0 ){ |
| 95 | 95 | if( pFile->zUuid==0 || uuid_is_shunned(pFile->zUuid) ) continue; |
| 96 | 96 | rid = uuid_to_rid(pFile->zUuid, 0); |
| 97 | 97 | if( rid==0 || content_size(rid, -1)<0 ){ |
| 98 | 98 | fossil_warning("content missing for %s", pFile->zName); |
| 99 | 99 | continue; |
| 100 | 100 | } |
| 101 | + db_bind_int(&ins, ":isexe", manifest_file_mperm(pFile)); | |
| 101 | 102 | db_bind_int(&ins, ":id", rid); |
| 102 | 103 | db_bind_text(&ins, ":name", pFile->zName); |
| 103 | 104 | db_step(&ins); |
| 104 | 105 | db_reset(&ins); |
| 105 | 106 | } |
| @@ -207,31 +208,36 @@ | ||
| 207 | 208 | Stmt q; |
| 208 | 209 | Blob content; |
| 209 | 210 | int nRepos = strlen(g.zLocalRoot); |
| 210 | 211 | |
| 211 | 212 | if( vid>0 && id==0 ){ |
| 212 | - db_prepare(&q, "SELECT id, %Q || pathname, mrid" | |
| 213 | + db_prepare(&q, "SELECT id, %Q || pathname, mrid, isexe" | |
| 213 | 214 | " FROM vfile" |
| 214 | 215 | " WHERE vid=%d AND mrid>0", |
| 215 | 216 | g.zLocalRoot, vid); |
| 216 | 217 | }else{ |
| 217 | 218 | assert( vid==0 && id>0 ); |
| 218 | - db_prepare(&q, "SELECT id, %Q || pathname, mrid" | |
| 219 | + db_prepare(&q, "SELECT id, %Q || pathname, mrid, isexe" | |
| 219 | 220 | " FROM vfile" |
| 220 | 221 | " WHERE id=%d AND mrid>0", |
| 221 | 222 | g.zLocalRoot, id); |
| 222 | 223 | } |
| 223 | 224 | while( db_step(&q)==SQLITE_ROW ){ |
| 224 | - int id, rid; | |
| 225 | + int id, rid, isExe; | |
| 225 | 226 | const char *zName; |
| 226 | 227 | |
| 227 | 228 | id = db_column_int(&q, 0); |
| 228 | 229 | zName = db_column_text(&q, 1); |
| 229 | 230 | rid = db_column_int(&q, 2); |
| 231 | + isExe = db_column_int(&q, 3); | |
| 230 | 232 | content_get(rid, &content); |
| 231 | 233 | if( file_is_the_same(&content, zName) ){ |
| 232 | 234 | blob_reset(&content); |
| 235 | + if( file_setexe(zName, isExe) ){ | |
| 236 | + db_multi_exec("UPDATE vfile SET mtime=%lld WHERE id=%d", | |
| 237 | + file_mtime(zName), id); | |
| 238 | + } | |
| 233 | 239 | continue; |
| 234 | 240 | } |
| 235 | 241 | if( promptFlag && file_size(zName)>=0 ){ |
| 236 | 242 | Blob ans; |
| 237 | 243 | char *zMsg; |
| @@ -250,10 +256,11 @@ | ||
| 250 | 256 | continue; |
| 251 | 257 | } |
| 252 | 258 | } |
| 253 | 259 | if( verbose ) printf("%s\n", &zName[nRepos]); |
| 254 | 260 | blob_write_to_file(&content, zName); |
| 261 | + file_setexe(zName, isExe); | |
| 255 | 262 | blob_reset(&content); |
| 256 | 263 | db_multi_exec("UPDATE vfile SET mtime=%lld WHERE id=%d", |
| 257 | 264 | file_mtime(zName), id); |
| 258 | 265 | } |
| 259 | 266 | db_finalize(&q); |
| 260 | 267 |
| --- src/vfile.c | |
| +++ src/vfile.c | |
| @@ -85,21 +85,22 @@ | |
| 85 | db_begin_transaction(); |
| 86 | p = manifest_get(vid, CFTYPE_MANIFEST); |
| 87 | if( p==0 ) return; |
| 88 | db_multi_exec("DELETE FROM vfile WHERE vid=%d", vid); |
| 89 | db_prepare(&ins, |
| 90 | "INSERT INTO vfile(vid,rid,mrid,pathname) " |
| 91 | " VALUES(:vid,:id,:id,:name)"); |
| 92 | db_bind_int(&ins, ":vid", vid); |
| 93 | manifest_file_rewind(p); |
| 94 | while( (pFile = manifest_file_next(p,0))!=0 ){ |
| 95 | if( pFile->zUuid==0 || uuid_is_shunned(pFile->zUuid) ) continue; |
| 96 | rid = uuid_to_rid(pFile->zUuid, 0); |
| 97 | if( rid==0 || content_size(rid, -1)<0 ){ |
| 98 | fossil_warning("content missing for %s", pFile->zName); |
| 99 | continue; |
| 100 | } |
| 101 | db_bind_int(&ins, ":id", rid); |
| 102 | db_bind_text(&ins, ":name", pFile->zName); |
| 103 | db_step(&ins); |
| 104 | db_reset(&ins); |
| 105 | } |
| @@ -207,31 +208,36 @@ | |
| 207 | Stmt q; |
| 208 | Blob content; |
| 209 | int nRepos = strlen(g.zLocalRoot); |
| 210 | |
| 211 | if( vid>0 && id==0 ){ |
| 212 | db_prepare(&q, "SELECT id, %Q || pathname, mrid" |
| 213 | " FROM vfile" |
| 214 | " WHERE vid=%d AND mrid>0", |
| 215 | g.zLocalRoot, vid); |
| 216 | }else{ |
| 217 | assert( vid==0 && id>0 ); |
| 218 | db_prepare(&q, "SELECT id, %Q || pathname, mrid" |
| 219 | " FROM vfile" |
| 220 | " WHERE id=%d AND mrid>0", |
| 221 | g.zLocalRoot, id); |
| 222 | } |
| 223 | while( db_step(&q)==SQLITE_ROW ){ |
| 224 | int id, rid; |
| 225 | const char *zName; |
| 226 | |
| 227 | id = db_column_int(&q, 0); |
| 228 | zName = db_column_text(&q, 1); |
| 229 | rid = db_column_int(&q, 2); |
| 230 | content_get(rid, &content); |
| 231 | if( file_is_the_same(&content, zName) ){ |
| 232 | blob_reset(&content); |
| 233 | continue; |
| 234 | } |
| 235 | if( promptFlag && file_size(zName)>=0 ){ |
| 236 | Blob ans; |
| 237 | char *zMsg; |
| @@ -250,10 +256,11 @@ | |
| 250 | continue; |
| 251 | } |
| 252 | } |
| 253 | if( verbose ) printf("%s\n", &zName[nRepos]); |
| 254 | blob_write_to_file(&content, zName); |
| 255 | blob_reset(&content); |
| 256 | db_multi_exec("UPDATE vfile SET mtime=%lld WHERE id=%d", |
| 257 | file_mtime(zName), id); |
| 258 | } |
| 259 | db_finalize(&q); |
| 260 |
| --- src/vfile.c | |
| +++ src/vfile.c | |
| @@ -85,21 +85,22 @@ | |
| 85 | db_begin_transaction(); |
| 86 | p = manifest_get(vid, CFTYPE_MANIFEST); |
| 87 | if( p==0 ) return; |
| 88 | db_multi_exec("DELETE FROM vfile WHERE vid=%d", vid); |
| 89 | db_prepare(&ins, |
| 90 | "INSERT INTO vfile(vid,isexe,rid,mrid,pathname) " |
| 91 | " VALUES(:vid,:isexe,:id,:id,:name)"); |
| 92 | db_bind_int(&ins, ":vid", vid); |
| 93 | manifest_file_rewind(p); |
| 94 | while( (pFile = manifest_file_next(p,0))!=0 ){ |
| 95 | if( pFile->zUuid==0 || uuid_is_shunned(pFile->zUuid) ) continue; |
| 96 | rid = uuid_to_rid(pFile->zUuid, 0); |
| 97 | if( rid==0 || content_size(rid, -1)<0 ){ |
| 98 | fossil_warning("content missing for %s", pFile->zName); |
| 99 | continue; |
| 100 | } |
| 101 | db_bind_int(&ins, ":isexe", manifest_file_mperm(pFile)); |
| 102 | db_bind_int(&ins, ":id", rid); |
| 103 | db_bind_text(&ins, ":name", pFile->zName); |
| 104 | db_step(&ins); |
| 105 | db_reset(&ins); |
| 106 | } |
| @@ -207,31 +208,36 @@ | |
| 208 | Stmt q; |
| 209 | Blob content; |
| 210 | int nRepos = strlen(g.zLocalRoot); |
| 211 | |
| 212 | if( vid>0 && id==0 ){ |
| 213 | db_prepare(&q, "SELECT id, %Q || pathname, mrid, isexe" |
| 214 | " FROM vfile" |
| 215 | " WHERE vid=%d AND mrid>0", |
| 216 | g.zLocalRoot, vid); |
| 217 | }else{ |
| 218 | assert( vid==0 && id>0 ); |
| 219 | db_prepare(&q, "SELECT id, %Q || pathname, mrid, isexe" |
| 220 | " FROM vfile" |
| 221 | " WHERE id=%d AND mrid>0", |
| 222 | g.zLocalRoot, id); |
| 223 | } |
| 224 | while( db_step(&q)==SQLITE_ROW ){ |
| 225 | int id, rid, isExe; |
| 226 | const char *zName; |
| 227 | |
| 228 | id = db_column_int(&q, 0); |
| 229 | zName = db_column_text(&q, 1); |
| 230 | rid = db_column_int(&q, 2); |
| 231 | isExe = db_column_int(&q, 3); |
| 232 | content_get(rid, &content); |
| 233 | if( file_is_the_same(&content, zName) ){ |
| 234 | blob_reset(&content); |
| 235 | if( file_setexe(zName, isExe) ){ |
| 236 | db_multi_exec("UPDATE vfile SET mtime=%lld WHERE id=%d", |
| 237 | file_mtime(zName), id); |
| 238 | } |
| 239 | continue; |
| 240 | } |
| 241 | if( promptFlag && file_size(zName)>=0 ){ |
| 242 | Blob ans; |
| 243 | char *zMsg; |
| @@ -250,10 +256,11 @@ | |
| 256 | continue; |
| 257 | } |
| 258 | } |
| 259 | if( verbose ) printf("%s\n", &zName[nRepos]); |
| 260 | blob_write_to_file(&content, zName); |
| 261 | file_setexe(zName, isExe); |
| 262 | blob_reset(&content); |
| 263 | db_multi_exec("UPDATE vfile SET mtime=%lld WHERE id=%d", |
| 264 | file_mtime(zName), id); |
| 265 | } |
| 266 | db_finalize(&q); |
| 267 |