| | @@ -21,32 +21,115 @@ |
| 21 | 21 | #include "config.h" |
| 22 | 22 | #include "checkin.h" |
| 23 | 23 | #include <assert.h> |
| 24 | 24 | |
| 25 | 25 | /* |
| 26 | | -** Generate text describing all changes. Prepend zPrefix to each line |
| 27 | | -** of output. |
| 26 | +** Change filter options. |
| 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 |
| 64 | +** all unmanaged files contained underneath those directories. If there |
| 65 | +** are no files or directories named on the command-line, then add all |
| 66 | +** unmanaged files anywhere in the checkout. |
| 67 | +*/ |
| 68 | +static void locate_unmanaged_files( |
| 69 | + int argc, /* Number of command-line arguments to examine */ |
| 70 | + char **argv, /* values of command-line arguments */ |
| 71 | + unsigned scanFlags, /* Zero or more SCAN_xxx flags */ |
| 72 | + Glob *pIgnore /* Do not add files that match this GLOB */ |
| 73 | +){ |
| 74 | + Blob name; /* Name of a candidate file or directory */ |
| 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); |
| 87 | + }else{ |
| 88 | + for(i=0; i<argc; i++){ |
| 89 | + file_canonical_name(argv[i], &name, 0); |
| 90 | + zName = blob_str(&name); |
| 91 | + isDir = file_wd_isdir(zName); |
| 92 | + if( isDir==1 ){ |
| 93 | + vfile_scan(&name, nRoot-1, scanFlags, pIgnore, 0); |
| 94 | + }else if( isDir==0 ){ |
| 95 | + fossil_warning("not found: %s", &zName[nRoot]); |
| 96 | + }else if( file_access(zName, R_OK) ){ |
| 97 | + fossil_fatal("cannot open %s", &zName[nRoot]); |
| 98 | + }else{ |
| 99 | + db_multi_exec( |
| 100 | + "INSERT OR IGNORE INTO sfile(pathname) VALUES(%Q)", |
| 101 | + &zName[nRoot] |
| 102 | + ); |
| 103 | + } |
| 104 | + blob_reset(&name); |
| 105 | + } |
| 106 | + } |
| 107 | +} |
| 108 | + |
| 109 | +/* |
| 110 | +** Generate text describing all changes. |
| 28 | 111 | ** |
| 29 | 112 | ** We assume that vfile_check_signature has been run. |
| 30 | | -** |
| 31 | | -** If missingIsFatal is true, then any files that are missing or which |
| 32 | | -** are not true files results in a fatal error. |
| 33 | 113 | */ |
| 34 | 114 | static void status_report( |
| 35 | 115 | Blob *report, /* Append the status report here */ |
| 36 | | - const char *zPrefix, /* Prefix on each line of the report */ |
| 37 | | - int missingIsFatal, /* MISSING and NOT_A_FILE are fatal errors */ |
| 38 | | - int cwdRelative /* Report relative to the current working dir */ |
| 116 | + unsigned flags /* Filter and other configuration flags */ |
| 39 | 117 | ){ |
| 40 | 118 | Stmt q; |
| 41 | | - int nPrefix = strlen(zPrefix); |
| 42 | 119 | int nErr = 0; |
| 43 | 120 | Blob rewrittenPathname; |
| 44 | | - Blob where; |
| 121 | + Blob sql = BLOB_INITIALIZER, where = BLOB_INITIALIZER; |
| 45 | 122 | const char *zName; |
| 46 | 123 | int i; |
| 47 | 124 | |
| 125 | + /* Skip the file report if no files are requested at all. */ |
| 126 | + if( !(flags & (C_ALL | C_EXTRA)) ){ |
| 127 | + goto skipFiles; |
| 128 | + } |
| 129 | + |
| 130 | + /* Assemble the path-limiting WHERE clause, if any. */ |
| 48 | 131 | blob_zero(&where); |
| 49 | 132 | for(i=2; i<g.argc; i++){ |
| 50 | 133 | Blob fname; |
| 51 | 134 | file_tree_name(g.argv[i], &fname, 0, 1); |
| 52 | 135 | zName = blob_str(&fname); |
| | @@ -61,99 +144,187 @@ |
| 61 | 144 | filename_collation(), zName, filename_collation(), |
| 62 | 145 | zName, filename_collation() |
| 63 | 146 | ); |
| 64 | 147 | } |
| 65 | 148 | |
| 66 | | - db_prepare(&q, |
| 67 | | - "SELECT pathname, deleted, chnged," |
| 68 | | - " rid, coalesce(origname!=pathname,0), islink" |
| 69 | | - " FROM vfile " |
| 70 | | - " WHERE is_selected(id) %s" |
| 71 | | - " AND (chnged OR deleted OR rid=0 OR pathname!=origname)" |
| 72 | | - " ORDER BY 1 /*scan*/", |
| 73 | | - blob_sql_text(&where) |
| 74 | | - ); |
| 75 | | - blob_zero(&rewrittenPathname); |
| 76 | | - while( db_step(&q)==SQLITE_ROW ){ |
| 77 | | - const char *zPathname = db_column_text(&q,0); |
| 78 | | - const char *zDisplayName = zPathname; |
| 79 | | - int isDeleted = db_column_int(&q, 1); |
| 80 | | - int isChnged = db_column_int(&q,2); |
| 81 | | - int isNew = db_column_int(&q,3)==0; |
| 82 | | - int isRenamed = db_column_int(&q,4); |
| 83 | | - int isLink = db_column_int(&q,5); |
| 84 | | - char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname); |
| 85 | | - if( cwdRelative ){ |
| 86 | | - file_relative_name(zFullName, &rewrittenPathname, 0); |
| 87 | | - zDisplayName = blob_str(&rewrittenPathname); |
| 88 | | - if( zDisplayName[0]=='.' && zDisplayName[1]=='/' ){ |
| 89 | | - zDisplayName += 2; /* no unnecessary ./ prefix */ |
| 90 | | - } |
| 91 | | - } |
| 92 | | - blob_append(report, zPrefix, nPrefix); |
| 93 | | - if( isDeleted ){ |
| 94 | | - blob_appendf(report, "DELETED %s\n", zDisplayName); |
| 95 | | - }else if( !file_wd_isfile_or_link(zFullName) ){ |
| 96 | | - if( file_access(zFullName, F_OK)==0 ){ |
| 97 | | - blob_appendf(report, "NOT_A_FILE %s\n", zDisplayName); |
| 98 | | - if( missingIsFatal ){ |
| 99 | | - fossil_warning("not a file: %s", zDisplayName); |
| 100 | | - nErr++; |
| 101 | | - } |
| 102 | | - }else{ |
| 103 | | - blob_appendf(report, "MISSING %s\n", zDisplayName); |
| 104 | | - if( missingIsFatal ){ |
| 105 | | - fossil_warning("missing file: %s", zDisplayName); |
| 106 | | - nErr++; |
| 107 | | - } |
| 108 | | - } |
| 109 | | - }else if( isNew ){ |
| 110 | | - blob_appendf(report, "ADDED %s\n", zDisplayName); |
| 111 | | - }else if( isChnged ){ |
| 112 | | - if( isChnged==2 ){ |
| 113 | | - blob_appendf(report, "UPDATED_BY_MERGE %s\n", zDisplayName); |
| 114 | | - }else if( isChnged==3 ){ |
| 115 | | - blob_appendf(report, "ADDED_BY_MERGE %s\n", zDisplayName); |
| 116 | | - }else if( isChnged==4 ){ |
| 117 | | - blob_appendf(report, "UPDATED_BY_INTEGRATE %s\n", zDisplayName); |
| 118 | | - }else if( isChnged==5 ){ |
| 119 | | - blob_appendf(report, "ADDED_BY_INTEGRATE %s\n", zDisplayName); |
| 120 | | - }else if( isChnged==6 ){ |
| 121 | | - blob_appendf(report, "EXECUTABLE %s\n", zDisplayName); |
| 122 | | - }else if( isChnged==7 ){ |
| 123 | | - blob_appendf(report, "SYMLINK %s\n", zDisplayName); |
| 124 | | - }else if( isChnged==8 ){ |
| 125 | | - blob_appendf(report, "UNEXEC %s\n", zDisplayName); |
| 126 | | - }else if( isChnged==9 ){ |
| 127 | | - blob_appendf(report, "UNLINK %s\n", zDisplayName); |
| 128 | | - }else if( !isLink && file_contains_merge_marker(zFullName) ){ |
| 129 | | - blob_appendf(report, "CONFLICT %s\n", zDisplayName); |
| 130 | | - }else{ |
| 131 | | - blob_appendf(report, "EDITED %s\n", zDisplayName); |
| 132 | | - } |
| 133 | | - }else if( isRenamed ){ |
| 134 | | - blob_appendf(report, "RENAMED %s\n", zDisplayName); |
| 135 | | - }else{ |
| 136 | | - report->nUsed -= nPrefix; |
| 149 | + /* Obtain the list of managed files if appropriate. */ |
| 150 | + blob_zero(&sql); |
| 151 | + if( flags & C_ALL ){ |
| 152 | + /* Start with a list of all managed files. */ |
| 153 | + blob_append_sql(&sql, |
| 154 | + "SELECT pathname, %s as mtime, %s as size, deleted, chnged, rid," |
| 155 | + " coalesce(origname!=pathname,0) AS renamed, islink, 1 AS managed" |
| 156 | + " FROM vfile LEFT JOIN blob USING (rid)" |
| 157 | + " WHERE is_selected(id)%s", |
| 158 | + flags & C_MTIME ? "datetime(checkin_mtime(:vid, rid), " |
| 159 | + "'unixepoch', toLocal())" : "''" /*safe-for-%s*/, |
| 160 | + flags & C_SIZE ? "coalesce(blob.size, 0)" : "0" /*safe-for-%s*/, |
| 161 | + blob_sql_text(&where)); |
| 162 | + |
| 163 | + /* Exclude unchanged files unless requested. */ |
| 164 | + if( !(flags & C_UNCHANGED) ){ |
| 165 | + blob_append_sql(&sql, |
| 166 | + " AND (chnged OR deleted OR rid=0 OR pathname!=origname)"); |
| 167 | + } |
| 168 | + } |
| 169 | + |
| 170 | + /* If C_EXTRA, add unmanaged files to the query result too. */ |
| 171 | + if( flags & C_EXTRA ){ |
| 172 | + if( blob_size(&sql) ){ |
| 173 | + blob_append_sql(&sql, " UNION ALL"); |
| 174 | + } |
| 175 | + blob_append_sql(&sql, |
| 176 | + " SELECT pathname, %s, %s, 0, 0, 0, 0, 0, 0" |
| 177 | + " FROM sfile WHERE pathname NOT IN (%s)%s", |
| 178 | + flags & C_MTIME ? "datetime(mtime, 'unixepoch', toLocal())" : "''", |
| 179 | + flags & C_SIZE ? "size" : "0", |
| 180 | + fossil_all_reserved_names(0), blob_sql_text(&where)); |
| 181 | + } |
| 182 | + blob_reset(&where); |
| 183 | + |
| 184 | + /* Pre-create the "ok" temporary table so the checkin_mtime() SQL function |
| 185 | + * does not lead to SQLITE_ABORT_ROLLBACK during execution of the OP_OpenRead |
| 186 | + * SQLite opcode. checkin_mtime() calls mtime_of_manifest_file() which |
| 187 | + * creates a temporary table if it doesn't already exist, thus invalidating |
| 188 | + * the prepared statement in the middle of its execution. */ |
| 189 | + db_multi_exec("CREATE TEMP TABLE IF NOT EXISTS ok(rid INTEGER PRIMARY KEY)"); |
| 190 | + |
| 191 | + /* Append an ORDER BY clause then compile the query. */ |
| 192 | + blob_append_sql(&sql, " ORDER BY pathname"); |
| 193 | + db_prepare(&q, "%s", blob_sql_text(&sql)); |
| 194 | + blob_reset(&sql); |
| 195 | + |
| 196 | + /* Bind the checkout version ID to the query if needed. */ |
| 197 | + if( (flags & C_ALL) && (flags & C_MTIME) ){ |
| 198 | + db_bind_int(&q, ":vid", db_lget_int("checkout", 0)); |
| 199 | + } |
| 200 | + |
| 201 | + /* Execute the query and assemble the report. */ |
| 202 | + blob_zero(&rewrittenPathname); |
| 203 | + while( db_step(&q)==SQLITE_ROW ){ |
| 204 | + const char *zPathname = db_column_text(&q, 0); |
| 205 | + const char *zClass = 0; |
| 206 | + int isManaged = db_column_int(&q, 8); |
| 207 | + const char *zMtime = db_column_text(&q, 1); |
| 208 | + int size = db_column_int(&q, 2); |
| 209 | + int isDeleted = db_column_int(&q, 3); |
| 210 | + int isChnged = db_column_int(&q, 4); |
| 211 | + int isNew = isManaged && !db_column_int(&q, 5); |
| 212 | + int isRenamed = db_column_int(&q, 6); |
| 213 | + int isLink = db_column_int(&q, 7); |
| 214 | + char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname); |
| 215 | + int isMissing = !file_wd_isfile_or_link(zFullName); |
| 216 | + |
| 217 | + /* Determine the file change classification, if any. */ |
| 218 | + if( (flags & C_DELETED) && isDeleted ){ |
| 219 | + zClass = "DELETED"; |
| 220 | + }else if( (flags & C_MISSING) && isMissing ){ |
| 221 | + if( file_access(zFullName, F_OK)==0 ){ |
| 222 | + zClass = "NOT_A_FILE"; |
| 223 | + if( flags & C_FATAL ){ |
| 224 | + fossil_warning("not a file: %s", zFullName); |
| 225 | + nErr++; |
| 226 | + } |
| 227 | + }else{ |
| 228 | + zClass = "MISSING"; |
| 229 | + if( flags & C_FATAL ){ |
| 230 | + fossil_warning("missing file: %s", zFullName); |
| 231 | + nErr++; |
| 232 | + } |
| 233 | + } |
| 234 | + }else if( (flags & C_ADDED) && isNew ){ |
| 235 | + zClass = "ADDED"; |
| 236 | + }else if( (flags & (C_UPDATED | C_CHANGED)) && isChnged==2 ){ |
| 237 | + zClass = "UPDATED_BY_MERGE"; |
| 238 | + }else if( (flags & C_ADDED) && isChnged==3 ){ |
| 239 | + zClass = "ADDED_BY_MERGE"; |
| 240 | + }else if( (flags & (C_UPDATED | C_CHANGED)) && isChnged==4 ){ |
| 241 | + zClass = "UPDATED_BY_INTEGRATE"; |
| 242 | + }else if( (flags & C_ADDED) && isChnged==5 ){ |
| 243 | + zClass = "ADDED_BY_INTEGRATE"; |
| 244 | + }else if( (flags & C_META) && isChnged==6 ){ |
| 245 | + zClass = "EXECUTABLE"; |
| 246 | + }else if( (flags & C_META) && isChnged==7 ){ |
| 247 | + zClass = "SYMLINK"; |
| 248 | + }else if( (flags & C_META) && isChnged==8 ){ |
| 249 | + zClass = "UNEXEC"; |
| 250 | + }else if( (flags & C_META) && isChnged==9 ){ |
| 251 | + zClass = "UNLINK"; |
| 252 | + }else if( (flags & C_CONFLICT) && isChnged && !isLink |
| 253 | + && file_contains_merge_marker(zFullName) ){ |
| 254 | + zClass = "CONFLICT"; |
| 255 | + }else if( (flags & (C_EDITED | C_CHANGED)) && isChnged |
| 256 | + && (isChnged<2 || isChnged>9) ){ |
| 257 | + zClass = "EDITED"; |
| 258 | + }else if( (flags & C_RENAMED) && isRenamed ){ |
| 259 | + zClass = "RENAMED"; |
| 260 | + }else if( (flags & C_UNCHANGED) && isManaged && !isDeleted && !isMissing |
| 261 | + && !isNew && !isChnged && !isRenamed ){ |
| 262 | + zClass = "UNCHANGED"; |
| 263 | + }else if( (flags & C_EXTRA) && !isManaged ){ |
| 264 | + zClass = "EXTRA"; |
| 265 | + } |
| 266 | + |
| 267 | + /* Only report files for which a change classification was determined. */ |
| 268 | + if( zClass ){ |
| 269 | + if( flags & C_COMMENT ){ |
| 270 | + blob_append(report, "# ", 2); |
| 271 | + } |
| 272 | + if( flags & C_CLASSIFY ){ |
| 273 | + blob_appendf(report, "%-10s ", zClass); |
| 274 | + } |
| 275 | + if( flags & C_MTIME ){ |
| 276 | + blob_append(report, zMtime, -1); |
| 277 | + blob_append(report, " ", 2); |
| 278 | + } |
| 279 | + if( flags & C_SIZE ){ |
| 280 | + blob_appendf(report, "%7d ", size); |
| 281 | + } |
| 282 | + if( flags & C_RELPATH ){ |
| 283 | + /* If C_RELPATH, display paths relative to current directory. */ |
| 284 | + const char *zDisplayName; |
| 285 | + file_relative_name(zFullName, &rewrittenPathname, 0); |
| 286 | + zDisplayName = blob_str(&rewrittenPathname); |
| 287 | + if( zDisplayName[0]=='.' && zDisplayName[1]=='/' ){ |
| 288 | + zDisplayName += 2; /* no unnecessary ./ prefix */ |
| 289 | + } |
| 290 | + blob_append(report, zDisplayName, -1); |
| 291 | + }else{ |
| 292 | + /* If not C_RELPATH, display paths relative to project root. */ |
| 293 | + blob_append(report, zPathname, -1); |
| 294 | + } |
| 295 | + blob_append(report, "\n", 1); |
| 137 | 296 | } |
| 138 | 297 | free(zFullName); |
| 139 | 298 | } |
| 140 | 299 | blob_reset(&rewrittenPathname); |
| 141 | 300 | db_finalize(&q); |
| 142 | | - db_prepare(&q, "SELECT uuid, id FROM vmerge JOIN blob ON merge=rid" |
| 143 | | - " WHERE id<=0"); |
| 144 | | - while( db_step(&q)==SQLITE_ROW ){ |
| 145 | | - const char *zLabel = "MERGED_WITH "; |
| 146 | | - switch( db_column_int(&q, 1) ){ |
| 147 | | - case -1: zLabel = "CHERRYPICK "; break; |
| 148 | | - case -2: zLabel = "BACKOUT "; break; |
| 149 | | - case -4: zLabel = "INTEGRATE "; break; |
| 150 | | - } |
| 151 | | - blob_append(report, zPrefix, nPrefix); |
| 152 | | - blob_appendf(report, "%s%s\n", zLabel, db_column_text(&q, 0)); |
| 153 | | - } |
| 154 | | - db_finalize(&q); |
| 301 | + |
| 302 | + /* If C_MERGE, put merge contributors at the end of the report. */ |
| 303 | +skipFiles: |
| 304 | + if( flags & C_MERGE ){ |
| 305 | + db_prepare(&q, "SELECT uuid, id FROM vmerge JOIN blob ON merge=rid" |
| 306 | + " WHERE id<=0"); |
| 307 | + while( db_step(&q)==SQLITE_ROW ){ |
| 308 | + if( flags & C_COMMENT ){ |
| 309 | + blob_append(report, "# ", 2); |
| 310 | + } |
| 311 | + if( flags & C_CLASSIFY ){ |
| 312 | + const char *zClass; |
| 313 | + switch( db_column_int(&q, 1) ){ |
| 314 | + case -1: zClass = "CHERRYPICK" ; break; |
| 315 | + case -2: zClass = "BACKOUT" ; break; |
| 316 | + case -4: zClass = "INTEGRATE" ; break; |
| 317 | + default: zClass = "MERGED_WITH"; break; |
| 318 | + } |
| 319 | + blob_appendf(report, "%-10s ", zClass); |
| 320 | + } |
| 321 | + blob_append(report, db_column_text(&q, 0), -1); |
| 322 | + blob_append(report, "\n", 1); |
| 323 | + } |
| 324 | + db_finalize(&q); |
| 325 | + } |
| 155 | 326 | if( nErr ){ |
| 156 | 327 | fossil_fatal("aborting due to prior errors"); |
| 157 | 328 | } |
| 158 | 329 | } |
| 159 | 330 | |
| | @@ -171,115 +342,228 @@ |
| 171 | 342 | if( absPathOption ){ relativePaths = 0; } |
| 172 | 343 | if( relPathOption ){ relativePaths = 1; } |
| 173 | 344 | return relativePaths; |
| 174 | 345 | } |
| 175 | 346 | |
| 176 | | -void print_changes( |
| 177 | | - int useSha1sum, /* Verify file status using SHA1 hashing rather |
| 178 | | - than relying on file mtimes. */ |
| 179 | | - int showHdr, /* Identify the repository if there are changes */ |
| 180 | | - int verboseFlag, /* Say "(none)" if there are no changes */ |
| 181 | | - int cwdRelative /* Report relative to the current working dir */ |
| 182 | | -){ |
| 183 | | - Blob report; |
| 184 | | - int vid; |
| 185 | | - blob_zero(&report); |
| 186 | | - |
| 187 | | - vid = db_lget_int("checkout", 0); |
| 188 | | - vfile_check_signature(vid, useSha1sum ? CKSIG_SHA1 : 0); |
| 189 | | - status_report(&report, "", 0, cwdRelative); |
| 190 | | - if( verboseFlag && blob_size(&report)==0 ){ |
| 191 | | - blob_append(&report, " (none)\n", -1); |
| 192 | | - } |
| 193 | | - if( showHdr && blob_size(&report)>0 ){ |
| 194 | | - fossil_print("Changes for %s at %s:\n", db_get("project-name","???"), |
| 195 | | - g.zLocalRoot); |
| 196 | | - } |
| 197 | | - blob_write_to_file(&report, "-"); |
| 198 | | - blob_reset(&report); |
| 199 | | -} |
| 200 | | - |
| 201 | | -/* |
| 202 | | -** COMMAND: changes |
| 203 | | -** |
| 204 | | -** Usage: %fossil changes ?OPTIONS? |
| 205 | | -** |
| 206 | | -** Report on the edit status of all files in the current checkout. |
| 207 | | -** |
| 208 | | -** Pathnames are displayed according to the "relative-paths" setting, |
| 209 | | -** unless overridden by the --abs-paths or --rel-paths options. |
| 210 | | -** |
| 211 | | -** Options: |
| 212 | | -** --abs-paths Display absolute pathnames. |
| 213 | | -** --rel-paths Display pathnames relative to the current working |
| 214 | | -** directory. |
| 215 | | -** --sha1sum Verify file status using SHA1 hashing rather |
| 216 | | -** than relying on file mtimes. |
| 217 | | -** --header Identify the repository if there are changes |
| 218 | | -** -v|--verbose Say "(none)" if there are no changes |
| 219 | | -** |
| 220 | | -** See also: extras, ls, status |
| 221 | | -*/ |
| 222 | | -void changes_cmd(void){ |
| 223 | | - int useSha1sum = find_option("sha1sum", 0, 0)!=0; |
| 224 | | - int showHdr = find_option("header",0,0)!=0; |
| 225 | | - int verboseFlag = find_option("verbose","v",0)!=0; |
| 226 | | - int cwdRelative = 0; |
| 227 | | - db_must_be_within_tree(); |
| 228 | | - cwdRelative = determine_cwd_relative_option(); |
| 229 | | - |
| 230 | | - /* We should be done with options.. */ |
| 231 | | - verify_all_options(); |
| 232 | | - |
| 233 | | - print_changes(useSha1sum, showHdr, verboseFlag, cwdRelative); |
| 234 | | -} |
| 235 | | - |
| 236 | | -/* |
| 237 | | -** COMMAND: status |
| 238 | | -** |
| 239 | | -** Usage: %fossil status ?OPTIONS? |
| 240 | | -** |
| 241 | | -** Report on the status of the current checkout. |
| 242 | | -** |
| 243 | | -** Pathnames are displayed according to the "relative-paths" setting, |
| 244 | | -** unless overridden by the --abs-paths or --rel-paths options. |
| 245 | | -** |
| 246 | | -** Options: |
| 247 | | -** |
| 248 | | -** --abs-paths Display absolute pathnames. |
| 249 | | -** --rel-paths Display pathnames relative to the current working |
| 250 | | -** directory. |
| 251 | | -** --sha1sum Verify file status using SHA1 hashing rather |
| 252 | | -** than relying on file mtimes. |
| 253 | | -** |
| 254 | | -** See also: changes, extras, ls |
| 255 | | -*/ |
| 256 | | -void status_cmd(void){ |
| 257 | | - int vid; |
| 258 | | - int useSha1sum = find_option("sha1sum", 0, 0)!=0; |
| 259 | | - int showHdr = find_option("header",0,0)!=0; |
| 260 | | - int verboseFlag = find_option("verbose","v",0)!=0; |
| 261 | | - int cwdRelative = 0; |
| 262 | | - db_must_be_within_tree(); |
| 263 | | - /* 012345678901234 */ |
| 264 | | - cwdRelative = determine_cwd_relative_option(); |
| 265 | | - |
| 266 | | - /* We should be done with options.. */ |
| 267 | | - verify_all_options(); |
| 268 | | - |
| 269 | | - fossil_print("repository: %s\n", db_repository_filename()); |
| 270 | | - fossil_print("local-root: %s\n", g.zLocalRoot); |
| 271 | | - if( g.zConfigDbName ){ |
| 272 | | - fossil_print("config-db: %s\n", g.zConfigDbName); |
| 273 | | - } |
| 274 | | - vid = db_lget_int("checkout", 0); |
| 275 | | - if( vid ){ |
| 276 | | - show_common_info(vid, "checkout:", 1, 1); |
| 277 | | - } |
| 278 | | - db_record_repository_filename(0); |
| 279 | | - print_changes(useSha1sum, showHdr, verboseFlag, cwdRelative); |
| 280 | | - leaf_ambiguity_warning(vid, vid); |
| 347 | +/* |
| 348 | +** COMMAND: changes |
| 349 | +** COMMAND: status |
| 350 | +** |
| 351 | +** Usage: %fossil changes|status ?OPTIONS? ?PATHS ...? |
| 352 | +** |
| 353 | +** Report the change status of files in the current checkout. If one or |
| 354 | +** more PATHS are specified, only changes among the named files and |
| 355 | +** directories are reported. Directories are searched recursively. |
| 356 | +** |
| 357 | +** The status command is similar to the changes command, except it lacks |
| 358 | +** several of the options supported by changes and it has its own header |
| 359 | +** and footer information. The header information is a subset of that |
| 360 | +** shown by the info command, and the footer shows if there are any forks. |
| 361 | +** Change type classification is always enabled for the status command. |
| 362 | +** |
| 363 | +** Each line of output is the name of a changed file, with paths shown |
| 364 | +** according to the "relative-paths" setting, unless overridden by the |
| 365 | +** --abs-paths or --rel-paths options. |
| 366 | +** |
| 367 | +** By default, all changed files are selected for display. This behavior |
| 368 | +** can be overridden by using one or more filter options (listed below), |
| 369 | +** in which case only files with the specified change type(s) are shown. |
| 370 | +** As a special case, the --no-merge option does not inhibit this default. |
| 371 | +** This default shows exactly the set of changes that would be checked |
| 372 | +** in by the commit command. |
| 373 | +** |
| 374 | +** If no filter options are used, or if the --merge option is used, the |
| 375 | +** SHA1 hash of each merge contributor check-in version is displayed at |
| 376 | +** the end of the report. The --no-merge option is useful to display the |
| 377 | +** default set of changed files without the merge contributors. |
| 378 | +** |
| 379 | +** If change type classification is enabled, each output line starts with |
| 380 | +** a code describing the file's change type, e.g. EDITED or RENAMED. It |
| 381 | +** is enabled by default unless exactly one change type is selected. For |
| 382 | +** the purposes of determining the default, --changed counts as selecting |
| 383 | +** one change type. The default can be overridden by the --classify or |
| 384 | +** --no-classify options. |
| 385 | +** |
| 386 | +** If both --merge and --no-merge are used, --no-merge has priority. The |
| 387 | +** same is true of --classify and --no-classify. |
| 388 | +** |
| 389 | +** The "fossil changes --extra" command is equivalent to "fossil extras". |
| 390 | +** |
| 391 | +** --edited and --updated produce disjoint sets. --updated shows a file |
| 392 | +** only when it is identical to that of its merge contributor, and the |
| 393 | +** change type classification is UPDATED_BY_MERGE or UPDATED_BY_INTEGRATE. |
| 394 | +** If the file had to be merged with any other changes, it is considered |
| 395 | +** to be merged or conflicted and therefore will be shown by --edited, not |
| 396 | +** --updated, with types EDITED or CONFLICT. The --changed option can be |
| 397 | +** used to display the union of --edited and --updated. |
| 398 | +** |
| 399 | +** --differ is so named because it lists all the differences between the |
| 400 | +** checked-out version and the checkout directory. In addition to the |
| 401 | +** default changes (besides --merge), it lists extra files which (assuming |
| 402 | +** ignore-glob is set correctly) may be worth adding. Prior to doing a |
| 403 | +** commit, it is good practice to check --differ to see not only which |
| 404 | +** changes would be committed but also if any files need to be added. |
| 405 | +** |
| 406 | +** General options: |
| 407 | +** --abs-paths Display absolute pathnames. |
| 408 | +** --rel-paths Display pathnames relative to the current working |
| 409 | +** directory. |
| 410 | +** --sha1sum Verify file status using SHA1 hashing rather than |
| 411 | +** relying on file mtimes. |
| 412 | +** --case-sensitive <BOOL> Override case-sensitive setting. |
| 413 | +** --dotfiles Include unmanaged files beginning with a dot. |
| 414 | +** --ignore <CSG> Ignore unmanaged files matching CSG glob patterns. |
| 415 | +** |
| 416 | +** Options specific to the changes command: |
| 417 | +** --header Identify the repository if report is non-empty. |
| 418 | +** -v|--verbose Say "(none)" if the change report is empty. |
| 419 | +** --classify Start each line with the file's change type. |
| 420 | +** --no-classify Do not print file change types. |
| 421 | +** |
| 422 | +** Filter options: |
| 423 | +** --edited Display edited, merged, and conflicted files. |
| 424 | +** --updated Display files updated by merge/integrate. |
| 425 | +** --changed Combination of the above two options. |
| 426 | +** --missing Display missing files. |
| 427 | +** --added Display added files. |
| 428 | +** --deleted Display deleted files. |
| 429 | +** --renamed Display renamed files. |
| 430 | +** --conflict Display files having merge conflicts. |
| 431 | +** --meta Display files with metadata changes. |
| 432 | +** --unchanged Display unchanged files. |
| 433 | +** --all Display all managed files, i.e. all of the above. |
| 434 | +** --extra Display unmanaged files. |
| 435 | +** --differ Display modified and extra files. |
| 436 | +** --merge Display merge contributors. |
| 437 | +** --no-merge Do not display merge contributors. |
| 438 | +** |
| 439 | +** See also: extras, ls |
| 440 | +*/ |
| 441 | +void status_cmd(void){ |
| 442 | + /* Affirmative and negative flag option tables. */ |
| 443 | + static const struct { |
| 444 | + const char *option; /* Flag name. */ |
| 445 | + unsigned mask; /* Flag bits. */ |
| 446 | + } flagDefs[] = { |
| 447 | + {"edited" , C_EDITED }, {"updated" , C_UPDATED }, |
| 448 | + {"changed" , C_CHANGED }, {"missing" , C_MISSING }, |
| 449 | + {"added" , C_ADDED }, {"deleted" , C_DELETED }, |
| 450 | + {"renamed" , C_RENAMED }, {"conflict" , C_CONFLICT }, |
| 451 | + {"meta" , C_META }, {"unchanged" , C_UNCHANGED}, |
| 452 | + {"all" , C_ALL }, {"extra" , C_EXTRA }, |
| 453 | + {"differ" , C_DIFFER }, {"merge" , C_MERGE }, |
| 454 | + {"classify", C_CLASSIFY}, |
| 455 | + }, noFlagDefs[] = { |
| 456 | + {"no-merge", C_MERGE }, {"no-classify", C_CLASSIFY }, |
| 457 | + }; |
| 458 | + |
| 459 | + Blob report = BLOB_INITIALIZER; |
| 460 | + enum {CHANGES, STATUS} command = *g.argv[1]=='s' ? STATUS : CHANGES; |
| 461 | + int useSha1sum = find_option("sha1sum", 0, 0)!=0; |
| 462 | + int showHdr = command==CHANGES && find_option("header", 0, 0); |
| 463 | + int verboseFlag = command==CHANGES && find_option("verbose", "v", 0); |
| 464 | + const char *zIgnoreFlag = find_option("ignore", 0, 1); |
| 465 | + unsigned scanFlags = 0; |
| 466 | + unsigned flags = 0; |
| 467 | + int vid, i; |
| 468 | + |
| 469 | + /* Load affirmative flag options. */ |
| 470 | + for( i=0; i<count(flagDefs); ++i ){ |
| 471 | + if( (command==CHANGES || !(flagDefs[i].mask & C_CLASSIFY)) |
| 472 | + && find_option(flagDefs[i].option, 0, 0) ){ |
| 473 | + flags |= flagDefs[i].mask; |
| 474 | + } |
| 475 | + } |
| 476 | + |
| 477 | + /* If no filter options are specified, enable defaults. */ |
| 478 | + if( !(flags & C_FILTER) ){ |
| 479 | + flags |= C_DEFAULT; |
| 480 | + } |
| 481 | + |
| 482 | + /* If more than one filter is enabled, enable classification. This is tricky. |
| 483 | + * Having one filter means flags masked by C_FILTER is a power of two. If a |
| 484 | + * number masked by one less than itself is zero, it's either zero or a power |
| 485 | + * of two. It's already known to not be zero because of the above defaults. |
| 486 | + * Unlike --all, --changed is a single filter, i.e. it sets only one bit. |
| 487 | + * Also force classification for the status command. */ |
| 488 | + if( command==STATUS || (flags & (flags-1) & C_FILTER) ){ |
| 489 | + flags |= C_CLASSIFY; |
| 490 | + } |
| 491 | + |
| 492 | + /* Negative flag options override defaults applied above. */ |
| 493 | + for( i=0; i<count(noFlagDefs); ++i ){ |
| 494 | + if( (command==CHANGES || !(noFlagDefs[i].mask & C_CLASSIFY)) |
| 495 | + && find_option(noFlagDefs[i].option, 0, 0) ){ |
| 496 | + flags &= ~noFlagDefs[i].mask; |
| 497 | + } |
| 498 | + } |
| 499 | + |
| 500 | + /* Confirm current working directory is within checkout. */ |
| 501 | + db_must_be_within_tree(); |
| 502 | + |
| 503 | + /* Get checkout version. l*/ |
| 504 | + vid = db_lget_int("checkout", 0); |
| 505 | + |
| 506 | + /* Relative path flag determination is done by a shared function. */ |
| 507 | + if( determine_cwd_relative_option() ){ |
| 508 | + flags |= C_RELPATH; |
| 509 | + } |
| 510 | + |
| 511 | + /* If --ignore is not specified, use the ignore-glob setting. */ |
| 512 | + if( !zIgnoreFlag ){ |
| 513 | + zIgnoreFlag = db_get("ignore-glob", 0); |
| 514 | + } |
| 515 | + |
| 516 | + /* Get the --dotfiles argument, or read it from the dotfiles setting. */ |
| 517 | + if( find_option("dotfiles", 0, 0) || db_get_boolean("dotfiles", 0) ){ |
| 518 | + scanFlags = SCAN_ALL; |
| 519 | + } |
| 520 | + |
| 521 | + /* We should be done with options. */ |
| 522 | + verify_all_options(); |
| 523 | + |
| 524 | + /* Check for changed files. */ |
| 525 | + vfile_check_signature(vid, useSha1sum ? CKSIG_SHA1 : 0); |
| 526 | + |
| 527 | + /* Search for unmanaged files if requested. */ |
| 528 | + if( flags & C_EXTRA ){ |
| 529 | + Glob *pIgnore = glob_create(zIgnoreFlag); |
| 530 | + locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags, pIgnore); |
| 531 | + glob_free(pIgnore); |
| 532 | + } |
| 533 | + |
| 534 | + /* The status command prints general information before the change list. */ |
| 535 | + if( command==STATUS ){ |
| 536 | + fossil_print("repository: %s\n", db_repository_filename()); |
| 537 | + fossil_print("local-root: %s\n", g.zLocalRoot); |
| 538 | + if( g.zConfigDbName ){ |
| 539 | + fossil_print("config-db: %s\n", g.zConfigDbName); |
| 540 | + } |
| 541 | + if( vid ){ |
| 542 | + show_common_info(vid, "checkout:", 1, 1); |
| 543 | + } |
| 544 | + db_record_repository_filename(0); |
| 545 | + } |
| 546 | + |
| 547 | + /* Find and print all requested changes. */ |
| 548 | + blob_zero(&report); |
| 549 | + status_report(&report, flags); |
| 550 | + if( blob_size(&report) ){ |
| 551 | + if( showHdr ){ |
| 552 | + fossil_print("Changes for %s at %s:\n", db_get("project-name", "???"), |
| 553 | + g.zLocalRoot); |
| 554 | + } |
| 555 | + blob_write_to_file(&report, "-"); |
| 556 | + }else if( verboseFlag ){ |
| 557 | + fossil_print(" (none)\n"); |
| 558 | + } |
| 559 | + blob_reset(&report); |
| 560 | + |
| 561 | + /* The status command ends with warnings about ambiguous leaves (forks). */ |
| 562 | + if( command==STATUS ){ |
| 563 | + leaf_ambiguity_warning(vid, vid); |
| 564 | + } |
| 281 | 565 | } |
| 282 | 566 | |
| 283 | 567 | /* |
| 284 | 568 | ** Take care of -r version of ls command |
| 285 | 569 | */ |
| | @@ -508,59 +792,10 @@ |
| 508 | 792 | free(zFullName); |
| 509 | 793 | } |
| 510 | 794 | db_finalize(&q); |
| 511 | 795 | } |
| 512 | 796 | |
| 513 | | -/* |
| 514 | | -** Create a TEMP table named SFILE and add all unmanaged files named on |
| 515 | | -** the command-line to that table. If directories are named, then add |
| 516 | | -** all unmanaged files contained underneath those directories. If there |
| 517 | | -** are no files or directories named on the command-line, then add all |
| 518 | | -** unmanaged files anywhere in the checkout. |
| 519 | | -*/ |
| 520 | | -static void locate_unmanaged_files( |
| 521 | | - int argc, /* Number of command-line arguments to examine */ |
| 522 | | - char **argv, /* values of command-line arguments */ |
| 523 | | - unsigned scanFlags, /* Zero or more SCAN_xxx flags */ |
| 524 | | - Glob *pIgnore1, /* Do not add files that match this GLOB */ |
| 525 | | - Glob *pIgnore2 /* Omit files matching this GLOB too */ |
| 526 | | -){ |
| 527 | | - Blob name; /* Name of a candidate file or directory */ |
| 528 | | - char *zName; /* Name of a candidate file or directory */ |
| 529 | | - int isDir; /* 1 for a directory, 0 if doesn't exist, 2 for anything else */ |
| 530 | | - int i; /* Loop counter */ |
| 531 | | - int nRoot; /* length of g.zLocalRoot */ |
| 532 | | - |
| 533 | | - db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY %s)", |
| 534 | | - filename_collation()); |
| 535 | | - nRoot = (int)strlen(g.zLocalRoot); |
| 536 | | - if( argc==0 ){ |
| 537 | | - blob_init(&name, g.zLocalRoot, nRoot - 1); |
| 538 | | - vfile_scan(&name, blob_size(&name), scanFlags, pIgnore1, pIgnore2); |
| 539 | | - blob_reset(&name); |
| 540 | | - }else{ |
| 541 | | - for(i=0; i<argc; i++){ |
| 542 | | - file_canonical_name(argv[i], &name, 0); |
| 543 | | - zName = blob_str(&name); |
| 544 | | - isDir = file_wd_isdir(zName); |
| 545 | | - if( isDir==1 ){ |
| 546 | | - vfile_scan(&name, nRoot-1, scanFlags, pIgnore1, pIgnore2); |
| 547 | | - }else if( isDir==0 ){ |
| 548 | | - fossil_warning("not found: %s", &zName[nRoot]); |
| 549 | | - }else if( file_access(zName, R_OK) ){ |
| 550 | | - fossil_fatal("cannot open %s", &zName[nRoot]); |
| 551 | | - }else{ |
| 552 | | - db_multi_exec( |
| 553 | | - "INSERT OR IGNORE INTO sfile(x) VALUES(%Q)", |
| 554 | | - &zName[nRoot] |
| 555 | | - ); |
| 556 | | - } |
| 557 | | - blob_reset(&name); |
| 558 | | - } |
| 559 | | - } |
| 560 | | -} |
| 561 | | - |
| 562 | 797 | /* |
| 563 | 798 | ** COMMAND: extras |
| 564 | 799 | ** |
| 565 | 800 | ** Usage: %fossil extras ?OPTIONS? ?PATH1 ...? |
| 566 | 801 | ** |
| | @@ -588,22 +823,23 @@ |
| 588 | 823 | ** directory. |
| 589 | 824 | ** |
| 590 | 825 | ** See also: changes, clean, status |
| 591 | 826 | */ |
| 592 | 827 | void extras_cmd(void){ |
| 593 | | - Stmt q; |
| 828 | + Blob report = BLOB_INITIALIZER; |
| 594 | 829 | const char *zIgnoreFlag = find_option("ignore",0,1); |
| 595 | 830 | unsigned scanFlags = find_option("dotfiles",0,0)!=0 ? SCAN_ALL : 0; |
| 831 | + unsigned flags = C_EXTRA; |
| 596 | 832 | int showHdr = find_option("header",0,0)!=0; |
| 597 | | - int cwdRelative = 0; |
| 598 | 833 | Glob *pIgnore; |
| 599 | | - Blob rewrittenPathname; |
| 600 | | - const char *zPathname, *zDisplayName; |
| 601 | 834 | |
| 602 | 835 | if( find_option("temp",0,0)!=0 ) scanFlags |= SCAN_TEMP; |
| 603 | 836 | db_must_be_within_tree(); |
| 604 | | - cwdRelative = determine_cwd_relative_option(); |
| 837 | + |
| 838 | + if( determine_cwd_relative_option() ){ |
| 839 | + flags |= C_RELPATH; |
| 840 | + } |
| 605 | 841 | |
| 606 | 842 | if( db_get_boolean("dotfiles", 0) ) scanFlags |= SCAN_ALL; |
| 607 | 843 | |
| 608 | 844 | /* We should be done with options.. */ |
| 609 | 845 | verify_all_options(); |
| | @@ -610,41 +846,24 @@ |
| 610 | 846 | |
| 611 | 847 | if( zIgnoreFlag==0 ){ |
| 612 | 848 | zIgnoreFlag = db_get("ignore-glob", 0); |
| 613 | 849 | } |
| 614 | 850 | pIgnore = glob_create(zIgnoreFlag); |
| 615 | | - locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags, pIgnore, 0); |
| 851 | + locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags, pIgnore); |
| 616 | 852 | glob_free(pIgnore); |
| 617 | | - db_prepare(&q, |
| 618 | | - "SELECT x FROM sfile" |
| 619 | | - " WHERE x NOT IN (%s)" |
| 620 | | - " ORDER BY 1", |
| 621 | | - fossil_all_reserved_names(0) |
| 622 | | - ); |
| 623 | | - db_multi_exec("DELETE FROM sfile WHERE x IN (SELECT pathname FROM vfile)"); |
| 624 | | - blob_zero(&rewrittenPathname); |
| 625 | 853 | g.allowSymlinks = 1; /* Report on symbolic links */ |
| 626 | | - while( db_step(&q)==SQLITE_ROW ){ |
| 627 | | - zDisplayName = zPathname = db_column_text(&q, 0); |
| 628 | | - if( cwdRelative ){ |
| 629 | | - char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname); |
| 630 | | - file_relative_name(zFullName, &rewrittenPathname, 0); |
| 631 | | - free(zFullName); |
| 632 | | - zDisplayName = blob_str(&rewrittenPathname); |
| 633 | | - if( zDisplayName[0]=='.' && zDisplayName[1]=='/' ){ |
| 634 | | - zDisplayName += 2; /* no unnecessary ./ prefix */ |
| 635 | | - } |
| 636 | | - } |
| 854 | + |
| 855 | + blob_zero(&report); |
| 856 | + status_report(&report, flags); |
| 857 | + if( blob_size(&report) ){ |
| 637 | 858 | if( showHdr ){ |
| 638 | | - showHdr = 0; |
| 639 | 859 | fossil_print("Extras for %s at %s:\n", db_get("project-name","???"), |
| 640 | 860 | g.zLocalRoot); |
| 641 | 861 | } |
| 642 | | - fossil_print("%s\n", zDisplayName); |
| 862 | + blob_write_to_file(&report, "-"); |
| 643 | 863 | } |
| 644 | | - blob_reset(&rewrittenPathname); |
| 645 | | - db_finalize(&q); |
| 864 | + blob_reset(&report); |
| 646 | 865 | } |
| 647 | 866 | |
| 648 | 867 | /* |
| 649 | 868 | ** COMMAND: clean |
| 650 | 869 | ** |
| | @@ -790,21 +1009,22 @@ |
| 790 | 1009 | g.allowSymlinks = 1; /* Find symlinks too */ |
| 791 | 1010 | if( !dirsOnlyFlag ){ |
| 792 | 1011 | Stmt q; |
| 793 | 1012 | Blob repo; |
| 794 | 1013 | if( !dryRunFlag && !disableUndo ) undo_begin(); |
| 795 | | - locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags, pIgnore, 0); |
| 1014 | + locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags, pIgnore); |
| 796 | 1015 | db_prepare(&q, |
| 797 | | - "SELECT %Q || x FROM sfile" |
| 798 | | - " WHERE x NOT IN (%s)" |
| 1016 | + "SELECT %Q || pathname FROM sfile" |
| 1017 | + " WHERE pathname NOT IN (%s)" |
| 799 | 1018 | " ORDER BY 1", |
| 800 | 1019 | g.zLocalRoot, fossil_all_reserved_names(0) |
| 801 | 1020 | ); |
| 802 | 1021 | if( file_tree_name(g.zRepositoryName, &repo, 0, 0) ){ |
| 803 | | - db_multi_exec("DELETE FROM sfile WHERE x=%B", &repo); |
| 1022 | + db_multi_exec("DELETE FROM sfile WHERE pathname=%B", &repo); |
| 804 | 1023 | } |
| 805 | | - db_multi_exec("DELETE FROM sfile WHERE x IN (SELECT pathname FROM vfile)"); |
| 1024 | + db_multi_exec("DELETE FROM sfile WHERE pathname IN" |
| 1025 | + " (SELECT pathname FROM vfile)"); |
| 806 | 1026 | while( db_step(&q)==SQLITE_ROW ){ |
| 807 | 1027 | const char *zName = db_column_text(&q, 0); |
| 808 | 1028 | if( glob_match(pKeep, zName+nRoot) ){ |
| 809 | 1029 | if( verboseFlag ){ |
| 810 | 1030 | fossil_print("KEPT file \"%s\" not removed (due to --keep" |
| | @@ -1081,11 +1301,11 @@ |
| 1081 | 1301 | } |
| 1082 | 1302 | } |
| 1083 | 1303 | blob_appendf(&prompt, "\n#\n"); |
| 1084 | 1304 | } |
| 1085 | 1305 | } |
| 1086 | | - status_report(&prompt, "# ", 1, 0); |
| 1306 | + status_report(&prompt, C_DEFAULT | C_FATAL | C_COMMENT); |
| 1087 | 1307 | if( g.markPrivate ){ |
| 1088 | 1308 | blob_append(&prompt, |
| 1089 | 1309 | "# PRIVATE BRANCH: This check-in will be private and will not sync to\n" |
| 1090 | 1310 | "# repositories.\n" |
| 1091 | 1311 | "#\n", -1 |
| 1092 | 1312 | |