Fossil SCM
Add workaround code
Commit
9d5de8d702e8b00c81ecdf76be308f803cdd70f5
Parent
ec9480fcba01677…
2 files changed
+76
-44
+10
-2
+76
-44
| --- src/checkin.c | ||
| +++ src/checkin.c | ||
| @@ -27,35 +27,37 @@ | ||
| 27 | 27 | */ |
| 28 | 28 | enum { |
| 29 | 29 | /* Zero-based bit indexes. */ |
| 30 | 30 | CB_EDITED , CB_UPDATED , CB_CHANGED, CB_MISSING , CB_ADDED, CB_DELETED, |
| 31 | 31 | CB_RENAMED, CB_CONFLICT, CB_META , CB_UNCHANGED, CB_EXTRA, CB_MERGE , |
| 32 | - CB_RELPATH, CB_CLASSIFY, CB_FATAL , CB_COMMENT , | |
| 32 | + CB_RELPATH, CB_CLASSIFY, CB_MTIME , CB_SIZE , CB_FATAL, CB_COMMENT, | |
| 33 | 33 | |
| 34 | 34 | /* Bitmask values. */ |
| 35 | - C_EDITED = 1 << CB_EDITED, /* Edited, merged, and conflicted files. */ | |
| 36 | - C_UPDATED = 1 << CB_UPDATED, /* Files updated by merge/integrate. */ | |
| 37 | - C_CHANGED = 1 << CB_CHANGED, /* Treated the same as the above two. */ | |
| 38 | - C_MISSING = 1 << CB_MISSING, /* Missing and non- files. */ | |
| 39 | - C_ADDED = 1 << CB_ADDED, /* Added files. */ | |
| 40 | - C_DELETED = 1 << CB_DELETED, /* Deleted files. */ | |
| 41 | - C_RENAMED = 1 << CB_RENAMED, /* Renamed files. */ | |
| 42 | - C_CONFLICT = 1 << CB_CONFLICT, /* Files having merge conflicts. */ | |
| 43 | - C_META = 1 << CB_META, /* Files with metadata changes. */ | |
| 44 | - C_UNCHANGED = 1 << CB_UNCHANGED, /* Unchanged files. */ | |
| 45 | - C_EXTRA = 1 << CB_EXTRA, /* Unmanaged files. */ | |
| 46 | - C_MERGE = 1 << CB_MERGE, /* Merge contributors. */ | |
| 47 | - C_FILTER = C_EDITED | C_UPDATED | C_CHANGED | C_MISSING | C_ADDED | |
| 48 | - | C_DELETED | C_RENAMED | C_CONFLICT | C_META | C_UNCHANGED | |
| 49 | - | C_EXTRA | C_MERGE, /* All filter bits. */ | |
| 50 | - C_ALL = C_FILTER & ~(C_EXTRA | C_MERGE), /* All managed files. */ | |
| 51 | - C_DIFFER = C_FILTER & ~(C_UNCHANGED | C_MERGE), /* All differences. */ | |
| 52 | - C_RELPATH = 1 << CB_RELPATH, /* Show relative paths. */ | |
| 53 | - C_CLASSIFY = 1 << CB_CLASSIFY, /* Show file change types. */ | |
| 54 | - C_DEFAULT = (C_ALL & ~C_UNCHANGED) | C_MERGE | C_CLASSIFY, | |
| 55 | - C_FATAL = (1 << CB_FATAL) | C_MISSING, /* Fail on MISSING/NOT_A_FILE. */ | |
| 56 | - C_COMMENT = 1 << CB_COMMENT, /* Precede each line with "# ". */ | |
| 35 | + C_EDITED = 1 << CB_EDITED, /* Edited, merged, and conflicted files. */ | |
| 36 | + C_UPDATED = 1 << CB_UPDATED, /* Files updated by merge/integrate. */ | |
| 37 | + C_CHANGED = 1 << CB_CHANGED, /* Treated the same as the above two. */ | |
| 38 | + C_MISSING = 1 << CB_MISSING, /* Missing and non- files. */ | |
| 39 | + C_ADDED = 1 << CB_ADDED, /* Added files. */ | |
| 40 | + C_DELETED = 1 << CB_DELETED, /* Deleted files. */ | |
| 41 | + C_RENAMED = 1 << CB_RENAMED, /* Renamed files. */ | |
| 42 | + C_CONFLICT = 1 << CB_CONFLICT, /* Files having merge conflicts. */ | |
| 43 | + C_META = 1 << CB_META, /* Files with metadata changes. */ | |
| 44 | + C_UNCHANGED = 1 << CB_UNCHANGED, /* Unchanged files. */ | |
| 45 | + C_EXTRA = 1 << CB_EXTRA, /* Unmanaged files. */ | |
| 46 | + C_MERGE = 1 << CB_MERGE, /* Merge contributors. */ | |
| 47 | + C_FILTER = C_EDITED | C_UPDATED | C_CHANGED | C_MISSING | C_ADDED | |
| 48 | + | C_DELETED | C_RENAMED | C_CONFLICT | C_META | C_UNCHANGED | |
| 49 | + | C_EXTRA | C_MERGE, /* All filter bits. */ | |
| 50 | + C_ALL = C_FILTER & ~(C_EXTRA | C_MERGE),/* All managed files. */ | |
| 51 | + C_DIFFER = C_FILTER & ~(C_UNCHANGED | C_MERGE),/* All differences. */ | |
| 52 | + C_RELPATH = 1 << CB_RELPATH, /* Show relative paths. */ | |
| 53 | + C_CLASSIFY = 1 << CB_CLASSIFY, /* Show file change types. */ | |
| 54 | + C_DEFAULT = (C_ALL & ~C_UNCHANGED) | C_MERGE | C_CLASSIFY, | |
| 55 | + C_MTIME = 1 << CB_MTIME, /* Show file modification time. */ | |
| 56 | + C_SIZE = 1 << CB_SIZE, /* Show file size in bytes. */ | |
| 57 | + C_FATAL = (1 << CB_FATAL) | C_MISSING, /* Fail on MISSING/NOT_A_FILE. */ | |
| 58 | + C_COMMENT = 1 << CB_COMMENT, /* Precede each line with "# ". */ | |
| 57 | 59 | }; |
| 58 | 60 | |
| 59 | 61 | /* |
| 60 | 62 | ** Create a TEMP table named SFILE and add all unmanaged files named on |
| 61 | 63 | ** the command-line to that table. If directories are named, then add |
| @@ -73,12 +75,12 @@ | ||
| 73 | 75 | char *zName; /* Name of a candidate file or directory */ |
| 74 | 76 | int isDir; /* 1 for a directory, 0 if doesn't exist, 2 for anything else */ |
| 75 | 77 | int i; /* Loop counter */ |
| 76 | 78 | int nRoot; /* length of g.zLocalRoot */ |
| 77 | 79 | |
| 78 | - db_multi_exec("CREATE TEMP TABLE sfile(pathname TEXT PRIMARY KEY %s)", | |
| 79 | - filename_collation()); | |
| 80 | + db_multi_exec("CREATE TEMP TABLE sfile(pathname TEXT PRIMARY KEY %s," | |
| 81 | + " mtime INTEGER, size INTEGER)", filename_collation()); | |
| 80 | 82 | nRoot = (int)strlen(g.zLocalRoot); |
| 81 | 83 | if( argc==0 ){ |
| 82 | 84 | blob_init(&name, g.zLocalRoot, nRoot - 1); |
| 83 | 85 | vfile_scan(&name, blob_size(&name), scanFlags, pIgnore, 0); |
| 84 | 86 | blob_reset(&name); |
| @@ -142,14 +144,18 @@ | ||
| 142 | 144 | /* Obtain the list of managed files if appropriate. */ |
| 143 | 145 | blob_zero(&sql); |
| 144 | 146 | if( flags & C_ALL ){ |
| 145 | 147 | /* Start with a list of all managed files. */ |
| 146 | 148 | blob_append_sql(&sql, |
| 147 | - "SELECT pathname, deleted, chnged, rid," | |
| 149 | + "SELECT pathname, %s as mtime, %s as size, deleted, chnged, rid," | |
| 148 | 150 | " coalesce(origname!=pathname,0) AS renamed, islink, 1 AS managed" |
| 149 | - " FROM vfile" | |
| 150 | - " WHERE is_selected(id)%s", blob_sql_text(&where)); | |
| 151 | + " FROM vfile, blob USING (rid)" | |
| 152 | + " WHERE is_selected(id)%s", | |
| 153 | + flags & C_MTIME ? "datetime(checkin_mtime(:vid, rid), " | |
| 154 | + "'unixepoch', toLocal())" : "''" /*safe-for-%s*/, | |
| 155 | + flags & C_SIZE ? "blob.size" : "0" /*safe-for-%s*/, | |
| 156 | + blob_sql_text(&where)); | |
| 151 | 157 | |
| 152 | 158 | /* Exclude unchanged files unless requested. */ |
| 153 | 159 | if( !(flags & C_UNCHANGED) ){ |
| 154 | 160 | blob_append_sql(&sql, |
| 155 | 161 | " AND (chnged OR deleted OR rid=0 OR pathname!=origname)"); |
| @@ -159,32 +165,56 @@ | ||
| 159 | 165 | /* If C_EXTRA, add unmanaged files to the query result too. */ |
| 160 | 166 | if( flags & C_EXTRA ){ |
| 161 | 167 | if( blob_size(&sql) ){ |
| 162 | 168 | blob_append_sql(&sql, " UNION ALL"); |
| 163 | 169 | } |
| 164 | - blob_append_sql(&sql, " SELECT pathname, 0, 0, 0, 0, 0, 0" | |
| 165 | - " FROM sfile WHERE pathname NOT IN (%s)%s", | |
| 166 | - fossil_all_reserved_names(0), blob_sql_text(&where)); | |
| 170 | + blob_append_sql(&sql, | |
| 171 | + " SELECT pathname, %s, %s, 0, 0, 0, 0, 0, 0" | |
| 172 | + " FROM sfile WHERE pathname NOT IN (%s)%s", | |
| 173 | + flags & C_MTIME ? "datetime(mtime, 'unixepoch', toLocal())" : "''", | |
| 174 | + flags & C_SIZE ? "size" : "0", | |
| 175 | + fossil_all_reserved_names(0), blob_sql_text(&where)); | |
| 167 | 176 | } |
| 168 | 177 | |
| 178 | +#if 1 | |
| 179 | + /* SQLITE BUG WORKAROUND??? */ | |
| 180 | + /* If I step the query sans the ORDER BY clause, then I can run the full query | |
| 181 | + * without incident. But if I delete this workaround and run the query | |
| 182 | + * normally, I get SQLITE_ABORT due to ROLLBACK, which makes no sense. */ | |
| 183 | + db_prepare(&q, "%s", blob_sql_text(&sql)); | |
| 184 | + if( (flags & C_ALL) && (flags & C_MTIME) ){ | |
| 185 | + db_bind_int(&q, ":vid", db_lget_int("checkout", 0)); | |
| 186 | + } | |
| 187 | + db_step(&q); | |
| 188 | + db_finalize(&q); | |
| 189 | + /* SQLITE BUG WORKAROUND??? */ | |
| 190 | +#endif | |
| 191 | + | |
| 169 | 192 | /* Append an ORDER BY clause then compile the query. */ |
| 170 | 193 | blob_append_sql(&sql, " ORDER BY pathname"); |
| 171 | 194 | db_prepare(&q, "%s", blob_sql_text(&sql)); |
| 172 | 195 | blob_reset(&sql); |
| 173 | 196 | blob_reset(&where); |
| 197 | + | |
| 198 | + /* Bind the checkout version ID to the query if needed. */ | |
| 199 | + if( (flags & C_ALL) && (flags & C_MTIME) ){ | |
| 200 | + db_bind_int(&q, ":vid", db_lget_int("checkout", 0)); | |
| 201 | + } | |
| 174 | 202 | |
| 175 | 203 | /* Execute the query and assemble the report. */ |
| 176 | 204 | blob_zero(&rewrittenPathname); |
| 177 | 205 | while( db_step(&q)==SQLITE_ROW ){ |
| 178 | 206 | const char *zPathname = db_column_text(&q, 0); |
| 179 | 207 | const char *zClass = 0; |
| 180 | - int isManaged = db_column_int(&q, 6); | |
| 181 | - int isDeleted = db_column_int(&q, 1); | |
| 182 | - int isChnged = db_column_int(&q, 2); | |
| 183 | - int isNew = isManaged && !db_column_int(&q, 3); | |
| 184 | - int isRenamed = db_column_int(&q, 4); | |
| 185 | - int isLink = db_column_int(&q, 5); | |
| 208 | + int isManaged = db_column_int(&q, 8); | |
| 209 | + const char *zMtime = db_column_text(&q, 1); | |
| 210 | + int size = db_column_int(&q, 2); | |
| 211 | + int isDeleted = db_column_int(&q, 3); | |
| 212 | + int isChnged = db_column_int(&q, 4); | |
| 213 | + int isNew = isManaged && !db_column_int(&q, 5); | |
| 214 | + int isRenamed = db_column_int(&q, 6); | |
| 215 | + int isLink = db_column_int(&q, 7); | |
| 186 | 216 | char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname); |
| 187 | 217 | int isMissing = !file_wd_isfile_or_link(zFullName); |
| 188 | 218 | |
| 189 | 219 | /* Determine the file change classification, if any. */ |
| 190 | 220 | if( (flags & C_DELETED) && isDeleted ){ |
| @@ -236,21 +266,23 @@ | ||
| 236 | 266 | zClass = "EXTRA"; |
| 237 | 267 | } |
| 238 | 268 | |
| 239 | 269 | /* Only report files for which a change classification was determined. */ |
| 240 | 270 | if( zClass ){ |
| 241 | - /* If C_COMMENT, precede each line with "# ". */ | |
| 242 | 271 | if( flags & C_COMMENT ){ |
| 243 | 272 | blob_append(report, "# ", 2); |
| 244 | 273 | } |
| 245 | - | |
| 246 | - /* If C_CLASSIFY, include the change classification. */ | |
| 247 | 274 | if( flags & C_CLASSIFY ){ |
| 248 | 275 | blob_appendf(report, "%-10s ", zClass); |
| 249 | 276 | } |
| 250 | - | |
| 251 | - /* Finish with the filename followed by newline. */ | |
| 277 | + if( flags & C_MTIME ){ | |
| 278 | + blob_append(report, zMtime, -1); | |
| 279 | + blob_append(report, " ", 2); | |
| 280 | + } | |
| 281 | + if( flags & C_SIZE ){ | |
| 282 | + blob_appendf(report, "%7d ", size); | |
| 283 | + } | |
| 252 | 284 | if( flags & C_RELPATH ){ |
| 253 | 285 | /* If C_RELPATH, display paths relative to current directory. */ |
| 254 | 286 | const char *zDisplayName; |
| 255 | 287 | file_relative_name(zFullName, &rewrittenPathname, 0); |
| 256 | 288 | zDisplayName = blob_str(&rewrittenPathname); |
| @@ -498,11 +530,11 @@ | ||
| 498 | 530 | vfile_check_signature(vid, useSha1sum ? CKSIG_SHA1 : 0); |
| 499 | 531 | |
| 500 | 532 | /* Search for unmanaged files if requested. */ |
| 501 | 533 | if( flags & C_EXTRA ){ |
| 502 | 534 | Glob *pIgnore = glob_create(zIgnoreFlag); |
| 503 | - locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags, pIgnore); | |
| 535 | + locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags | SCAN_META, pIgnore); | |
| 504 | 536 | glob_free(pIgnore); |
| 505 | 537 | } |
| 506 | 538 | |
| 507 | 539 | /* The status command prints general information before the change list. */ |
| 508 | 540 | if( command==STATUS ){ |
| @@ -517,11 +549,11 @@ | ||
| 517 | 549 | db_record_repository_filename(0); |
| 518 | 550 | } |
| 519 | 551 | |
| 520 | 552 | /* Find and print all requested changes. */ |
| 521 | 553 | blob_zero(&report); |
| 522 | - status_report(&report, flags); | |
| 554 | + status_report(&report, flags | C_MTIME | C_SIZE); | |
| 523 | 555 | if( blob_size(&report) ){ |
| 524 | 556 | if( showHdr ){ |
| 525 | 557 | fossil_print("Changes for %s at %s:\n", db_get("project-name", "???"), |
| 526 | 558 | g.zLocalRoot); |
| 527 | 559 | } |
| 528 | 560 |
| --- src/checkin.c | |
| +++ src/checkin.c | |
| @@ -27,35 +27,37 @@ | |
| 27 | */ |
| 28 | enum { |
| 29 | /* Zero-based bit indexes. */ |
| 30 | CB_EDITED , CB_UPDATED , CB_CHANGED, CB_MISSING , CB_ADDED, CB_DELETED, |
| 31 | CB_RENAMED, CB_CONFLICT, CB_META , CB_UNCHANGED, CB_EXTRA, CB_MERGE , |
| 32 | CB_RELPATH, CB_CLASSIFY, CB_FATAL , CB_COMMENT , |
| 33 | |
| 34 | /* Bitmask values. */ |
| 35 | C_EDITED = 1 << CB_EDITED, /* Edited, merged, and conflicted files. */ |
| 36 | C_UPDATED = 1 << CB_UPDATED, /* Files updated by merge/integrate. */ |
| 37 | C_CHANGED = 1 << CB_CHANGED, /* Treated the same as the above two. */ |
| 38 | C_MISSING = 1 << CB_MISSING, /* Missing and non- files. */ |
| 39 | C_ADDED = 1 << CB_ADDED, /* Added files. */ |
| 40 | C_DELETED = 1 << CB_DELETED, /* Deleted files. */ |
| 41 | C_RENAMED = 1 << CB_RENAMED, /* Renamed files. */ |
| 42 | C_CONFLICT = 1 << CB_CONFLICT, /* Files having merge conflicts. */ |
| 43 | C_META = 1 << CB_META, /* Files with metadata changes. */ |
| 44 | C_UNCHANGED = 1 << CB_UNCHANGED, /* Unchanged files. */ |
| 45 | C_EXTRA = 1 << CB_EXTRA, /* Unmanaged files. */ |
| 46 | C_MERGE = 1 << CB_MERGE, /* Merge contributors. */ |
| 47 | C_FILTER = C_EDITED | C_UPDATED | C_CHANGED | C_MISSING | C_ADDED |
| 48 | | C_DELETED | C_RENAMED | C_CONFLICT | C_META | C_UNCHANGED |
| 49 | | C_EXTRA | C_MERGE, /* All filter bits. */ |
| 50 | C_ALL = C_FILTER & ~(C_EXTRA | C_MERGE), /* All managed files. */ |
| 51 | C_DIFFER = C_FILTER & ~(C_UNCHANGED | C_MERGE), /* All differences. */ |
| 52 | C_RELPATH = 1 << CB_RELPATH, /* Show relative paths. */ |
| 53 | C_CLASSIFY = 1 << CB_CLASSIFY, /* Show file change types. */ |
| 54 | C_DEFAULT = (C_ALL & ~C_UNCHANGED) | C_MERGE | C_CLASSIFY, |
| 55 | C_FATAL = (1 << CB_FATAL) | C_MISSING, /* Fail on MISSING/NOT_A_FILE. */ |
| 56 | C_COMMENT = 1 << CB_COMMENT, /* Precede each line with "# ". */ |
| 57 | }; |
| 58 | |
| 59 | /* |
| 60 | ** Create a TEMP table named SFILE and add all unmanaged files named on |
| 61 | ** the command-line to that table. If directories are named, then add |
| @@ -73,12 +75,12 @@ | |
| 73 | char *zName; /* Name of a candidate file or directory */ |
| 74 | int isDir; /* 1 for a directory, 0 if doesn't exist, 2 for anything else */ |
| 75 | int i; /* Loop counter */ |
| 76 | int nRoot; /* length of g.zLocalRoot */ |
| 77 | |
| 78 | db_multi_exec("CREATE TEMP TABLE sfile(pathname TEXT PRIMARY KEY %s)", |
| 79 | filename_collation()); |
| 80 | nRoot = (int)strlen(g.zLocalRoot); |
| 81 | if( argc==0 ){ |
| 82 | blob_init(&name, g.zLocalRoot, nRoot - 1); |
| 83 | vfile_scan(&name, blob_size(&name), scanFlags, pIgnore, 0); |
| 84 | blob_reset(&name); |
| @@ -142,14 +144,18 @@ | |
| 142 | /* Obtain the list of managed files if appropriate. */ |
| 143 | blob_zero(&sql); |
| 144 | if( flags & C_ALL ){ |
| 145 | /* Start with a list of all managed files. */ |
| 146 | blob_append_sql(&sql, |
| 147 | "SELECT pathname, deleted, chnged, rid," |
| 148 | " coalesce(origname!=pathname,0) AS renamed, islink, 1 AS managed" |
| 149 | " FROM vfile" |
| 150 | " WHERE is_selected(id)%s", blob_sql_text(&where)); |
| 151 | |
| 152 | /* Exclude unchanged files unless requested. */ |
| 153 | if( !(flags & C_UNCHANGED) ){ |
| 154 | blob_append_sql(&sql, |
| 155 | " AND (chnged OR deleted OR rid=0 OR pathname!=origname)"); |
| @@ -159,32 +165,56 @@ | |
| 159 | /* If C_EXTRA, add unmanaged files to the query result too. */ |
| 160 | if( flags & C_EXTRA ){ |
| 161 | if( blob_size(&sql) ){ |
| 162 | blob_append_sql(&sql, " UNION ALL"); |
| 163 | } |
| 164 | blob_append_sql(&sql, " SELECT pathname, 0, 0, 0, 0, 0, 0" |
| 165 | " FROM sfile WHERE pathname NOT IN (%s)%s", |
| 166 | fossil_all_reserved_names(0), blob_sql_text(&where)); |
| 167 | } |
| 168 | |
| 169 | /* Append an ORDER BY clause then compile the query. */ |
| 170 | blob_append_sql(&sql, " ORDER BY pathname"); |
| 171 | db_prepare(&q, "%s", blob_sql_text(&sql)); |
| 172 | blob_reset(&sql); |
| 173 | blob_reset(&where); |
| 174 | |
| 175 | /* Execute the query and assemble the report. */ |
| 176 | blob_zero(&rewrittenPathname); |
| 177 | while( db_step(&q)==SQLITE_ROW ){ |
| 178 | const char *zPathname = db_column_text(&q, 0); |
| 179 | const char *zClass = 0; |
| 180 | int isManaged = db_column_int(&q, 6); |
| 181 | int isDeleted = db_column_int(&q, 1); |
| 182 | int isChnged = db_column_int(&q, 2); |
| 183 | int isNew = isManaged && !db_column_int(&q, 3); |
| 184 | int isRenamed = db_column_int(&q, 4); |
| 185 | int isLink = db_column_int(&q, 5); |
| 186 | char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname); |
| 187 | int isMissing = !file_wd_isfile_or_link(zFullName); |
| 188 | |
| 189 | /* Determine the file change classification, if any. */ |
| 190 | if( (flags & C_DELETED) && isDeleted ){ |
| @@ -236,21 +266,23 @@ | |
| 236 | zClass = "EXTRA"; |
| 237 | } |
| 238 | |
| 239 | /* Only report files for which a change classification was determined. */ |
| 240 | if( zClass ){ |
| 241 | /* If C_COMMENT, precede each line with "# ". */ |
| 242 | if( flags & C_COMMENT ){ |
| 243 | blob_append(report, "# ", 2); |
| 244 | } |
| 245 | |
| 246 | /* If C_CLASSIFY, include the change classification. */ |
| 247 | if( flags & C_CLASSIFY ){ |
| 248 | blob_appendf(report, "%-10s ", zClass); |
| 249 | } |
| 250 | |
| 251 | /* Finish with the filename followed by newline. */ |
| 252 | if( flags & C_RELPATH ){ |
| 253 | /* If C_RELPATH, display paths relative to current directory. */ |
| 254 | const char *zDisplayName; |
| 255 | file_relative_name(zFullName, &rewrittenPathname, 0); |
| 256 | zDisplayName = blob_str(&rewrittenPathname); |
| @@ -498,11 +530,11 @@ | |
| 498 | vfile_check_signature(vid, useSha1sum ? CKSIG_SHA1 : 0); |
| 499 | |
| 500 | /* Search for unmanaged files if requested. */ |
| 501 | if( flags & C_EXTRA ){ |
| 502 | Glob *pIgnore = glob_create(zIgnoreFlag); |
| 503 | locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags, pIgnore); |
| 504 | glob_free(pIgnore); |
| 505 | } |
| 506 | |
| 507 | /* The status command prints general information before the change list. */ |
| 508 | if( command==STATUS ){ |
| @@ -517,11 +549,11 @@ | |
| 517 | db_record_repository_filename(0); |
| 518 | } |
| 519 | |
| 520 | /* Find and print all requested changes. */ |
| 521 | blob_zero(&report); |
| 522 | status_report(&report, flags); |
| 523 | if( blob_size(&report) ){ |
| 524 | if( showHdr ){ |
| 525 | fossil_print("Changes for %s at %s:\n", db_get("project-name", "???"), |
| 526 | g.zLocalRoot); |
| 527 | } |
| 528 |
| --- src/checkin.c | |
| +++ src/checkin.c | |
| @@ -27,35 +27,37 @@ | |
| 27 | */ |
| 28 | enum { |
| 29 | /* Zero-based bit indexes. */ |
| 30 | CB_EDITED , CB_UPDATED , CB_CHANGED, CB_MISSING , CB_ADDED, CB_DELETED, |
| 31 | CB_RENAMED, CB_CONFLICT, CB_META , CB_UNCHANGED, CB_EXTRA, CB_MERGE , |
| 32 | CB_RELPATH, CB_CLASSIFY, CB_MTIME , CB_SIZE , CB_FATAL, CB_COMMENT, |
| 33 | |
| 34 | /* Bitmask values. */ |
| 35 | C_EDITED = 1 << CB_EDITED, /* Edited, merged, and conflicted files. */ |
| 36 | C_UPDATED = 1 << CB_UPDATED, /* Files updated by merge/integrate. */ |
| 37 | C_CHANGED = 1 << CB_CHANGED, /* Treated the same as the above two. */ |
| 38 | C_MISSING = 1 << CB_MISSING, /* Missing and non- files. */ |
| 39 | C_ADDED = 1 << CB_ADDED, /* Added files. */ |
| 40 | C_DELETED = 1 << CB_DELETED, /* Deleted files. */ |
| 41 | C_RENAMED = 1 << CB_RENAMED, /* Renamed files. */ |
| 42 | C_CONFLICT = 1 << CB_CONFLICT, /* Files having merge conflicts. */ |
| 43 | C_META = 1 << CB_META, /* Files with metadata changes. */ |
| 44 | C_UNCHANGED = 1 << CB_UNCHANGED, /* Unchanged files. */ |
| 45 | C_EXTRA = 1 << CB_EXTRA, /* Unmanaged files. */ |
| 46 | C_MERGE = 1 << CB_MERGE, /* Merge contributors. */ |
| 47 | C_FILTER = C_EDITED | C_UPDATED | C_CHANGED | C_MISSING | C_ADDED |
| 48 | | C_DELETED | C_RENAMED | C_CONFLICT | C_META | C_UNCHANGED |
| 49 | | C_EXTRA | C_MERGE, /* All filter bits. */ |
| 50 | C_ALL = C_FILTER & ~(C_EXTRA | C_MERGE),/* All managed files. */ |
| 51 | C_DIFFER = C_FILTER & ~(C_UNCHANGED | C_MERGE),/* All differences. */ |
| 52 | C_RELPATH = 1 << CB_RELPATH, /* Show relative paths. */ |
| 53 | C_CLASSIFY = 1 << CB_CLASSIFY, /* Show file change types. */ |
| 54 | C_DEFAULT = (C_ALL & ~C_UNCHANGED) | C_MERGE | C_CLASSIFY, |
| 55 | C_MTIME = 1 << CB_MTIME, /* Show file modification time. */ |
| 56 | C_SIZE = 1 << CB_SIZE, /* Show file size in bytes. */ |
| 57 | C_FATAL = (1 << CB_FATAL) | C_MISSING, /* Fail on MISSING/NOT_A_FILE. */ |
| 58 | C_COMMENT = 1 << CB_COMMENT, /* Precede each line with "# ". */ |
| 59 | }; |
| 60 | |
| 61 | /* |
| 62 | ** Create a TEMP table named SFILE and add all unmanaged files named on |
| 63 | ** the command-line to that table. If directories are named, then add |
| @@ -73,12 +75,12 @@ | |
| 75 | char *zName; /* Name of a candidate file or directory */ |
| 76 | int isDir; /* 1 for a directory, 0 if doesn't exist, 2 for anything else */ |
| 77 | int i; /* Loop counter */ |
| 78 | int nRoot; /* length of g.zLocalRoot */ |
| 79 | |
| 80 | db_multi_exec("CREATE TEMP TABLE sfile(pathname TEXT PRIMARY KEY %s," |
| 81 | " mtime INTEGER, size INTEGER)", filename_collation()); |
| 82 | nRoot = (int)strlen(g.zLocalRoot); |
| 83 | if( argc==0 ){ |
| 84 | blob_init(&name, g.zLocalRoot, nRoot - 1); |
| 85 | vfile_scan(&name, blob_size(&name), scanFlags, pIgnore, 0); |
| 86 | blob_reset(&name); |
| @@ -142,14 +144,18 @@ | |
| 144 | /* Obtain the list of managed files if appropriate. */ |
| 145 | blob_zero(&sql); |
| 146 | if( flags & C_ALL ){ |
| 147 | /* Start with a list of all managed files. */ |
| 148 | blob_append_sql(&sql, |
| 149 | "SELECT pathname, %s as mtime, %s as size, deleted, chnged, rid," |
| 150 | " coalesce(origname!=pathname,0) AS renamed, islink, 1 AS managed" |
| 151 | " FROM vfile, blob USING (rid)" |
| 152 | " WHERE is_selected(id)%s", |
| 153 | flags & C_MTIME ? "datetime(checkin_mtime(:vid, rid), " |
| 154 | "'unixepoch', toLocal())" : "''" /*safe-for-%s*/, |
| 155 | flags & C_SIZE ? "blob.size" : "0" /*safe-for-%s*/, |
| 156 | blob_sql_text(&where)); |
| 157 | |
| 158 | /* Exclude unchanged files unless requested. */ |
| 159 | if( !(flags & C_UNCHANGED) ){ |
| 160 | blob_append_sql(&sql, |
| 161 | " AND (chnged OR deleted OR rid=0 OR pathname!=origname)"); |
| @@ -159,32 +165,56 @@ | |
| 165 | /* If C_EXTRA, add unmanaged files to the query result too. */ |
| 166 | if( flags & C_EXTRA ){ |
| 167 | if( blob_size(&sql) ){ |
| 168 | blob_append_sql(&sql, " UNION ALL"); |
| 169 | } |
| 170 | blob_append_sql(&sql, |
| 171 | " SELECT pathname, %s, %s, 0, 0, 0, 0, 0, 0" |
| 172 | " FROM sfile WHERE pathname NOT IN (%s)%s", |
| 173 | flags & C_MTIME ? "datetime(mtime, 'unixepoch', toLocal())" : "''", |
| 174 | flags & C_SIZE ? "size" : "0", |
| 175 | fossil_all_reserved_names(0), blob_sql_text(&where)); |
| 176 | } |
| 177 | |
| 178 | #if 1 |
| 179 | /* SQLITE BUG WORKAROUND??? */ |
| 180 | /* If I step the query sans the ORDER BY clause, then I can run the full query |
| 181 | * without incident. But if I delete this workaround and run the query |
| 182 | * normally, I get SQLITE_ABORT due to ROLLBACK, which makes no sense. */ |
| 183 | db_prepare(&q, "%s", blob_sql_text(&sql)); |
| 184 | if( (flags & C_ALL) && (flags & C_MTIME) ){ |
| 185 | db_bind_int(&q, ":vid", db_lget_int("checkout", 0)); |
| 186 | } |
| 187 | db_step(&q); |
| 188 | db_finalize(&q); |
| 189 | /* SQLITE BUG WORKAROUND??? */ |
| 190 | #endif |
| 191 | |
| 192 | /* Append an ORDER BY clause then compile the query. */ |
| 193 | blob_append_sql(&sql, " ORDER BY pathname"); |
| 194 | db_prepare(&q, "%s", blob_sql_text(&sql)); |
| 195 | blob_reset(&sql); |
| 196 | blob_reset(&where); |
| 197 | |
| 198 | /* Bind the checkout version ID to the query if needed. */ |
| 199 | if( (flags & C_ALL) && (flags & C_MTIME) ){ |
| 200 | db_bind_int(&q, ":vid", db_lget_int("checkout", 0)); |
| 201 | } |
| 202 | |
| 203 | /* Execute the query and assemble the report. */ |
| 204 | blob_zero(&rewrittenPathname); |
| 205 | while( db_step(&q)==SQLITE_ROW ){ |
| 206 | const char *zPathname = db_column_text(&q, 0); |
| 207 | const char *zClass = 0; |
| 208 | int isManaged = db_column_int(&q, 8); |
| 209 | const char *zMtime = db_column_text(&q, 1); |
| 210 | int size = db_column_int(&q, 2); |
| 211 | int isDeleted = db_column_int(&q, 3); |
| 212 | int isChnged = db_column_int(&q, 4); |
| 213 | int isNew = isManaged && !db_column_int(&q, 5); |
| 214 | int isRenamed = db_column_int(&q, 6); |
| 215 | int isLink = db_column_int(&q, 7); |
| 216 | char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname); |
| 217 | int isMissing = !file_wd_isfile_or_link(zFullName); |
| 218 | |
| 219 | /* Determine the file change classification, if any. */ |
| 220 | if( (flags & C_DELETED) && isDeleted ){ |
| @@ -236,21 +266,23 @@ | |
| 266 | zClass = "EXTRA"; |
| 267 | } |
| 268 | |
| 269 | /* Only report files for which a change classification was determined. */ |
| 270 | if( zClass ){ |
| 271 | if( flags & C_COMMENT ){ |
| 272 | blob_append(report, "# ", 2); |
| 273 | } |
| 274 | if( flags & C_CLASSIFY ){ |
| 275 | blob_appendf(report, "%-10s ", zClass); |
| 276 | } |
| 277 | if( flags & C_MTIME ){ |
| 278 | blob_append(report, zMtime, -1); |
| 279 | blob_append(report, " ", 2); |
| 280 | } |
| 281 | if( flags & C_SIZE ){ |
| 282 | blob_appendf(report, "%7d ", size); |
| 283 | } |
| 284 | if( flags & C_RELPATH ){ |
| 285 | /* If C_RELPATH, display paths relative to current directory. */ |
| 286 | const char *zDisplayName; |
| 287 | file_relative_name(zFullName, &rewrittenPathname, 0); |
| 288 | zDisplayName = blob_str(&rewrittenPathname); |
| @@ -498,11 +530,11 @@ | |
| 530 | vfile_check_signature(vid, useSha1sum ? CKSIG_SHA1 : 0); |
| 531 | |
| 532 | /* Search for unmanaged files if requested. */ |
| 533 | if( flags & C_EXTRA ){ |
| 534 | Glob *pIgnore = glob_create(zIgnoreFlag); |
| 535 | locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags | SCAN_META, pIgnore); |
| 536 | glob_free(pIgnore); |
| 537 | } |
| 538 | |
| 539 | /* The status command prints general information before the change list. */ |
| 540 | if( command==STATUS ){ |
| @@ -517,11 +549,11 @@ | |
| 549 | db_record_repository_filename(0); |
| 550 | } |
| 551 | |
| 552 | /* Find and print all requested changes. */ |
| 553 | blob_zero(&report); |
| 554 | status_report(&report, flags | C_MTIME | C_SIZE); |
| 555 | if( blob_size(&report) ){ |
| 556 | if( showHdr ){ |
| 557 | fossil_print("Changes for %s at %s:\n", db_get("project-name", "???"), |
| 558 | g.zLocalRoot); |
| 559 | } |
| 560 |
+10
-2
| --- src/vfile.c | ||
| +++ src/vfile.c | ||
| @@ -455,10 +455,11 @@ | ||
| 455 | 455 | ** Values for the scanFlags parameter to vfile_scan(). |
| 456 | 456 | */ |
| 457 | 457 | #define SCAN_ALL 0x001 /* Includes files that begin with "." */ |
| 458 | 458 | #define SCAN_TEMP 0x002 /* Only Fossil-generated files like *-baseline */ |
| 459 | 459 | #define SCAN_NESTED 0x004 /* Scan for empty dirs in nested checkouts */ |
| 460 | +#define SCAN_META 0x008 /* Populate mtime and size columns */ | |
| 460 | 461 | #endif /* INTERFACE */ |
| 461 | 462 | |
| 462 | 463 | /* |
| 463 | 464 | ** Load into table SFILE the name of every ordinary file in |
| 464 | 465 | ** the directory pPath. Omit the first nPrefix characters of |
| @@ -498,13 +499,16 @@ | ||
| 498 | 499 | } |
| 499 | 500 | if( skipAll ) return; |
| 500 | 501 | |
| 501 | 502 | if( depth==0 ){ |
| 502 | 503 | db_prepare(&ins, |
| 503 | - "INSERT OR IGNORE INTO sfile(pathname) SELECT :file" | |
| 504 | + "INSERT OR IGNORE INTO sfile(pathname%s) SELECT :file%s" | |
| 504 | 505 | " WHERE NOT EXISTS(SELECT 1 FROM vfile WHERE" |
| 505 | - " pathname=:file %s)", filename_collation() | |
| 506 | + " pathname=:file %s)", | |
| 507 | + scanFlags & SCAN_META ? ", mtime, size" : "", | |
| 508 | + scanFlags & SCAN_META ? ", :mtime, :size" : "", | |
| 509 | + filename_collation() | |
| 506 | 510 | ); |
| 507 | 511 | } |
| 508 | 512 | depth++; |
| 509 | 513 | |
| 510 | 514 | zNative = fossil_utf8_to_path(blob_str(pPath), 1); |
| @@ -539,10 +543,14 @@ | ||
| 539 | 543 | #else |
| 540 | 544 | }else if( file_wd_isfile_or_link(zPath) ){ |
| 541 | 545 | #endif |
| 542 | 546 | if( (scanFlags & SCAN_TEMP)==0 || is_temporary_file(zUtf8) ){ |
| 543 | 547 | db_bind_text(&ins, ":file", &zPath[nPrefix+1]); |
| 548 | + if( scanFlags & SCAN_META ){ | |
| 549 | + db_bind_int(&ins, ":mtime", file_mtime(zPath)); | |
| 550 | + db_bind_int(&ins, ":size", file_size(zPath)); | |
| 551 | + } | |
| 544 | 552 | db_step(&ins); |
| 545 | 553 | db_reset(&ins); |
| 546 | 554 | } |
| 547 | 555 | } |
| 548 | 556 | fossil_path_free(zUtf8); |
| 549 | 557 |
| --- src/vfile.c | |
| +++ src/vfile.c | |
| @@ -455,10 +455,11 @@ | |
| 455 | ** Values for the scanFlags parameter to vfile_scan(). |
| 456 | */ |
| 457 | #define SCAN_ALL 0x001 /* Includes files that begin with "." */ |
| 458 | #define SCAN_TEMP 0x002 /* Only Fossil-generated files like *-baseline */ |
| 459 | #define SCAN_NESTED 0x004 /* Scan for empty dirs in nested checkouts */ |
| 460 | #endif /* INTERFACE */ |
| 461 | |
| 462 | /* |
| 463 | ** Load into table SFILE the name of every ordinary file in |
| 464 | ** the directory pPath. Omit the first nPrefix characters of |
| @@ -498,13 +499,16 @@ | |
| 498 | } |
| 499 | if( skipAll ) return; |
| 500 | |
| 501 | if( depth==0 ){ |
| 502 | db_prepare(&ins, |
| 503 | "INSERT OR IGNORE INTO sfile(pathname) SELECT :file" |
| 504 | " WHERE NOT EXISTS(SELECT 1 FROM vfile WHERE" |
| 505 | " pathname=:file %s)", filename_collation() |
| 506 | ); |
| 507 | } |
| 508 | depth++; |
| 509 | |
| 510 | zNative = fossil_utf8_to_path(blob_str(pPath), 1); |
| @@ -539,10 +543,14 @@ | |
| 539 | #else |
| 540 | }else if( file_wd_isfile_or_link(zPath) ){ |
| 541 | #endif |
| 542 | if( (scanFlags & SCAN_TEMP)==0 || is_temporary_file(zUtf8) ){ |
| 543 | db_bind_text(&ins, ":file", &zPath[nPrefix+1]); |
| 544 | db_step(&ins); |
| 545 | db_reset(&ins); |
| 546 | } |
| 547 | } |
| 548 | fossil_path_free(zUtf8); |
| 549 |
| --- src/vfile.c | |
| +++ src/vfile.c | |
| @@ -455,10 +455,11 @@ | |
| 455 | ** Values for the scanFlags parameter to vfile_scan(). |
| 456 | */ |
| 457 | #define SCAN_ALL 0x001 /* Includes files that begin with "." */ |
| 458 | #define SCAN_TEMP 0x002 /* Only Fossil-generated files like *-baseline */ |
| 459 | #define SCAN_NESTED 0x004 /* Scan for empty dirs in nested checkouts */ |
| 460 | #define SCAN_META 0x008 /* Populate mtime and size columns */ |
| 461 | #endif /* INTERFACE */ |
| 462 | |
| 463 | /* |
| 464 | ** Load into table SFILE the name of every ordinary file in |
| 465 | ** the directory pPath. Omit the first nPrefix characters of |
| @@ -498,13 +499,16 @@ | |
| 499 | } |
| 500 | if( skipAll ) return; |
| 501 | |
| 502 | if( depth==0 ){ |
| 503 | db_prepare(&ins, |
| 504 | "INSERT OR IGNORE INTO sfile(pathname%s) SELECT :file%s" |
| 505 | " WHERE NOT EXISTS(SELECT 1 FROM vfile WHERE" |
| 506 | " pathname=:file %s)", |
| 507 | scanFlags & SCAN_META ? ", mtime, size" : "", |
| 508 | scanFlags & SCAN_META ? ", :mtime, :size" : "", |
| 509 | filename_collation() |
| 510 | ); |
| 511 | } |
| 512 | depth++; |
| 513 | |
| 514 | zNative = fossil_utf8_to_path(blob_str(pPath), 1); |
| @@ -539,10 +543,14 @@ | |
| 543 | #else |
| 544 | }else if( file_wd_isfile_or_link(zPath) ){ |
| 545 | #endif |
| 546 | if( (scanFlags & SCAN_TEMP)==0 || is_temporary_file(zUtf8) ){ |
| 547 | db_bind_text(&ins, ":file", &zPath[nPrefix+1]); |
| 548 | if( scanFlags & SCAN_META ){ |
| 549 | db_bind_int(&ins, ":mtime", file_mtime(zPath)); |
| 550 | db_bind_int(&ins, ":size", file_size(zPath)); |
| 551 | } |
| 552 | db_step(&ins); |
| 553 | db_reset(&ins); |
| 554 | } |
| 555 | } |
| 556 | fossil_path_free(zUtf8); |
| 557 |