| | @@ -21,115 +21,32 @@ |
| 21 | 21 | #include "config.h" |
| 22 | 22 | #include "checkin.h" |
| 23 | 23 | #include <assert.h> |
| 24 | 24 | |
| 25 | 25 | /* |
| 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. |
| 26 | +** Generate text describing all changes. Prepend zPrefix to each line |
| 27 | +** of output. |
| 111 | 28 | ** |
| 112 | 29 | ** 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. |
| 113 | 33 | */ |
| 114 | 34 | static void status_report( |
| 115 | 35 | Blob *report, /* Append the status report here */ |
| 116 | | - unsigned flags /* Filter and other configuration flags */ |
| 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 */ |
| 117 | 39 | ){ |
| 118 | 40 | Stmt q; |
| 41 | + int nPrefix = strlen(zPrefix); |
| 119 | 42 | int nErr = 0; |
| 120 | 43 | Blob rewrittenPathname; |
| 121 | | - Blob sql = BLOB_INITIALIZER, where = BLOB_INITIALIZER; |
| 44 | + Blob where; |
| 122 | 45 | const char *zName; |
| 123 | 46 | int i; |
| 124 | 47 | |
| 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. */ |
| 131 | 48 | blob_zero(&where); |
| 132 | 49 | for(i=2; i<g.argc; i++){ |
| 133 | 50 | Blob fname; |
| 134 | 51 | file_tree_name(g.argv[i], &fname, 0, 1); |
| 135 | 52 | zName = blob_str(&fname); |
| | @@ -144,187 +61,99 @@ |
| 144 | 61 | filename_collation(), zName, filename_collation(), |
| 145 | 62 | zName, filename_collation() |
| 146 | 63 | ); |
| 147 | 64 | } |
| 148 | 65 | |
| 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, 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 ? "blob.size" : "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); |
| 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; |
| 296 | 137 | } |
| 297 | 138 | free(zFullName); |
| 298 | 139 | } |
| 299 | 140 | blob_reset(&rewrittenPathname); |
| 300 | 141 | 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 | | - } |
| 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); |
| 326 | 155 | if( nErr ){ |
| 327 | 156 | fossil_fatal("aborting due to prior errors"); |
| 328 | 157 | } |
| 329 | 158 | } |
| 330 | 159 | |
| | @@ -341,229 +170,116 @@ |
| 341 | 170 | int relPathOption = find_option("rel-paths", 0, 0)!=0; |
| 342 | 171 | if( absPathOption ){ relativePaths = 0; } |
| 343 | 172 | if( relPathOption ){ relativePaths = 1; } |
| 344 | 173 | return relativePaths; |
| 345 | 174 | } |
| 175 | + |
| 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 | +} |
| 346 | 200 | |
| 347 | 201 | /* |
| 348 | 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 | +/* |
| 349 | 237 | ** COMMAND: status |
| 350 | 238 | ** |
| 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: |
| 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 | +** |
| 407 | 248 | ** --abs-paths Display absolute pathnames. |
| 408 | 249 | ** --rel-paths Display pathnames relative to the current working |
| 409 | 250 | ** 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 |
| 251 | +** --sha1sum Verify file status using SHA1 hashing rather |
| 252 | +** than relying on file mtimes. |
| 253 | +** |
| 254 | +** See also: changes, extras, ls |
| 440 | 255 | */ |
| 441 | 256 | 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; |
| 257 | + int vid; |
| 461 | 258 | 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. */ |
| 259 | + int showHdr = find_option("header",0,0)!=0; |
| 260 | + int verboseFlag = find_option("verbose","v",0)!=0; |
| 261 | + int cwdRelative = 0; |
| 501 | 262 | db_must_be_within_tree(); |
| 263 | + /* 012345678901234 */ |
| 264 | + cwdRelative = determine_cwd_relative_option(); |
| 502 | 265 | |
| 503 | | - /* Get checkout version. l*/ |
| 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 | + } |
| 504 | 274 | 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 | | - } |
| 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); |
| 565 | 281 | } |
| 566 | 282 | |
| 567 | 283 | /* |
| 568 | 284 | ** Take care of -r version of ls command |
| 569 | 285 | */ |
| | @@ -791,10 +507,59 @@ |
| 791 | 507 | } |
| 792 | 508 | free(zFullName); |
| 793 | 509 | } |
| 794 | 510 | db_finalize(&q); |
| 795 | 511 | } |
| 512 | + |
| 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 | +} |
| 796 | 561 | |
| 797 | 562 | /* |
| 798 | 563 | ** COMMAND: extras |
| 799 | 564 | ** |
| 800 | 565 | ** Usage: %fossil extras ?OPTIONS? ?PATH1 ...? |
| | @@ -823,23 +588,22 @@ |
| 823 | 588 | ** directory. |
| 824 | 589 | ** |
| 825 | 590 | ** See also: changes, clean, status |
| 826 | 591 | */ |
| 827 | 592 | void extras_cmd(void){ |
| 828 | | - Blob report = BLOB_INITIALIZER; |
| 593 | + Stmt q; |
| 829 | 594 | const char *zIgnoreFlag = find_option("ignore",0,1); |
| 830 | 595 | unsigned scanFlags = find_option("dotfiles",0,0)!=0 ? SCAN_ALL : 0; |
| 831 | | - unsigned flags = C_EXTRA; |
| 832 | 596 | int showHdr = find_option("header",0,0)!=0; |
| 597 | + int cwdRelative = 0; |
| 833 | 598 | Glob *pIgnore; |
| 599 | + Blob rewrittenPathname; |
| 600 | + const char *zPathname, *zDisplayName; |
| 834 | 601 | |
| 835 | 602 | if( find_option("temp",0,0)!=0 ) scanFlags |= SCAN_TEMP; |
| 836 | 603 | db_must_be_within_tree(); |
| 837 | | - |
| 838 | | - if( determine_cwd_relative_option() ){ |
| 839 | | - flags |= C_RELPATH; |
| 840 | | - } |
| 604 | + cwdRelative = determine_cwd_relative_option(); |
| 841 | 605 | |
| 842 | 606 | if( db_get_boolean("dotfiles", 0) ) scanFlags |= SCAN_ALL; |
| 843 | 607 | |
| 844 | 608 | /* We should be done with options.. */ |
| 845 | 609 | verify_all_options(); |
| | @@ -846,24 +610,41 @@ |
| 846 | 610 | |
| 847 | 611 | if( zIgnoreFlag==0 ){ |
| 848 | 612 | zIgnoreFlag = db_get("ignore-glob", 0); |
| 849 | 613 | } |
| 850 | 614 | pIgnore = glob_create(zIgnoreFlag); |
| 851 | | - locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags, pIgnore); |
| 615 | + locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags, pIgnore, 0); |
| 852 | 616 | 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); |
| 853 | 625 | g.allowSymlinks = 1; /* Report on symbolic links */ |
| 854 | | - |
| 855 | | - blob_zero(&report); |
| 856 | | - status_report(&report, flags); |
| 857 | | - if( blob_size(&report) ){ |
| 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 | + } |
| 858 | 637 | if( showHdr ){ |
| 638 | + showHdr = 0; |
| 859 | 639 | fossil_print("Extras for %s at %s:\n", db_get("project-name","???"), |
| 860 | 640 | g.zLocalRoot); |
| 861 | 641 | } |
| 862 | | - blob_write_to_file(&report, "-"); |
| 642 | + fossil_print("%s\n", zDisplayName); |
| 863 | 643 | } |
| 864 | | - blob_reset(&report); |
| 644 | + blob_reset(&rewrittenPathname); |
| 645 | + db_finalize(&q); |
| 865 | 646 | } |
| 866 | 647 | |
| 867 | 648 | /* |
| 868 | 649 | ** COMMAND: clean |
| 869 | 650 | ** |
| | @@ -1009,22 +790,21 @@ |
| 1009 | 790 | g.allowSymlinks = 1; /* Find symlinks too */ |
| 1010 | 791 | if( !dirsOnlyFlag ){ |
| 1011 | 792 | Stmt q; |
| 1012 | 793 | Blob repo; |
| 1013 | 794 | if( !dryRunFlag && !disableUndo ) undo_begin(); |
| 1014 | | - locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags, pIgnore); |
| 795 | + locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags, pIgnore, 0); |
| 1015 | 796 | db_prepare(&q, |
| 1016 | | - "SELECT %Q || pathname FROM sfile" |
| 1017 | | - " WHERE pathname NOT IN (%s)" |
| 797 | + "SELECT %Q || x FROM sfile" |
| 798 | + " WHERE x NOT IN (%s)" |
| 1018 | 799 | " ORDER BY 1", |
| 1019 | 800 | g.zLocalRoot, fossil_all_reserved_names(0) |
| 1020 | 801 | ); |
| 1021 | 802 | if( file_tree_name(g.zRepositoryName, &repo, 0, 0) ){ |
| 1022 | | - db_multi_exec("DELETE FROM sfile WHERE pathname=%B", &repo); |
| 803 | + db_multi_exec("DELETE FROM sfile WHERE x=%B", &repo); |
| 1023 | 804 | } |
| 1024 | | - db_multi_exec("DELETE FROM sfile WHERE pathname IN" |
| 1025 | | - " (SELECT pathname FROM vfile)"); |
| 805 | + db_multi_exec("DELETE FROM sfile WHERE x IN (SELECT pathname FROM vfile)"); |
| 1026 | 806 | while( db_step(&q)==SQLITE_ROW ){ |
| 1027 | 807 | const char *zName = db_column_text(&q, 0); |
| 1028 | 808 | if( glob_match(pKeep, zName+nRoot) ){ |
| 1029 | 809 | if( verboseFlag ){ |
| 1030 | 810 | fossil_print("KEPT file \"%s\" not removed (due to --keep" |
| | @@ -1301,11 +1081,11 @@ |
| 1301 | 1081 | } |
| 1302 | 1082 | } |
| 1303 | 1083 | blob_appendf(&prompt, "\n#\n"); |
| 1304 | 1084 | } |
| 1305 | 1085 | } |
| 1306 | | - status_report(&prompt, C_DEFAULT | C_FATAL | C_COMMENT); |
| 1086 | + status_report(&prompt, "# ", 1, 0); |
| 1307 | 1087 | if( g.markPrivate ){ |
| 1308 | 1088 | blob_append(&prompt, |
| 1309 | 1089 | "# PRIVATE BRANCH: This check-in will be private and will not sync to\n" |
| 1310 | 1090 | "# repositories.\n" |
| 1311 | 1091 | "#\n", -1 |
| 1312 | 1092 | |