Fossil SCM
merge from trunk
Commit
1e801695d30446cf722990a17b4e51b45be7351e
Parent
8050311dd57f595…
13 files changed
+1
+21
-5
+147
-54
+147
-54
+4
-4
+4
-4
+2
-2
+1
-1
+1
-1
+1
-1
+1
-1
+25
-9
+25
-9
+1
| --- src/doc.c | ||
| +++ src/doc.c | ||
| @@ -240,10 +240,11 @@ | ||
| 240 | 240 | { "step", 4, "application/STEP" }, |
| 241 | 241 | { "stl", 3, "application/SLA" }, |
| 242 | 242 | { "stp", 3, "application/STEP" }, |
| 243 | 243 | { "sv4cpio", 7, "application/x-sv4cpio" }, |
| 244 | 244 | { "sv4crc", 6, "application/x-sv4crc" }, |
| 245 | + { "svg", 3, "image/svg+xml" }, | |
| 245 | 246 | { "swf", 3, "application/x-shockwave-flash" }, |
| 246 | 247 | { "t", 1, "application/x-troff" }, |
| 247 | 248 | { "tar", 3, "application/x-tar" }, |
| 248 | 249 | { "tcl", 3, "application/x-tcl" }, |
| 249 | 250 | { "tex", 3, "application/x-tex" }, |
| 250 | 251 |
| --- src/doc.c | |
| +++ src/doc.c | |
| @@ -240,10 +240,11 @@ | |
| 240 | { "step", 4, "application/STEP" }, |
| 241 | { "stl", 3, "application/SLA" }, |
| 242 | { "stp", 3, "application/STEP" }, |
| 243 | { "sv4cpio", 7, "application/x-sv4cpio" }, |
| 244 | { "sv4crc", 6, "application/x-sv4crc" }, |
| 245 | { "swf", 3, "application/x-shockwave-flash" }, |
| 246 | { "t", 1, "application/x-troff" }, |
| 247 | { "tar", 3, "application/x-tar" }, |
| 248 | { "tcl", 3, "application/x-tcl" }, |
| 249 | { "tex", 3, "application/x-tex" }, |
| 250 |
| --- src/doc.c | |
| +++ src/doc.c | |
| @@ -240,10 +240,11 @@ | |
| 240 | { "step", 4, "application/STEP" }, |
| 241 | { "stl", 3, "application/SLA" }, |
| 242 | { "stp", 3, "application/STEP" }, |
| 243 | { "sv4cpio", 7, "application/x-sv4cpio" }, |
| 244 | { "sv4crc", 6, "application/x-sv4crc" }, |
| 245 | { "svg", 3, "image/svg+xml" }, |
| 246 | { "swf", 3, "application/x-shockwave-flash" }, |
| 247 | { "t", 1, "application/x-troff" }, |
| 248 | { "tar", 3, "application/x-tar" }, |
| 249 | { "tcl", 3, "application/x-tcl" }, |
| 250 | { "tex", 3, "application/x-tex" }, |
| 251 |
+21
-5
| --- src/file.c | ||
| +++ src/file.c | ||
| @@ -309,16 +309,19 @@ | ||
| 309 | 309 | void cmd_test_canonical_name(void){ |
| 310 | 310 | int i; |
| 311 | 311 | Blob x; |
| 312 | 312 | blob_zero(&x); |
| 313 | 313 | for(i=2; i<g.argc; i++){ |
| 314 | + char zBuf[100]; | |
| 314 | 315 | const char *zName = g.argv[i]; |
| 315 | 316 | file_canonical_name(zName, &x); |
| 316 | 317 | printf("%s\n", blob_buffer(&x)); |
| 317 | 318 | blob_reset(&x); |
| 318 | - printf(" file_size = %lld\n", file_size(zName)); | |
| 319 | - printf(" file_mtime = %lld\n", file_mtime(zName)); | |
| 319 | + sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", file_size(zName)); | |
| 320 | + printf(" file_size = %s\n", zBuf); | |
| 321 | + sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", file_mtime(zName)); | |
| 322 | + printf(" file_mtime = %s\n", zBuf); | |
| 320 | 323 | printf(" file_isfile = %d\n", file_isfile(zName)); |
| 321 | 324 | printf(" file_isexe = %d\n", file_isexe(zName)); |
| 322 | 325 | printf(" file_isdir = %d\n", file_isdir(zName)); |
| 323 | 326 | } |
| 324 | 327 | } |
| @@ -426,22 +429,35 @@ | ||
| 426 | 429 | ** The root of the tree is defined by the g.zLocalRoot variable. |
| 427 | 430 | */ |
| 428 | 431 | int file_tree_name(const char *zOrigName, Blob *pOut, int errFatal){ |
| 429 | 432 | int n; |
| 430 | 433 | Blob full; |
| 434 | + int nFull; | |
| 435 | + char *zFull; | |
| 436 | + | |
| 437 | + blob_zero(pOut); | |
| 431 | 438 | db_must_be_within_tree(); |
| 432 | 439 | file_canonical_name(zOrigName, &full); |
| 433 | 440 | n = strlen(g.zLocalRoot); |
| 434 | - if( blob_size(&full)<=n || memcmp(g.zLocalRoot, blob_buffer(&full), n) ){ | |
| 441 | + assert( n>0 && g.zLocalRoot[n-1]=='/' ); | |
| 442 | + nFull = blob_size(&full); | |
| 443 | + zFull = blob_buffer(&full); | |
| 444 | + | |
| 445 | + /* Special case. zOrigName refers to g.zLocalRoot directory. */ | |
| 446 | + if( nFull==n-1 && memcmp(g.zLocalRoot, zFull, nFull)==0 ){ | |
| 447 | + blob_append(pOut, ".", 1); | |
| 448 | + return 1; | |
| 449 | + } | |
| 450 | + | |
| 451 | + if( nFull<=n || memcmp(g.zLocalRoot, zFull, n) ){ | |
| 435 | 452 | blob_reset(&full); |
| 436 | 453 | if( errFatal ){ |
| 437 | 454 | fossil_fatal("file outside of checkout tree: %s", zOrigName); |
| 438 | 455 | } |
| 439 | 456 | return 0; |
| 440 | 457 | } |
| 441 | - blob_zero(pOut); | |
| 442 | - blob_append(pOut, blob_buffer(&full)+n, blob_size(&full)-n); | |
| 458 | + blob_append(pOut, &zFull[n], nFull-n); | |
| 443 | 459 | return 1; |
| 444 | 460 | } |
| 445 | 461 | |
| 446 | 462 | /* |
| 447 | 463 | ** COMMAND: test-tree-name |
| 448 | 464 |
| --- src/file.c | |
| +++ src/file.c | |
| @@ -309,16 +309,19 @@ | |
| 309 | void cmd_test_canonical_name(void){ |
| 310 | int i; |
| 311 | Blob x; |
| 312 | blob_zero(&x); |
| 313 | for(i=2; i<g.argc; i++){ |
| 314 | const char *zName = g.argv[i]; |
| 315 | file_canonical_name(zName, &x); |
| 316 | printf("%s\n", blob_buffer(&x)); |
| 317 | blob_reset(&x); |
| 318 | printf(" file_size = %lld\n", file_size(zName)); |
| 319 | printf(" file_mtime = %lld\n", file_mtime(zName)); |
| 320 | printf(" file_isfile = %d\n", file_isfile(zName)); |
| 321 | printf(" file_isexe = %d\n", file_isexe(zName)); |
| 322 | printf(" file_isdir = %d\n", file_isdir(zName)); |
| 323 | } |
| 324 | } |
| @@ -426,22 +429,35 @@ | |
| 426 | ** The root of the tree is defined by the g.zLocalRoot variable. |
| 427 | */ |
| 428 | int file_tree_name(const char *zOrigName, Blob *pOut, int errFatal){ |
| 429 | int n; |
| 430 | Blob full; |
| 431 | db_must_be_within_tree(); |
| 432 | file_canonical_name(zOrigName, &full); |
| 433 | n = strlen(g.zLocalRoot); |
| 434 | if( blob_size(&full)<=n || memcmp(g.zLocalRoot, blob_buffer(&full), n) ){ |
| 435 | blob_reset(&full); |
| 436 | if( errFatal ){ |
| 437 | fossil_fatal("file outside of checkout tree: %s", zOrigName); |
| 438 | } |
| 439 | return 0; |
| 440 | } |
| 441 | blob_zero(pOut); |
| 442 | blob_append(pOut, blob_buffer(&full)+n, blob_size(&full)-n); |
| 443 | return 1; |
| 444 | } |
| 445 | |
| 446 | /* |
| 447 | ** COMMAND: test-tree-name |
| 448 |
| --- src/file.c | |
| +++ src/file.c | |
| @@ -309,16 +309,19 @@ | |
| 309 | void cmd_test_canonical_name(void){ |
| 310 | int i; |
| 311 | Blob x; |
| 312 | blob_zero(&x); |
| 313 | for(i=2; i<g.argc; i++){ |
| 314 | char zBuf[100]; |
| 315 | const char *zName = g.argv[i]; |
| 316 | file_canonical_name(zName, &x); |
| 317 | printf("%s\n", blob_buffer(&x)); |
| 318 | blob_reset(&x); |
| 319 | sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", file_size(zName)); |
| 320 | printf(" file_size = %s\n", zBuf); |
| 321 | sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", file_mtime(zName)); |
| 322 | printf(" file_mtime = %s\n", zBuf); |
| 323 | printf(" file_isfile = %d\n", file_isfile(zName)); |
| 324 | printf(" file_isexe = %d\n", file_isexe(zName)); |
| 325 | printf(" file_isdir = %d\n", file_isdir(zName)); |
| 326 | } |
| 327 | } |
| @@ -426,22 +429,35 @@ | |
| 429 | ** The root of the tree is defined by the g.zLocalRoot variable. |
| 430 | */ |
| 431 | int file_tree_name(const char *zOrigName, Blob *pOut, int errFatal){ |
| 432 | int n; |
| 433 | Blob full; |
| 434 | int nFull; |
| 435 | char *zFull; |
| 436 | |
| 437 | blob_zero(pOut); |
| 438 | db_must_be_within_tree(); |
| 439 | file_canonical_name(zOrigName, &full); |
| 440 | n = strlen(g.zLocalRoot); |
| 441 | assert( n>0 && g.zLocalRoot[n-1]=='/' ); |
| 442 | nFull = blob_size(&full); |
| 443 | zFull = blob_buffer(&full); |
| 444 | |
| 445 | /* Special case. zOrigName refers to g.zLocalRoot directory. */ |
| 446 | if( nFull==n-1 && memcmp(g.zLocalRoot, zFull, nFull)==0 ){ |
| 447 | blob_append(pOut, ".", 1); |
| 448 | return 1; |
| 449 | } |
| 450 | |
| 451 | if( nFull<=n || memcmp(g.zLocalRoot, zFull, n) ){ |
| 452 | blob_reset(&full); |
| 453 | if( errFatal ){ |
| 454 | fossil_fatal("file outside of checkout tree: %s", zOrigName); |
| 455 | } |
| 456 | return 0; |
| 457 | } |
| 458 | blob_append(pOut, &zFull[n], nFull-n); |
| 459 | return 1; |
| 460 | } |
| 461 | |
| 462 | /* |
| 463 | ** COMMAND: test-tree-name |
| 464 |
+147
-54
| --- src/finfo.c | ||
| +++ src/finfo.c | ||
| @@ -21,78 +21,171 @@ | ||
| 21 | 21 | #include "finfo.h" |
| 22 | 22 | |
| 23 | 23 | /* |
| 24 | 24 | ** COMMAND: finfo |
| 25 | 25 | ** |
| 26 | -** Usage: %fossil finfo FILENAME | |
| 26 | +** Usage: %fossil finfo {?-l|--log? / -s|--status / --p|--print} FILENAME | |
| 27 | +** | |
| 28 | +** Print the complete change history for a single file going backwards | |
| 29 | +** in time. The default is -l. | |
| 30 | +** | |
| 31 | +** For the -l|--log option: If "-b|--brief" is specified one line per revision | |
| 32 | +** is printed, otherwise the full comment is printed. The "--limit N" | |
| 33 | +** and "--offset P" options limits the output to the first N changes | |
| 34 | +** after skipping P changes. | |
| 27 | 35 | ** |
| 28 | -** Print the change history for a single file. | |
| 36 | +** In the -s form prints the status as <status> <revision>. This is | |
| 37 | +** a quick status and does not check for up-to-date-ness of the file. | |
| 29 | 38 | ** |
| 30 | -** The "--limit N" and "--offset P" options limit the output to the first | |
| 31 | -** N changes after skipping P changes. | |
| 39 | +** The -p form, there's an optional flag "-r|--revision REVISION". The | |
| 40 | +** specified version (or the latest checked out version) is printed to | |
| 41 | +** stdout. | |
| 32 | 42 | ** |
| 33 | 43 | ** The history of a file can also be viewed in the gui: |
| 34 | 44 | ** * Go to the <a href="dir">file browser</a> and drill down to the file |
| 35 | 45 | */ |
| 36 | 46 | void finfo_cmd(void){ |
| 37 | - Stmt q; | |
| 38 | 47 | int vid; |
| 39 | - Blob dest; | |
| 40 | - const char *zFilename; | |
| 41 | - const char *zLimit; | |
| 42 | - const char *zOffset; | |
| 43 | - int iLimit, iOffset; | |
| 44 | 48 | |
| 45 | 49 | db_must_be_within_tree(); |
| 46 | 50 | vid = db_lget_int("checkout", 0); |
| 47 | 51 | if( vid==0 ){ |
| 48 | 52 | fossil_panic("no checkout to finfo files in"); |
| 49 | 53 | } |
| 50 | - zLimit = find_option("limit",0,1); | |
| 51 | - iLimit = zLimit ? atoi(zLimit) : -1; | |
| 52 | - zOffset = find_option("offset",0,1); | |
| 53 | - iOffset = zOffset ? atoi(zOffset) : 0; | |
| 54 | - if (g.argc<3) { | |
| 55 | - usage("FILENAME"); | |
| 56 | - } | |
| 57 | - file_tree_name(g.argv[2], &dest, 1); | |
| 58 | - zFilename = blob_str(&dest); | |
| 59 | - db_prepare(&q, | |
| 60 | - "SELECT " | |
| 61 | - " (SELECT uuid FROM blob WHERE rid=mlink.fid)," /* New file */ | |
| 62 | - " (SELECT uuid FROM blob WHERE rid=mlink.mid)," /* The check-in */ | |
| 63 | - " date(event.mtime,'localtime')," | |
| 64 | - " coalesce(event.ecomment, event.comment)," | |
| 65 | - " coalesce(event.euser, event.user)" | |
| 66 | - " FROM mlink, event" | |
| 67 | - " WHERE mlink.fnid=(SELECT fnid FROM filename WHERE name=%Q)" | |
| 68 | - " AND event.objid=mlink.mid" | |
| 69 | - " ORDER BY event.mtime DESC LIMIT %d OFFSET %d /*sort*/", | |
| 70 | - zFilename, iLimit, iOffset | |
| 71 | - ); | |
| 72 | - | |
| 73 | - printf("History of %s\n", zFilename); | |
| 74 | - while( db_step(&q)==SQLITE_ROW ){ | |
| 75 | - const char *zFileUuid = db_column_text(&q, 0); | |
| 76 | - const char *zCiUuid = db_column_text(&q, 1); | |
| 77 | - const char *zDate = db_column_text(&q, 2); | |
| 78 | - const char *zCom = db_column_text(&q, 3); | |
| 79 | - const char *zUser = db_column_text(&q, 4); | |
| 80 | - char *zOut; | |
| 81 | - printf("%s ", zDate); | |
| 82 | - if( zFileUuid==0 ){ | |
| 83 | - zOut = sqlite3_mprintf("[%.10s] DELETED %s (user: %s)", | |
| 84 | - zCiUuid, zCom, zUser); | |
| 85 | - }else{ | |
| 86 | - zOut = sqlite3_mprintf("[%.10s] %s (user: %s, artifact: [%.10s])", | |
| 87 | - zCiUuid, zCom, zUser, zFileUuid); | |
| 88 | - } | |
| 89 | - comment_print(zOut, 11, 79); | |
| 90 | - sqlite3_free(zOut); | |
| 91 | - } | |
| 92 | - db_finalize(&q); | |
| 93 | - blob_reset(&dest); | |
| 54 | + vfile_check_signature(vid, 1); | |
| 55 | + if (find_option("status","s",0)) { | |
| 56 | + Stmt q; | |
| 57 | + Blob line; | |
| 58 | + Blob fname; | |
| 59 | + | |
| 60 | + if( g.argc!=3 ) usage("-s|--status FILENAME"); | |
| 61 | + file_tree_name(g.argv[2], &fname, 1); | |
| 62 | + db_prepare(&q, | |
| 63 | + "SELECT pathname, deleted, rid, chnged, coalesce(origname!=pathname,0)" | |
| 64 | + " FROM vfile WHERE vfile.pathname=%B", &fname); | |
| 65 | + blob_zero(&line); | |
| 66 | + if ( db_step(&q)==SQLITE_ROW ) { | |
| 67 | + Blob uuid; | |
| 68 | + int isDeleted = db_column_int(&q, 1); | |
| 69 | + int isNew = db_column_int(&q,2) == 0; | |
| 70 | + int chnged = db_column_int(&q,3); | |
| 71 | + int renamed = db_column_int(&q,4); | |
| 72 | + | |
| 73 | + blob_zero(&uuid); | |
| 74 | + db_blob(&uuid, | |
| 75 | + "SELECT uuid FROM blob, mlink, vfile WHERE " | |
| 76 | + "blob.rid = mlink.mid AND mlink.fid = vfile.rid AND " | |
| 77 | + "vfile.pathname=%B", | |
| 78 | + &fname | |
| 79 | + ); | |
| 80 | + if( isNew ){ | |
| 81 | + blob_appendf(&line, "new"); | |
| 82 | + }else if( isDeleted ){ | |
| 83 | + blob_appendf(&line, "deleted"); | |
| 84 | + }else if( renamed ){ | |
| 85 | + blob_appendf(&line, "renamed"); | |
| 86 | + }else if( chnged ){ | |
| 87 | + blob_appendf(&line, "edited"); | |
| 88 | + }else{ | |
| 89 | + blob_appendf(&line, "unchanged"); | |
| 90 | + } | |
| 91 | + blob_appendf(&line, " "); | |
| 92 | + blob_appendf(&line, " %10.10s", blob_str(&uuid)); | |
| 93 | + blob_reset(&uuid); | |
| 94 | + }else{ | |
| 95 | + blob_appendf(&line, "unknown 0000000000"); | |
| 96 | + } | |
| 97 | + db_finalize(&q); | |
| 98 | + printf("%s\n", blob_str(&line)); | |
| 99 | + blob_reset(&fname); | |
| 100 | + blob_reset(&line); | |
| 101 | + }else if( find_option("print","p",0) ){ | |
| 102 | + Blob record; | |
| 103 | + Blob fname; | |
| 104 | + const char *zRevision = find_option("revision", "r", 1); | |
| 105 | + | |
| 106 | + file_tree_name(g.argv[2], &fname, 1); | |
| 107 | + if( zRevision ){ | |
| 108 | + historical_version_of_file(zRevision, blob_str(&fname), &record, 0); | |
| 109 | + }else{ | |
| 110 | + int rid = db_int(0, "SELECT rid FROM vfile WHERE pathname=%B", &fname); | |
| 111 | + if( rid==0 ){ | |
| 112 | + fossil_fatal("no history for file: %b", &fname); | |
| 113 | + } | |
| 114 | + content_get(rid, &record); | |
| 115 | + } | |
| 116 | + blob_write_to_file(&record, "-"); | |
| 117 | + blob_reset(&record); | |
| 118 | + blob_reset(&fname); | |
| 119 | + }else{ | |
| 120 | + Blob line; | |
| 121 | + Stmt q; | |
| 122 | + Blob fname; | |
| 123 | + int rid; | |
| 124 | + const char *zFilename; | |
| 125 | + const char *zLimit; | |
| 126 | + const char *zOffset; | |
| 127 | + int iLimit, iOffset, iBrief; | |
| 128 | + | |
| 129 | + if( find_option("log","l",0) ){ | |
| 130 | + /* this is the default, no-op */ | |
| 131 | + } | |
| 132 | + zLimit = find_option("limit",0,1); | |
| 133 | + iLimit = zLimit ? atoi(zLimit) : -1; | |
| 134 | + zOffset = find_option("offset",0,1); | |
| 135 | + iOffset = zOffset ? atoi(zOffset) : 0; | |
| 136 | + iBrief = (find_option("brief","b",0) == 0); | |
| 137 | + if( g.argc!=3 ){ | |
| 138 | + usage("?-l|--log? ?-b|--brief? FILENAME"); | |
| 139 | + } | |
| 140 | + file_tree_name(g.argv[2], &fname, 1); | |
| 141 | + rid = db_int(0, "SELECT rid FROM vfile WHERE pathname=%B", &fname); | |
| 142 | + if( rid==0 ){ | |
| 143 | + fossil_fatal("no history for file: %b", &fname); | |
| 144 | + } | |
| 145 | + zFilename = blob_str(&fname); | |
| 146 | + db_prepare(&q, | |
| 147 | + "SELECT b.uuid, ci.uuid, date(event.mtime,'localtime')," | |
| 148 | + " coalesce(event.ecomment, event.comment)," | |
| 149 | + " coalesce(event.euser, event.user)" | |
| 150 | + " FROM mlink, blob b, event, blob ci" | |
| 151 | + " WHERE mlink.fnid=(SELECT fnid FROM filename WHERE name=%Q)" | |
| 152 | + " AND b.rid=mlink.fid" | |
| 153 | + " AND event.objid=mlink.mid" | |
| 154 | + " AND event.objid=ci.rid" | |
| 155 | + " ORDER BY event.mtime DESC LIMIT %d OFFSET %d", | |
| 156 | + zFilename, iLimit, iOffset | |
| 157 | + ); | |
| 158 | + blob_zero(&line); | |
| 159 | + if( iBrief ){ | |
| 160 | + printf("History of %s\n", blob_str(&fname)); | |
| 161 | + } | |
| 162 | + while( db_step(&q)==SQLITE_ROW ){ | |
| 163 | + const char *zFileUuid = db_column_text(&q, 0); | |
| 164 | + const char *zCiUuid = db_column_text(&q,1); | |
| 165 | + const char *zDate = db_column_text(&q, 2); | |
| 166 | + const char *zCom = db_column_text(&q, 3); | |
| 167 | + const char *zUser = db_column_text(&q, 4); | |
| 168 | + char *zOut; | |
| 169 | + if( iBrief ){ | |
| 170 | + printf("%s ", zDate); | |
| 171 | + zOut = sqlite3_mprintf("[%.10s] %s (user: %s, artifact: [%.10s])", | |
| 172 | + zCiUuid, zCom, zUser, zFileUuid); | |
| 173 | + comment_print(zOut, 11, 79); | |
| 174 | + sqlite3_free(zOut); | |
| 175 | + }else{ | |
| 176 | + blob_reset(&line); | |
| 177 | + blob_appendf(&line, "%.10s ", zCiUuid); | |
| 178 | + blob_appendf(&line, "%.10s ", zDate); | |
| 179 | + blob_appendf(&line, "%8.8s ", zUser); | |
| 180 | + blob_appendf(&line,"%-40.40s\n", zCom ); | |
| 181 | + comment_print(blob_str(&line), 0, 79); | |
| 182 | + } | |
| 183 | + } | |
| 184 | + db_finalize(&q); | |
| 185 | + blob_reset(&fname); | |
| 186 | + } | |
| 94 | 187 | } |
| 95 | 188 | |
| 96 | 189 | |
| 97 | 190 | /* |
| 98 | 191 | ** WEBPAGE: finfo |
| 99 | 192 |
| --- src/finfo.c | |
| +++ src/finfo.c | |
| @@ -21,78 +21,171 @@ | |
| 21 | #include "finfo.h" |
| 22 | |
| 23 | /* |
| 24 | ** COMMAND: finfo |
| 25 | ** |
| 26 | ** Usage: %fossil finfo FILENAME |
| 27 | ** |
| 28 | ** Print the change history for a single file. |
| 29 | ** |
| 30 | ** The "--limit N" and "--offset P" options limit the output to the first |
| 31 | ** N changes after skipping P changes. |
| 32 | ** |
| 33 | ** The history of a file can also be viewed in the gui: |
| 34 | ** * Go to the <a href="dir">file browser</a> and drill down to the file |
| 35 | */ |
| 36 | void finfo_cmd(void){ |
| 37 | Stmt q; |
| 38 | int vid; |
| 39 | Blob dest; |
| 40 | const char *zFilename; |
| 41 | const char *zLimit; |
| 42 | const char *zOffset; |
| 43 | int iLimit, iOffset; |
| 44 | |
| 45 | db_must_be_within_tree(); |
| 46 | vid = db_lget_int("checkout", 0); |
| 47 | if( vid==0 ){ |
| 48 | fossil_panic("no checkout to finfo files in"); |
| 49 | } |
| 50 | zLimit = find_option("limit",0,1); |
| 51 | iLimit = zLimit ? atoi(zLimit) : -1; |
| 52 | zOffset = find_option("offset",0,1); |
| 53 | iOffset = zOffset ? atoi(zOffset) : 0; |
| 54 | if (g.argc<3) { |
| 55 | usage("FILENAME"); |
| 56 | } |
| 57 | file_tree_name(g.argv[2], &dest, 1); |
| 58 | zFilename = blob_str(&dest); |
| 59 | db_prepare(&q, |
| 60 | "SELECT " |
| 61 | " (SELECT uuid FROM blob WHERE rid=mlink.fid)," /* New file */ |
| 62 | " (SELECT uuid FROM blob WHERE rid=mlink.mid)," /* The check-in */ |
| 63 | " date(event.mtime,'localtime')," |
| 64 | " coalesce(event.ecomment, event.comment)," |
| 65 | " coalesce(event.euser, event.user)" |
| 66 | " FROM mlink, event" |
| 67 | " WHERE mlink.fnid=(SELECT fnid FROM filename WHERE name=%Q)" |
| 68 | " AND event.objid=mlink.mid" |
| 69 | " ORDER BY event.mtime DESC LIMIT %d OFFSET %d /*sort*/", |
| 70 | zFilename, iLimit, iOffset |
| 71 | ); |
| 72 | |
| 73 | printf("History of %s\n", zFilename); |
| 74 | while( db_step(&q)==SQLITE_ROW ){ |
| 75 | const char *zFileUuid = db_column_text(&q, 0); |
| 76 | const char *zCiUuid = db_column_text(&q, 1); |
| 77 | const char *zDate = db_column_text(&q, 2); |
| 78 | const char *zCom = db_column_text(&q, 3); |
| 79 | const char *zUser = db_column_text(&q, 4); |
| 80 | char *zOut; |
| 81 | printf("%s ", zDate); |
| 82 | if( zFileUuid==0 ){ |
| 83 | zOut = sqlite3_mprintf("[%.10s] DELETED %s (user: %s)", |
| 84 | zCiUuid, zCom, zUser); |
| 85 | }else{ |
| 86 | zOut = sqlite3_mprintf("[%.10s] %s (user: %s, artifact: [%.10s])", |
| 87 | zCiUuid, zCom, zUser, zFileUuid); |
| 88 | } |
| 89 | comment_print(zOut, 11, 79); |
| 90 | sqlite3_free(zOut); |
| 91 | } |
| 92 | db_finalize(&q); |
| 93 | blob_reset(&dest); |
| 94 | } |
| 95 | |
| 96 | |
| 97 | /* |
| 98 | ** WEBPAGE: finfo |
| 99 |
| --- src/finfo.c | |
| +++ src/finfo.c | |
| @@ -21,78 +21,171 @@ | |
| 21 | #include "finfo.h" |
| 22 | |
| 23 | /* |
| 24 | ** COMMAND: finfo |
| 25 | ** |
| 26 | ** Usage: %fossil finfo {?-l|--log? / -s|--status / --p|--print} FILENAME |
| 27 | ** |
| 28 | ** Print the complete change history for a single file going backwards |
| 29 | ** in time. The default is -l. |
| 30 | ** |
| 31 | ** For the -l|--log option: If "-b|--brief" is specified one line per revision |
| 32 | ** is printed, otherwise the full comment is printed. The "--limit N" |
| 33 | ** and "--offset P" options limits the output to the first N changes |
| 34 | ** after skipping P changes. |
| 35 | ** |
| 36 | ** In the -s form prints the status as <status> <revision>. This is |
| 37 | ** a quick status and does not check for up-to-date-ness of the file. |
| 38 | ** |
| 39 | ** The -p form, there's an optional flag "-r|--revision REVISION". The |
| 40 | ** specified version (or the latest checked out version) is printed to |
| 41 | ** stdout. |
| 42 | ** |
| 43 | ** The history of a file can also be viewed in the gui: |
| 44 | ** * Go to the <a href="dir">file browser</a> and drill down to the file |
| 45 | */ |
| 46 | void finfo_cmd(void){ |
| 47 | int vid; |
| 48 | |
| 49 | db_must_be_within_tree(); |
| 50 | vid = db_lget_int("checkout", 0); |
| 51 | if( vid==0 ){ |
| 52 | fossil_panic("no checkout to finfo files in"); |
| 53 | } |
| 54 | vfile_check_signature(vid, 1); |
| 55 | if (find_option("status","s",0)) { |
| 56 | Stmt q; |
| 57 | Blob line; |
| 58 | Blob fname; |
| 59 | |
| 60 | if( g.argc!=3 ) usage("-s|--status FILENAME"); |
| 61 | file_tree_name(g.argv[2], &fname, 1); |
| 62 | db_prepare(&q, |
| 63 | "SELECT pathname, deleted, rid, chnged, coalesce(origname!=pathname,0)" |
| 64 | " FROM vfile WHERE vfile.pathname=%B", &fname); |
| 65 | blob_zero(&line); |
| 66 | if ( db_step(&q)==SQLITE_ROW ) { |
| 67 | Blob uuid; |
| 68 | int isDeleted = db_column_int(&q, 1); |
| 69 | int isNew = db_column_int(&q,2) == 0; |
| 70 | int chnged = db_column_int(&q,3); |
| 71 | int renamed = db_column_int(&q,4); |
| 72 | |
| 73 | blob_zero(&uuid); |
| 74 | db_blob(&uuid, |
| 75 | "SELECT uuid FROM blob, mlink, vfile WHERE " |
| 76 | "blob.rid = mlink.mid AND mlink.fid = vfile.rid AND " |
| 77 | "vfile.pathname=%B", |
| 78 | &fname |
| 79 | ); |
| 80 | if( isNew ){ |
| 81 | blob_appendf(&line, "new"); |
| 82 | }else if( isDeleted ){ |
| 83 | blob_appendf(&line, "deleted"); |
| 84 | }else if( renamed ){ |
| 85 | blob_appendf(&line, "renamed"); |
| 86 | }else if( chnged ){ |
| 87 | blob_appendf(&line, "edited"); |
| 88 | }else{ |
| 89 | blob_appendf(&line, "unchanged"); |
| 90 | } |
| 91 | blob_appendf(&line, " "); |
| 92 | blob_appendf(&line, " %10.10s", blob_str(&uuid)); |
| 93 | blob_reset(&uuid); |
| 94 | }else{ |
| 95 | blob_appendf(&line, "unknown 0000000000"); |
| 96 | } |
| 97 | db_finalize(&q); |
| 98 | printf("%s\n", blob_str(&line)); |
| 99 | blob_reset(&fname); |
| 100 | blob_reset(&line); |
| 101 | }else if( find_option("print","p",0) ){ |
| 102 | Blob record; |
| 103 | Blob fname; |
| 104 | const char *zRevision = find_option("revision", "r", 1); |
| 105 | |
| 106 | file_tree_name(g.argv[2], &fname, 1); |
| 107 | if( zRevision ){ |
| 108 | historical_version_of_file(zRevision, blob_str(&fname), &record, 0); |
| 109 | }else{ |
| 110 | int rid = db_int(0, "SELECT rid FROM vfile WHERE pathname=%B", &fname); |
| 111 | if( rid==0 ){ |
| 112 | fossil_fatal("no history for file: %b", &fname); |
| 113 | } |
| 114 | content_get(rid, &record); |
| 115 | } |
| 116 | blob_write_to_file(&record, "-"); |
| 117 | blob_reset(&record); |
| 118 | blob_reset(&fname); |
| 119 | }else{ |
| 120 | Blob line; |
| 121 | Stmt q; |
| 122 | Blob fname; |
| 123 | int rid; |
| 124 | const char *zFilename; |
| 125 | const char *zLimit; |
| 126 | const char *zOffset; |
| 127 | int iLimit, iOffset, iBrief; |
| 128 | |
| 129 | if( find_option("log","l",0) ){ |
| 130 | /* this is the default, no-op */ |
| 131 | } |
| 132 | zLimit = find_option("limit",0,1); |
| 133 | iLimit = zLimit ? atoi(zLimit) : -1; |
| 134 | zOffset = find_option("offset",0,1); |
| 135 | iOffset = zOffset ? atoi(zOffset) : 0; |
| 136 | iBrief = (find_option("brief","b",0) == 0); |
| 137 | if( g.argc!=3 ){ |
| 138 | usage("?-l|--log? ?-b|--brief? FILENAME"); |
| 139 | } |
| 140 | file_tree_name(g.argv[2], &fname, 1); |
| 141 | rid = db_int(0, "SELECT rid FROM vfile WHERE pathname=%B", &fname); |
| 142 | if( rid==0 ){ |
| 143 | fossil_fatal("no history for file: %b", &fname); |
| 144 | } |
| 145 | zFilename = blob_str(&fname); |
| 146 | db_prepare(&q, |
| 147 | "SELECT b.uuid, ci.uuid, date(event.mtime,'localtime')," |
| 148 | " coalesce(event.ecomment, event.comment)," |
| 149 | " coalesce(event.euser, event.user)" |
| 150 | " FROM mlink, blob b, event, blob ci" |
| 151 | " WHERE mlink.fnid=(SELECT fnid FROM filename WHERE name=%Q)" |
| 152 | " AND b.rid=mlink.fid" |
| 153 | " AND event.objid=mlink.mid" |
| 154 | " AND event.objid=ci.rid" |
| 155 | " ORDER BY event.mtime DESC LIMIT %d OFFSET %d", |
| 156 | zFilename, iLimit, iOffset |
| 157 | ); |
| 158 | blob_zero(&line); |
| 159 | if( iBrief ){ |
| 160 | printf("History of %s\n", blob_str(&fname)); |
| 161 | } |
| 162 | while( db_step(&q)==SQLITE_ROW ){ |
| 163 | const char *zFileUuid = db_column_text(&q, 0); |
| 164 | const char *zCiUuid = db_column_text(&q,1); |
| 165 | const char *zDate = db_column_text(&q, 2); |
| 166 | const char *zCom = db_column_text(&q, 3); |
| 167 | const char *zUser = db_column_text(&q, 4); |
| 168 | char *zOut; |
| 169 | if( iBrief ){ |
| 170 | printf("%s ", zDate); |
| 171 | zOut = sqlite3_mprintf("[%.10s] %s (user: %s, artifact: [%.10s])", |
| 172 | zCiUuid, zCom, zUser, zFileUuid); |
| 173 | comment_print(zOut, 11, 79); |
| 174 | sqlite3_free(zOut); |
| 175 | }else{ |
| 176 | blob_reset(&line); |
| 177 | blob_appendf(&line, "%.10s ", zCiUuid); |
| 178 | blob_appendf(&line, "%.10s ", zDate); |
| 179 | blob_appendf(&line, "%8.8s ", zUser); |
| 180 | blob_appendf(&line,"%-40.40s\n", zCom ); |
| 181 | comment_print(blob_str(&line), 0, 79); |
| 182 | } |
| 183 | } |
| 184 | db_finalize(&q); |
| 185 | blob_reset(&fname); |
| 186 | } |
| 187 | } |
| 188 | |
| 189 | |
| 190 | /* |
| 191 | ** WEBPAGE: finfo |
| 192 |
+147
-54
| --- src/finfo.c | ||
| +++ src/finfo.c | ||
| @@ -21,78 +21,171 @@ | ||
| 21 | 21 | #include "finfo.h" |
| 22 | 22 | |
| 23 | 23 | /* |
| 24 | 24 | ** COMMAND: finfo |
| 25 | 25 | ** |
| 26 | -** Usage: %fossil finfo FILENAME | |
| 26 | +** Usage: %fossil finfo {?-l|--log? / -s|--status / --p|--print} FILENAME | |
| 27 | +** | |
| 28 | +** Print the complete change history for a single file going backwards | |
| 29 | +** in time. The default is -l. | |
| 30 | +** | |
| 31 | +** For the -l|--log option: If "-b|--brief" is specified one line per revision | |
| 32 | +** is printed, otherwise the full comment is printed. The "--limit N" | |
| 33 | +** and "--offset P" options limits the output to the first N changes | |
| 34 | +** after skipping P changes. | |
| 27 | 35 | ** |
| 28 | -** Print the change history for a single file. | |
| 36 | +** In the -s form prints the status as <status> <revision>. This is | |
| 37 | +** a quick status and does not check for up-to-date-ness of the file. | |
| 29 | 38 | ** |
| 30 | -** The "--limit N" and "--offset P" options limit the output to the first | |
| 31 | -** N changes after skipping P changes. | |
| 39 | +** The -p form, there's an optional flag "-r|--revision REVISION". The | |
| 40 | +** specified version (or the latest checked out version) is printed to | |
| 41 | +** stdout. | |
| 32 | 42 | ** |
| 33 | 43 | ** The history of a file can also be viewed in the gui: |
| 34 | 44 | ** * Go to the <a href="dir">file browser</a> and drill down to the file |
| 35 | 45 | */ |
| 36 | 46 | void finfo_cmd(void){ |
| 37 | - Stmt q; | |
| 38 | 47 | int vid; |
| 39 | - Blob dest; | |
| 40 | - const char *zFilename; | |
| 41 | - const char *zLimit; | |
| 42 | - const char *zOffset; | |
| 43 | - int iLimit, iOffset; | |
| 44 | 48 | |
| 45 | 49 | db_must_be_within_tree(); |
| 46 | 50 | vid = db_lget_int("checkout", 0); |
| 47 | 51 | if( vid==0 ){ |
| 48 | 52 | fossil_panic("no checkout to finfo files in"); |
| 49 | 53 | } |
| 50 | - zLimit = find_option("limit",0,1); | |
| 51 | - iLimit = zLimit ? atoi(zLimit) : -1; | |
| 52 | - zOffset = find_option("offset",0,1); | |
| 53 | - iOffset = zOffset ? atoi(zOffset) : 0; | |
| 54 | - if (g.argc<3) { | |
| 55 | - usage("FILENAME"); | |
| 56 | - } | |
| 57 | - file_tree_name(g.argv[2], &dest, 1); | |
| 58 | - zFilename = blob_str(&dest); | |
| 59 | - db_prepare(&q, | |
| 60 | - "SELECT " | |
| 61 | - " (SELECT uuid FROM blob WHERE rid=mlink.fid)," /* New file */ | |
| 62 | - " (SELECT uuid FROM blob WHERE rid=mlink.mid)," /* The check-in */ | |
| 63 | - " date(event.mtime,'localtime')," | |
| 64 | - " coalesce(event.ecomment, event.comment)," | |
| 65 | - " coalesce(event.euser, event.user)" | |
| 66 | - " FROM mlink, event" | |
| 67 | - " WHERE mlink.fnid=(SELECT fnid FROM filename WHERE name=%Q)" | |
| 68 | - " AND event.objid=mlink.mid" | |
| 69 | - " ORDER BY event.mtime DESC LIMIT %d OFFSET %d /*sort*/", | |
| 70 | - zFilename, iLimit, iOffset | |
| 71 | - ); | |
| 72 | - | |
| 73 | - printf("History of %s\n", zFilename); | |
| 74 | - while( db_step(&q)==SQLITE_ROW ){ | |
| 75 | - const char *zFileUuid = db_column_text(&q, 0); | |
| 76 | - const char *zCiUuid = db_column_text(&q, 1); | |
| 77 | - const char *zDate = db_column_text(&q, 2); | |
| 78 | - const char *zCom = db_column_text(&q, 3); | |
| 79 | - const char *zUser = db_column_text(&q, 4); | |
| 80 | - char *zOut; | |
| 81 | - printf("%s ", zDate); | |
| 82 | - if( zFileUuid==0 ){ | |
| 83 | - zOut = sqlite3_mprintf("[%.10s] DELETED %s (user: %s)", | |
| 84 | - zCiUuid, zCom, zUser); | |
| 85 | - }else{ | |
| 86 | - zOut = sqlite3_mprintf("[%.10s] %s (user: %s, artifact: [%.10s])", | |
| 87 | - zCiUuid, zCom, zUser, zFileUuid); | |
| 88 | - } | |
| 89 | - comment_print(zOut, 11, 79); | |
| 90 | - sqlite3_free(zOut); | |
| 91 | - } | |
| 92 | - db_finalize(&q); | |
| 93 | - blob_reset(&dest); | |
| 54 | + vfile_check_signature(vid, 1); | |
| 55 | + if (find_option("status","s",0)) { | |
| 56 | + Stmt q; | |
| 57 | + Blob line; | |
| 58 | + Blob fname; | |
| 59 | + | |
| 60 | + if( g.argc!=3 ) usage("-s|--status FILENAME"); | |
| 61 | + file_tree_name(g.argv[2], &fname, 1); | |
| 62 | + db_prepare(&q, | |
| 63 | + "SELECT pathname, deleted, rid, chnged, coalesce(origname!=pathname,0)" | |
| 64 | + " FROM vfile WHERE vfile.pathname=%B", &fname); | |
| 65 | + blob_zero(&line); | |
| 66 | + if ( db_step(&q)==SQLITE_ROW ) { | |
| 67 | + Blob uuid; | |
| 68 | + int isDeleted = db_column_int(&q, 1); | |
| 69 | + int isNew = db_column_int(&q,2) == 0; | |
| 70 | + int chnged = db_column_int(&q,3); | |
| 71 | + int renamed = db_column_int(&q,4); | |
| 72 | + | |
| 73 | + blob_zero(&uuid); | |
| 74 | + db_blob(&uuid, | |
| 75 | + "SELECT uuid FROM blob, mlink, vfile WHERE " | |
| 76 | + "blob.rid = mlink.mid AND mlink.fid = vfile.rid AND " | |
| 77 | + "vfile.pathname=%B", | |
| 78 | + &fname | |
| 79 | + ); | |
| 80 | + if( isNew ){ | |
| 81 | + blob_appendf(&line, "new"); | |
| 82 | + }else if( isDeleted ){ | |
| 83 | + blob_appendf(&line, "deleted"); | |
| 84 | + }else if( renamed ){ | |
| 85 | + blob_appendf(&line, "renamed"); | |
| 86 | + }else if( chnged ){ | |
| 87 | + blob_appendf(&line, "edited"); | |
| 88 | + }else{ | |
| 89 | + blob_appendf(&line, "unchanged"); | |
| 90 | + } | |
| 91 | + blob_appendf(&line, " "); | |
| 92 | + blob_appendf(&line, " %10.10s", blob_str(&uuid)); | |
| 93 | + blob_reset(&uuid); | |
| 94 | + }else{ | |
| 95 | + blob_appendf(&line, "unknown 0000000000"); | |
| 96 | + } | |
| 97 | + db_finalize(&q); | |
| 98 | + printf("%s\n", blob_str(&line)); | |
| 99 | + blob_reset(&fname); | |
| 100 | + blob_reset(&line); | |
| 101 | + }else if( find_option("print","p",0) ){ | |
| 102 | + Blob record; | |
| 103 | + Blob fname; | |
| 104 | + const char *zRevision = find_option("revision", "r", 1); | |
| 105 | + | |
| 106 | + file_tree_name(g.argv[2], &fname, 1); | |
| 107 | + if( zRevision ){ | |
| 108 | + historical_version_of_file(zRevision, blob_str(&fname), &record, 0); | |
| 109 | + }else{ | |
| 110 | + int rid = db_int(0, "SELECT rid FROM vfile WHERE pathname=%B", &fname); | |
| 111 | + if( rid==0 ){ | |
| 112 | + fossil_fatal("no history for file: %b", &fname); | |
| 113 | + } | |
| 114 | + content_get(rid, &record); | |
| 115 | + } | |
| 116 | + blob_write_to_file(&record, "-"); | |
| 117 | + blob_reset(&record); | |
| 118 | + blob_reset(&fname); | |
| 119 | + }else{ | |
| 120 | + Blob line; | |
| 121 | + Stmt q; | |
| 122 | + Blob fname; | |
| 123 | + int rid; | |
| 124 | + const char *zFilename; | |
| 125 | + const char *zLimit; | |
| 126 | + const char *zOffset; | |
| 127 | + int iLimit, iOffset, iBrief; | |
| 128 | + | |
| 129 | + if( find_option("log","l",0) ){ | |
| 130 | + /* this is the default, no-op */ | |
| 131 | + } | |
| 132 | + zLimit = find_option("limit",0,1); | |
| 133 | + iLimit = zLimit ? atoi(zLimit) : -1; | |
| 134 | + zOffset = find_option("offset",0,1); | |
| 135 | + iOffset = zOffset ? atoi(zOffset) : 0; | |
| 136 | + iBrief = (find_option("brief","b",0) == 0); | |
| 137 | + if( g.argc!=3 ){ | |
| 138 | + usage("?-l|--log? ?-b|--brief? FILENAME"); | |
| 139 | + } | |
| 140 | + file_tree_name(g.argv[2], &fname, 1); | |
| 141 | + rid = db_int(0, "SELECT rid FROM vfile WHERE pathname=%B", &fname); | |
| 142 | + if( rid==0 ){ | |
| 143 | + fossil_fatal("no history for file: %b", &fname); | |
| 144 | + } | |
| 145 | + zFilename = blob_str(&fname); | |
| 146 | + db_prepare(&q, | |
| 147 | + "SELECT b.uuid, ci.uuid, date(event.mtime,'localtime')," | |
| 148 | + " coalesce(event.ecomment, event.comment)," | |
| 149 | + " coalesce(event.euser, event.user)" | |
| 150 | + " FROM mlink, blob b, event, blob ci" | |
| 151 | + " WHERE mlink.fnid=(SELECT fnid FROM filename WHERE name=%Q)" | |
| 152 | + " AND b.rid=mlink.fid" | |
| 153 | + " AND event.objid=mlink.mid" | |
| 154 | + " AND event.objid=ci.rid" | |
| 155 | + " ORDER BY event.mtime DESC LIMIT %d OFFSET %d", | |
| 156 | + zFilename, iLimit, iOffset | |
| 157 | + ); | |
| 158 | + blob_zero(&line); | |
| 159 | + if( iBrief ){ | |
| 160 | + printf("History of %s\n", blob_str(&fname)); | |
| 161 | + } | |
| 162 | + while( db_step(&q)==SQLITE_ROW ){ | |
| 163 | + const char *zFileUuid = db_column_text(&q, 0); | |
| 164 | + const char *zCiUuid = db_column_text(&q,1); | |
| 165 | + const char *zDate = db_column_text(&q, 2); | |
| 166 | + const char *zCom = db_column_text(&q, 3); | |
| 167 | + const char *zUser = db_column_text(&q, 4); | |
| 168 | + char *zOut; | |
| 169 | + if( iBrief ){ | |
| 170 | + printf("%s ", zDate); | |
| 171 | + zOut = sqlite3_mprintf("[%.10s] %s (user: %s, artifact: [%.10s])", | |
| 172 | + zCiUuid, zCom, zUser, zFileUuid); | |
| 173 | + comment_print(zOut, 11, 79); | |
| 174 | + sqlite3_free(zOut); | |
| 175 | + }else{ | |
| 176 | + blob_reset(&line); | |
| 177 | + blob_appendf(&line, "%.10s ", zCiUuid); | |
| 178 | + blob_appendf(&line, "%.10s ", zDate); | |
| 179 | + blob_appendf(&line, "%8.8s ", zUser); | |
| 180 | + blob_appendf(&line,"%-40.40s\n", zCom ); | |
| 181 | + comment_print(blob_str(&line), 0, 79); | |
| 182 | + } | |
| 183 | + } | |
| 184 | + db_finalize(&q); | |
| 185 | + blob_reset(&fname); | |
| 186 | + } | |
| 94 | 187 | } |
| 95 | 188 | |
| 96 | 189 | |
| 97 | 190 | /* |
| 98 | 191 | ** WEBPAGE: finfo |
| 99 | 192 |
| --- src/finfo.c | |
| +++ src/finfo.c | |
| @@ -21,78 +21,171 @@ | |
| 21 | #include "finfo.h" |
| 22 | |
| 23 | /* |
| 24 | ** COMMAND: finfo |
| 25 | ** |
| 26 | ** Usage: %fossil finfo FILENAME |
| 27 | ** |
| 28 | ** Print the change history for a single file. |
| 29 | ** |
| 30 | ** The "--limit N" and "--offset P" options limit the output to the first |
| 31 | ** N changes after skipping P changes. |
| 32 | ** |
| 33 | ** The history of a file can also be viewed in the gui: |
| 34 | ** * Go to the <a href="dir">file browser</a> and drill down to the file |
| 35 | */ |
| 36 | void finfo_cmd(void){ |
| 37 | Stmt q; |
| 38 | int vid; |
| 39 | Blob dest; |
| 40 | const char *zFilename; |
| 41 | const char *zLimit; |
| 42 | const char *zOffset; |
| 43 | int iLimit, iOffset; |
| 44 | |
| 45 | db_must_be_within_tree(); |
| 46 | vid = db_lget_int("checkout", 0); |
| 47 | if( vid==0 ){ |
| 48 | fossil_panic("no checkout to finfo files in"); |
| 49 | } |
| 50 | zLimit = find_option("limit",0,1); |
| 51 | iLimit = zLimit ? atoi(zLimit) : -1; |
| 52 | zOffset = find_option("offset",0,1); |
| 53 | iOffset = zOffset ? atoi(zOffset) : 0; |
| 54 | if (g.argc<3) { |
| 55 | usage("FILENAME"); |
| 56 | } |
| 57 | file_tree_name(g.argv[2], &dest, 1); |
| 58 | zFilename = blob_str(&dest); |
| 59 | db_prepare(&q, |
| 60 | "SELECT " |
| 61 | " (SELECT uuid FROM blob WHERE rid=mlink.fid)," /* New file */ |
| 62 | " (SELECT uuid FROM blob WHERE rid=mlink.mid)," /* The check-in */ |
| 63 | " date(event.mtime,'localtime')," |
| 64 | " coalesce(event.ecomment, event.comment)," |
| 65 | " coalesce(event.euser, event.user)" |
| 66 | " FROM mlink, event" |
| 67 | " WHERE mlink.fnid=(SELECT fnid FROM filename WHERE name=%Q)" |
| 68 | " AND event.objid=mlink.mid" |
| 69 | " ORDER BY event.mtime DESC LIMIT %d OFFSET %d /*sort*/", |
| 70 | zFilename, iLimit, iOffset |
| 71 | ); |
| 72 | |
| 73 | printf("History of %s\n", zFilename); |
| 74 | while( db_step(&q)==SQLITE_ROW ){ |
| 75 | const char *zFileUuid = db_column_text(&q, 0); |
| 76 | const char *zCiUuid = db_column_text(&q, 1); |
| 77 | const char *zDate = db_column_text(&q, 2); |
| 78 | const char *zCom = db_column_text(&q, 3); |
| 79 | const char *zUser = db_column_text(&q, 4); |
| 80 | char *zOut; |
| 81 | printf("%s ", zDate); |
| 82 | if( zFileUuid==0 ){ |
| 83 | zOut = sqlite3_mprintf("[%.10s] DELETED %s (user: %s)", |
| 84 | zCiUuid, zCom, zUser); |
| 85 | }else{ |
| 86 | zOut = sqlite3_mprintf("[%.10s] %s (user: %s, artifact: [%.10s])", |
| 87 | zCiUuid, zCom, zUser, zFileUuid); |
| 88 | } |
| 89 | comment_print(zOut, 11, 79); |
| 90 | sqlite3_free(zOut); |
| 91 | } |
| 92 | db_finalize(&q); |
| 93 | blob_reset(&dest); |
| 94 | } |
| 95 | |
| 96 | |
| 97 | /* |
| 98 | ** WEBPAGE: finfo |
| 99 |
| --- src/finfo.c | |
| +++ src/finfo.c | |
| @@ -21,78 +21,171 @@ | |
| 21 | #include "finfo.h" |
| 22 | |
| 23 | /* |
| 24 | ** COMMAND: finfo |
| 25 | ** |
| 26 | ** Usage: %fossil finfo {?-l|--log? / -s|--status / --p|--print} FILENAME |
| 27 | ** |
| 28 | ** Print the complete change history for a single file going backwards |
| 29 | ** in time. The default is -l. |
| 30 | ** |
| 31 | ** For the -l|--log option: If "-b|--brief" is specified one line per revision |
| 32 | ** is printed, otherwise the full comment is printed. The "--limit N" |
| 33 | ** and "--offset P" options limits the output to the first N changes |
| 34 | ** after skipping P changes. |
| 35 | ** |
| 36 | ** In the -s form prints the status as <status> <revision>. This is |
| 37 | ** a quick status and does not check for up-to-date-ness of the file. |
| 38 | ** |
| 39 | ** The -p form, there's an optional flag "-r|--revision REVISION". The |
| 40 | ** specified version (or the latest checked out version) is printed to |
| 41 | ** stdout. |
| 42 | ** |
| 43 | ** The history of a file can also be viewed in the gui: |
| 44 | ** * Go to the <a href="dir">file browser</a> and drill down to the file |
| 45 | */ |
| 46 | void finfo_cmd(void){ |
| 47 | int vid; |
| 48 | |
| 49 | db_must_be_within_tree(); |
| 50 | vid = db_lget_int("checkout", 0); |
| 51 | if( vid==0 ){ |
| 52 | fossil_panic("no checkout to finfo files in"); |
| 53 | } |
| 54 | vfile_check_signature(vid, 1); |
| 55 | if (find_option("status","s",0)) { |
| 56 | Stmt q; |
| 57 | Blob line; |
| 58 | Blob fname; |
| 59 | |
| 60 | if( g.argc!=3 ) usage("-s|--status FILENAME"); |
| 61 | file_tree_name(g.argv[2], &fname, 1); |
| 62 | db_prepare(&q, |
| 63 | "SELECT pathname, deleted, rid, chnged, coalesce(origname!=pathname,0)" |
| 64 | " FROM vfile WHERE vfile.pathname=%B", &fname); |
| 65 | blob_zero(&line); |
| 66 | if ( db_step(&q)==SQLITE_ROW ) { |
| 67 | Blob uuid; |
| 68 | int isDeleted = db_column_int(&q, 1); |
| 69 | int isNew = db_column_int(&q,2) == 0; |
| 70 | int chnged = db_column_int(&q,3); |
| 71 | int renamed = db_column_int(&q,4); |
| 72 | |
| 73 | blob_zero(&uuid); |
| 74 | db_blob(&uuid, |
| 75 | "SELECT uuid FROM blob, mlink, vfile WHERE " |
| 76 | "blob.rid = mlink.mid AND mlink.fid = vfile.rid AND " |
| 77 | "vfile.pathname=%B", |
| 78 | &fname |
| 79 | ); |
| 80 | if( isNew ){ |
| 81 | blob_appendf(&line, "new"); |
| 82 | }else if( isDeleted ){ |
| 83 | blob_appendf(&line, "deleted"); |
| 84 | }else if( renamed ){ |
| 85 | blob_appendf(&line, "renamed"); |
| 86 | }else if( chnged ){ |
| 87 | blob_appendf(&line, "edited"); |
| 88 | }else{ |
| 89 | blob_appendf(&line, "unchanged"); |
| 90 | } |
| 91 | blob_appendf(&line, " "); |
| 92 | blob_appendf(&line, " %10.10s", blob_str(&uuid)); |
| 93 | blob_reset(&uuid); |
| 94 | }else{ |
| 95 | blob_appendf(&line, "unknown 0000000000"); |
| 96 | } |
| 97 | db_finalize(&q); |
| 98 | printf("%s\n", blob_str(&line)); |
| 99 | blob_reset(&fname); |
| 100 | blob_reset(&line); |
| 101 | }else if( find_option("print","p",0) ){ |
| 102 | Blob record; |
| 103 | Blob fname; |
| 104 | const char *zRevision = find_option("revision", "r", 1); |
| 105 | |
| 106 | file_tree_name(g.argv[2], &fname, 1); |
| 107 | if( zRevision ){ |
| 108 | historical_version_of_file(zRevision, blob_str(&fname), &record, 0); |
| 109 | }else{ |
| 110 | int rid = db_int(0, "SELECT rid FROM vfile WHERE pathname=%B", &fname); |
| 111 | if( rid==0 ){ |
| 112 | fossil_fatal("no history for file: %b", &fname); |
| 113 | } |
| 114 | content_get(rid, &record); |
| 115 | } |
| 116 | blob_write_to_file(&record, "-"); |
| 117 | blob_reset(&record); |
| 118 | blob_reset(&fname); |
| 119 | }else{ |
| 120 | Blob line; |
| 121 | Stmt q; |
| 122 | Blob fname; |
| 123 | int rid; |
| 124 | const char *zFilename; |
| 125 | const char *zLimit; |
| 126 | const char *zOffset; |
| 127 | int iLimit, iOffset, iBrief; |
| 128 | |
| 129 | if( find_option("log","l",0) ){ |
| 130 | /* this is the default, no-op */ |
| 131 | } |
| 132 | zLimit = find_option("limit",0,1); |
| 133 | iLimit = zLimit ? atoi(zLimit) : -1; |
| 134 | zOffset = find_option("offset",0,1); |
| 135 | iOffset = zOffset ? atoi(zOffset) : 0; |
| 136 | iBrief = (find_option("brief","b",0) == 0); |
| 137 | if( g.argc!=3 ){ |
| 138 | usage("?-l|--log? ?-b|--brief? FILENAME"); |
| 139 | } |
| 140 | file_tree_name(g.argv[2], &fname, 1); |
| 141 | rid = db_int(0, "SELECT rid FROM vfile WHERE pathname=%B", &fname); |
| 142 | if( rid==0 ){ |
| 143 | fossil_fatal("no history for file: %b", &fname); |
| 144 | } |
| 145 | zFilename = blob_str(&fname); |
| 146 | db_prepare(&q, |
| 147 | "SELECT b.uuid, ci.uuid, date(event.mtime,'localtime')," |
| 148 | " coalesce(event.ecomment, event.comment)," |
| 149 | " coalesce(event.euser, event.user)" |
| 150 | " FROM mlink, blob b, event, blob ci" |
| 151 | " WHERE mlink.fnid=(SELECT fnid FROM filename WHERE name=%Q)" |
| 152 | " AND b.rid=mlink.fid" |
| 153 | " AND event.objid=mlink.mid" |
| 154 | " AND event.objid=ci.rid" |
| 155 | " ORDER BY event.mtime DESC LIMIT %d OFFSET %d", |
| 156 | zFilename, iLimit, iOffset |
| 157 | ); |
| 158 | blob_zero(&line); |
| 159 | if( iBrief ){ |
| 160 | printf("History of %s\n", blob_str(&fname)); |
| 161 | } |
| 162 | while( db_step(&q)==SQLITE_ROW ){ |
| 163 | const char *zFileUuid = db_column_text(&q, 0); |
| 164 | const char *zCiUuid = db_column_text(&q,1); |
| 165 | const char *zDate = db_column_text(&q, 2); |
| 166 | const char *zCom = db_column_text(&q, 3); |
| 167 | const char *zUser = db_column_text(&q, 4); |
| 168 | char *zOut; |
| 169 | if( iBrief ){ |
| 170 | printf("%s ", zDate); |
| 171 | zOut = sqlite3_mprintf("[%.10s] %s (user: %s, artifact: [%.10s])", |
| 172 | zCiUuid, zCom, zUser, zFileUuid); |
| 173 | comment_print(zOut, 11, 79); |
| 174 | sqlite3_free(zOut); |
| 175 | }else{ |
| 176 | blob_reset(&line); |
| 177 | blob_appendf(&line, "%.10s ", zCiUuid); |
| 178 | blob_appendf(&line, "%.10s ", zDate); |
| 179 | blob_appendf(&line, "%8.8s ", zUser); |
| 180 | blob_appendf(&line,"%-40.40s\n", zCom ); |
| 181 | comment_print(blob_str(&line), 0, 79); |
| 182 | } |
| 183 | } |
| 184 | db_finalize(&q); |
| 185 | blob_reset(&fname); |
| 186 | } |
| 187 | } |
| 188 | |
| 189 | |
| 190 | /* |
| 191 | ** WEBPAGE: finfo |
| 192 |
+4
-4
| --- src/merge.c | ||
| +++ src/merge.c | ||
| @@ -73,11 +73,11 @@ | ||
| 73 | 73 | } |
| 74 | 74 | mid = name_to_rid(g.argv[2]); |
| 75 | 75 | if( mid==0 ){ |
| 76 | 76 | fossil_fatal("not a version: %s", g.argv[2]); |
| 77 | 77 | } |
| 78 | - if( mid>1 && !db_exists("SELECT 1 FROM plink WHERE cid=%d", mid) ){ | |
| 78 | + if( !is_a_version(mid) ){ | |
| 79 | 79 | fossil_fatal("not a version: %s", g.argv[2]); |
| 80 | 80 | } |
| 81 | 81 | if( pickFlag || backoutFlag ){ |
| 82 | 82 | pid = db_int(0, "SELECT pid FROM plink WHERE cid=%d AND isprim", mid); |
| 83 | 83 | if( pid<=0 ){ |
| @@ -96,16 +96,16 @@ | ||
| 96 | 96 | pivot_set_secondary(db_column_int(&q,0)); |
| 97 | 97 | } |
| 98 | 98 | db_finalize(&q); |
| 99 | 99 | pid = pivot_find(); |
| 100 | 100 | if( pid<=0 ){ |
| 101 | - fossil_fatal("cannot find a common ancestor between the current" | |
| 101 | + fossil_fatal("cannot find a common ancestor between the current " | |
| 102 | 102 | "checkout and %s", g.argv[2]); |
| 103 | 103 | } |
| 104 | 104 | } |
| 105 | - if( pid>1 && !db_exists("SELECT 1 FROM plink WHERE cid=%d", pid) ){ | |
| 106 | - fossil_fatal("not a version: record #%d", mid); | |
| 105 | + if( !is_a_version(pid) ){ | |
| 106 | + fossil_fatal("not a version: record #%d", pid); | |
| 107 | 107 | } |
| 108 | 108 | vfile_check_signature(vid, 1); |
| 109 | 109 | db_begin_transaction(); |
| 110 | 110 | undo_begin(); |
| 111 | 111 | load_vfile_from_rid(mid); |
| 112 | 112 |
| --- src/merge.c | |
| +++ src/merge.c | |
| @@ -73,11 +73,11 @@ | |
| 73 | } |
| 74 | mid = name_to_rid(g.argv[2]); |
| 75 | if( mid==0 ){ |
| 76 | fossil_fatal("not a version: %s", g.argv[2]); |
| 77 | } |
| 78 | if( mid>1 && !db_exists("SELECT 1 FROM plink WHERE cid=%d", mid) ){ |
| 79 | fossil_fatal("not a version: %s", g.argv[2]); |
| 80 | } |
| 81 | if( pickFlag || backoutFlag ){ |
| 82 | pid = db_int(0, "SELECT pid FROM plink WHERE cid=%d AND isprim", mid); |
| 83 | if( pid<=0 ){ |
| @@ -96,16 +96,16 @@ | |
| 96 | pivot_set_secondary(db_column_int(&q,0)); |
| 97 | } |
| 98 | db_finalize(&q); |
| 99 | pid = pivot_find(); |
| 100 | if( pid<=0 ){ |
| 101 | fossil_fatal("cannot find a common ancestor between the current" |
| 102 | "checkout and %s", g.argv[2]); |
| 103 | } |
| 104 | } |
| 105 | if( pid>1 && !db_exists("SELECT 1 FROM plink WHERE cid=%d", pid) ){ |
| 106 | fossil_fatal("not a version: record #%d", mid); |
| 107 | } |
| 108 | vfile_check_signature(vid, 1); |
| 109 | db_begin_transaction(); |
| 110 | undo_begin(); |
| 111 | load_vfile_from_rid(mid); |
| 112 |
| --- src/merge.c | |
| +++ src/merge.c | |
| @@ -73,11 +73,11 @@ | |
| 73 | } |
| 74 | mid = name_to_rid(g.argv[2]); |
| 75 | if( mid==0 ){ |
| 76 | fossil_fatal("not a version: %s", g.argv[2]); |
| 77 | } |
| 78 | if( !is_a_version(mid) ){ |
| 79 | fossil_fatal("not a version: %s", g.argv[2]); |
| 80 | } |
| 81 | if( pickFlag || backoutFlag ){ |
| 82 | pid = db_int(0, "SELECT pid FROM plink WHERE cid=%d AND isprim", mid); |
| 83 | if( pid<=0 ){ |
| @@ -96,16 +96,16 @@ | |
| 96 | pivot_set_secondary(db_column_int(&q,0)); |
| 97 | } |
| 98 | db_finalize(&q); |
| 99 | pid = pivot_find(); |
| 100 | if( pid<=0 ){ |
| 101 | fossil_fatal("cannot find a common ancestor between the current " |
| 102 | "checkout and %s", g.argv[2]); |
| 103 | } |
| 104 | } |
| 105 | if( !is_a_version(pid) ){ |
| 106 | fossil_fatal("not a version: record #%d", pid); |
| 107 | } |
| 108 | vfile_check_signature(vid, 1); |
| 109 | db_begin_transaction(); |
| 110 | undo_begin(); |
| 111 | load_vfile_from_rid(mid); |
| 112 |
+4
-4
| --- src/merge.c | ||
| +++ src/merge.c | ||
| @@ -73,11 +73,11 @@ | ||
| 73 | 73 | } |
| 74 | 74 | mid = name_to_rid(g.argv[2]); |
| 75 | 75 | if( mid==0 ){ |
| 76 | 76 | fossil_fatal("not a version: %s", g.argv[2]); |
| 77 | 77 | } |
| 78 | - if( mid>1 && !db_exists("SELECT 1 FROM plink WHERE cid=%d", mid) ){ | |
| 78 | + if( !is_a_version(mid) ){ | |
| 79 | 79 | fossil_fatal("not a version: %s", g.argv[2]); |
| 80 | 80 | } |
| 81 | 81 | if( pickFlag || backoutFlag ){ |
| 82 | 82 | pid = db_int(0, "SELECT pid FROM plink WHERE cid=%d AND isprim", mid); |
| 83 | 83 | if( pid<=0 ){ |
| @@ -96,16 +96,16 @@ | ||
| 96 | 96 | pivot_set_secondary(db_column_int(&q,0)); |
| 97 | 97 | } |
| 98 | 98 | db_finalize(&q); |
| 99 | 99 | pid = pivot_find(); |
| 100 | 100 | if( pid<=0 ){ |
| 101 | - fossil_fatal("cannot find a common ancestor between the current" | |
| 101 | + fossil_fatal("cannot find a common ancestor between the current " | |
| 102 | 102 | "checkout and %s", g.argv[2]); |
| 103 | 103 | } |
| 104 | 104 | } |
| 105 | - if( pid>1 && !db_exists("SELECT 1 FROM plink WHERE cid=%d", pid) ){ | |
| 106 | - fossil_fatal("not a version: record #%d", mid); | |
| 105 | + if( !is_a_version(pid) ){ | |
| 106 | + fossil_fatal("not a version: record #%d", pid); | |
| 107 | 107 | } |
| 108 | 108 | vfile_check_signature(vid, 1); |
| 109 | 109 | db_begin_transaction(); |
| 110 | 110 | undo_begin(); |
| 111 | 111 | load_vfile_from_rid(mid); |
| 112 | 112 |
| --- src/merge.c | |
| +++ src/merge.c | |
| @@ -73,11 +73,11 @@ | |
| 73 | } |
| 74 | mid = name_to_rid(g.argv[2]); |
| 75 | if( mid==0 ){ |
| 76 | fossil_fatal("not a version: %s", g.argv[2]); |
| 77 | } |
| 78 | if( mid>1 && !db_exists("SELECT 1 FROM plink WHERE cid=%d", mid) ){ |
| 79 | fossil_fatal("not a version: %s", g.argv[2]); |
| 80 | } |
| 81 | if( pickFlag || backoutFlag ){ |
| 82 | pid = db_int(0, "SELECT pid FROM plink WHERE cid=%d AND isprim", mid); |
| 83 | if( pid<=0 ){ |
| @@ -96,16 +96,16 @@ | |
| 96 | pivot_set_secondary(db_column_int(&q,0)); |
| 97 | } |
| 98 | db_finalize(&q); |
| 99 | pid = pivot_find(); |
| 100 | if( pid<=0 ){ |
| 101 | fossil_fatal("cannot find a common ancestor between the current" |
| 102 | "checkout and %s", g.argv[2]); |
| 103 | } |
| 104 | } |
| 105 | if( pid>1 && !db_exists("SELECT 1 FROM plink WHERE cid=%d", pid) ){ |
| 106 | fossil_fatal("not a version: record #%d", mid); |
| 107 | } |
| 108 | vfile_check_signature(vid, 1); |
| 109 | db_begin_transaction(); |
| 110 | undo_begin(); |
| 111 | load_vfile_from_rid(mid); |
| 112 |
| --- src/merge.c | |
| +++ src/merge.c | |
| @@ -73,11 +73,11 @@ | |
| 73 | } |
| 74 | mid = name_to_rid(g.argv[2]); |
| 75 | if( mid==0 ){ |
| 76 | fossil_fatal("not a version: %s", g.argv[2]); |
| 77 | } |
| 78 | if( !is_a_version(mid) ){ |
| 79 | fossil_fatal("not a version: %s", g.argv[2]); |
| 80 | } |
| 81 | if( pickFlag || backoutFlag ){ |
| 82 | pid = db_int(0, "SELECT pid FROM plink WHERE cid=%d AND isprim", mid); |
| 83 | if( pid<=0 ){ |
| @@ -96,16 +96,16 @@ | |
| 96 | pivot_set_secondary(db_column_int(&q,0)); |
| 97 | } |
| 98 | db_finalize(&q); |
| 99 | pid = pivot_find(); |
| 100 | if( pid<=0 ){ |
| 101 | fossil_fatal("cannot find a common ancestor between the current " |
| 102 | "checkout and %s", g.argv[2]); |
| 103 | } |
| 104 | } |
| 105 | if( !is_a_version(pid) ){ |
| 106 | fossil_fatal("not a version: record #%d", pid); |
| 107 | } |
| 108 | vfile_check_signature(vid, 1); |
| 109 | db_begin_transaction(); |
| 110 | undo_begin(); |
| 111 | load_vfile_from_rid(mid); |
| 112 |
+2
-2
| --- src/pivot.c | ||
| +++ src/pivot.c | ||
| @@ -50,11 +50,11 @@ | ||
| 50 | 50 | ); |
| 51 | 51 | |
| 52 | 52 | /* Insert the primary record */ |
| 53 | 53 | db_multi_exec( |
| 54 | 54 | "INSERT INTO aqueue(rid, mtime, pending, src)" |
| 55 | - " SELECT %d, mtime, 1, 1 FROM plink WHERE cid=%d LIMIT 1", | |
| 55 | + " SELECT %d, mtime, 1, 1 FROM event WHERE objid=%d AND type='ci' LIMIT 1", | |
| 56 | 56 | rid, rid |
| 57 | 57 | ); |
| 58 | 58 | } |
| 59 | 59 | |
| 60 | 60 | /* |
| @@ -64,11 +64,11 @@ | ||
| 64 | 64 | */ |
| 65 | 65 | void pivot_set_secondary(int rid){ |
| 66 | 66 | /* Insert the primary record */ |
| 67 | 67 | db_multi_exec( |
| 68 | 68 | "INSERT OR IGNORE INTO aqueue(rid, mtime, pending, src)" |
| 69 | - " SELECT %d, mtime, 1, 0 FROM plink WHERE cid=%d", | |
| 69 | + " SELECT %d, mtime, 1, 0 FROM event WHERE objid=%d AND type='ci'", | |
| 70 | 70 | rid, rid |
| 71 | 71 | ); |
| 72 | 72 | } |
| 73 | 73 | |
| 74 | 74 | /* |
| 75 | 75 |
| --- src/pivot.c | |
| +++ src/pivot.c | |
| @@ -50,11 +50,11 @@ | |
| 50 | ); |
| 51 | |
| 52 | /* Insert the primary record */ |
| 53 | db_multi_exec( |
| 54 | "INSERT INTO aqueue(rid, mtime, pending, src)" |
| 55 | " SELECT %d, mtime, 1, 1 FROM plink WHERE cid=%d LIMIT 1", |
| 56 | rid, rid |
| 57 | ); |
| 58 | } |
| 59 | |
| 60 | /* |
| @@ -64,11 +64,11 @@ | |
| 64 | */ |
| 65 | void pivot_set_secondary(int rid){ |
| 66 | /* Insert the primary record */ |
| 67 | db_multi_exec( |
| 68 | "INSERT OR IGNORE INTO aqueue(rid, mtime, pending, src)" |
| 69 | " SELECT %d, mtime, 1, 0 FROM plink WHERE cid=%d", |
| 70 | rid, rid |
| 71 | ); |
| 72 | } |
| 73 | |
| 74 | /* |
| 75 |
| --- src/pivot.c | |
| +++ src/pivot.c | |
| @@ -50,11 +50,11 @@ | |
| 50 | ); |
| 51 | |
| 52 | /* Insert the primary record */ |
| 53 | db_multi_exec( |
| 54 | "INSERT INTO aqueue(rid, mtime, pending, src)" |
| 55 | " SELECT %d, mtime, 1, 1 FROM event WHERE objid=%d AND type='ci' LIMIT 1", |
| 56 | rid, rid |
| 57 | ); |
| 58 | } |
| 59 | |
| 60 | /* |
| @@ -64,11 +64,11 @@ | |
| 64 | */ |
| 65 | void pivot_set_secondary(int rid){ |
| 66 | /* Insert the primary record */ |
| 67 | db_multi_exec( |
| 68 | "INSERT OR IGNORE INTO aqueue(rid, mtime, pending, src)" |
| 69 | " SELECT %d, mtime, 1, 0 FROM event WHERE objid=%d AND type='ci'", |
| 70 | rid, rid |
| 71 | ); |
| 72 | } |
| 73 | |
| 74 | /* |
| 75 |
+1
-1
| --- src/setup.c | ||
| +++ src/setup.c | ||
| @@ -1087,11 +1087,11 @@ | ||
| 1087 | 1087 | |
| 1088 | 1088 | /* |
| 1089 | 1089 | ** WEBPAGE: setup_logo |
| 1090 | 1090 | */ |
| 1091 | 1091 | void setup_logo(void){ |
| 1092 | - const char *zMime = "image/gif"; | |
| 1092 | + const char *zMime = db_get("logo-mimetype","image/gif"); | |
| 1093 | 1093 | const char *aImg = P("im"); |
| 1094 | 1094 | int szImg = atoi(PD("im:bytes","0")); |
| 1095 | 1095 | if( szImg>0 ){ |
| 1096 | 1096 | zMime = PD("im:mimetype","image/gif"); |
| 1097 | 1097 | } |
| 1098 | 1098 |
| --- src/setup.c | |
| +++ src/setup.c | |
| @@ -1087,11 +1087,11 @@ | |
| 1087 | |
| 1088 | /* |
| 1089 | ** WEBPAGE: setup_logo |
| 1090 | */ |
| 1091 | void setup_logo(void){ |
| 1092 | const char *zMime = "image/gif"; |
| 1093 | const char *aImg = P("im"); |
| 1094 | int szImg = atoi(PD("im:bytes","0")); |
| 1095 | if( szImg>0 ){ |
| 1096 | zMime = PD("im:mimetype","image/gif"); |
| 1097 | } |
| 1098 |
| --- src/setup.c | |
| +++ src/setup.c | |
| @@ -1087,11 +1087,11 @@ | |
| 1087 | |
| 1088 | /* |
| 1089 | ** WEBPAGE: setup_logo |
| 1090 | */ |
| 1091 | void setup_logo(void){ |
| 1092 | const char *zMime = db_get("logo-mimetype","image/gif"); |
| 1093 | const char *aImg = P("im"); |
| 1094 | int szImg = atoi(PD("im:bytes","0")); |
| 1095 | if( szImg>0 ){ |
| 1096 | zMime = PD("im:mimetype","image/gif"); |
| 1097 | } |
| 1098 |
+1
-1
| --- src/setup.c | ||
| +++ src/setup.c | ||
| @@ -1087,11 +1087,11 @@ | ||
| 1087 | 1087 | |
| 1088 | 1088 | /* |
| 1089 | 1089 | ** WEBPAGE: setup_logo |
| 1090 | 1090 | */ |
| 1091 | 1091 | void setup_logo(void){ |
| 1092 | - const char *zMime = "image/gif"; | |
| 1092 | + const char *zMime = db_get("logo-mimetype","image/gif"); | |
| 1093 | 1093 | const char *aImg = P("im"); |
| 1094 | 1094 | int szImg = atoi(PD("im:bytes","0")); |
| 1095 | 1095 | if( szImg>0 ){ |
| 1096 | 1096 | zMime = PD("im:mimetype","image/gif"); |
| 1097 | 1097 | } |
| 1098 | 1098 |
| --- src/setup.c | |
| +++ src/setup.c | |
| @@ -1087,11 +1087,11 @@ | |
| 1087 | |
| 1088 | /* |
| 1089 | ** WEBPAGE: setup_logo |
| 1090 | */ |
| 1091 | void setup_logo(void){ |
| 1092 | const char *zMime = "image/gif"; |
| 1093 | const char *aImg = P("im"); |
| 1094 | int szImg = atoi(PD("im:bytes","0")); |
| 1095 | if( szImg>0 ){ |
| 1096 | zMime = PD("im:mimetype","image/gif"); |
| 1097 | } |
| 1098 |
| --- src/setup.c | |
| +++ src/setup.c | |
| @@ -1087,11 +1087,11 @@ | |
| 1087 | |
| 1088 | /* |
| 1089 | ** WEBPAGE: setup_logo |
| 1090 | */ |
| 1091 | void setup_logo(void){ |
| 1092 | const char *zMime = db_get("logo-mimetype","image/gif"); |
| 1093 | const char *aImg = P("im"); |
| 1094 | int szImg = atoi(PD("im:bytes","0")); |
| 1095 | if( szImg>0 ){ |
| 1096 | zMime = PD("im:mimetype","image/gif"); |
| 1097 | } |
| 1098 |
+1
-1
| --- src/style.c | ||
| +++ src/style.c | ||
| @@ -89,11 +89,11 @@ | ||
| 89 | 89 | va_end(ap); |
| 90 | 90 | |
| 91 | 91 | cgi_destination(CGI_HEADER); |
| 92 | 92 | cgi_printf("%s", |
| 93 | 93 | "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"" |
| 94 | - " \"http://www.x3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">"); | |
| 94 | + " \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">"); | |
| 95 | 95 | |
| 96 | 96 | if( g.thTrace ) Th_Trace("BEGIN_HEADER<br />\n", -1); |
| 97 | 97 | |
| 98 | 98 | /* Generate the header up through the main menu */ |
| 99 | 99 | Th_Store("project_name", db_get("project-name","Unnamed Fossil Project")); |
| 100 | 100 |
| --- src/style.c | |
| +++ src/style.c | |
| @@ -89,11 +89,11 @@ | |
| 89 | va_end(ap); |
| 90 | |
| 91 | cgi_destination(CGI_HEADER); |
| 92 | cgi_printf("%s", |
| 93 | "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"" |
| 94 | " \"http://www.x3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">"); |
| 95 | |
| 96 | if( g.thTrace ) Th_Trace("BEGIN_HEADER<br />\n", -1); |
| 97 | |
| 98 | /* Generate the header up through the main menu */ |
| 99 | Th_Store("project_name", db_get("project-name","Unnamed Fossil Project")); |
| 100 |
| --- src/style.c | |
| +++ src/style.c | |
| @@ -89,11 +89,11 @@ | |
| 89 | va_end(ap); |
| 90 | |
| 91 | cgi_destination(CGI_HEADER); |
| 92 | cgi_printf("%s", |
| 93 | "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"" |
| 94 | " \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">"); |
| 95 | |
| 96 | if( g.thTrace ) Th_Trace("BEGIN_HEADER<br />\n", -1); |
| 97 | |
| 98 | /* Generate the header up through the main menu */ |
| 99 | Th_Store("project_name", db_get("project-name","Unnamed Fossil Project")); |
| 100 |
+1
-1
| --- src/style.c | ||
| +++ src/style.c | ||
| @@ -89,11 +89,11 @@ | ||
| 89 | 89 | va_end(ap); |
| 90 | 90 | |
| 91 | 91 | cgi_destination(CGI_HEADER); |
| 92 | 92 | cgi_printf("%s", |
| 93 | 93 | "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"" |
| 94 | - " \"http://www.x3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">"); | |
| 94 | + " \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">"); | |
| 95 | 95 | |
| 96 | 96 | if( g.thTrace ) Th_Trace("BEGIN_HEADER<br />\n", -1); |
| 97 | 97 | |
| 98 | 98 | /* Generate the header up through the main menu */ |
| 99 | 99 | Th_Store("project_name", db_get("project-name","Unnamed Fossil Project")); |
| 100 | 100 |
| --- src/style.c | |
| +++ src/style.c | |
| @@ -89,11 +89,11 @@ | |
| 89 | va_end(ap); |
| 90 | |
| 91 | cgi_destination(CGI_HEADER); |
| 92 | cgi_printf("%s", |
| 93 | "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"" |
| 94 | " \"http://www.x3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">"); |
| 95 | |
| 96 | if( g.thTrace ) Th_Trace("BEGIN_HEADER<br />\n", -1); |
| 97 | |
| 98 | /* Generate the header up through the main menu */ |
| 99 | Th_Store("project_name", db_get("project-name","Unnamed Fossil Project")); |
| 100 |
| --- src/style.c | |
| +++ src/style.c | |
| @@ -89,11 +89,11 @@ | |
| 89 | va_end(ap); |
| 90 | |
| 91 | cgi_destination(CGI_HEADER); |
| 92 | cgi_printf("%s", |
| 93 | "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"" |
| 94 | " \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">"); |
| 95 | |
| 96 | if( g.thTrace ) Th_Trace("BEGIN_HEADER<br />\n", -1); |
| 97 | |
| 98 | /* Generate the header up through the main menu */ |
| 99 | Th_Store("project_name", db_get("project-name","Unnamed Fossil Project")); |
| 100 |
+25
-9
| --- src/update.c | ||
| +++ src/update.c | ||
| @@ -43,11 +43,13 @@ | ||
| 43 | 43 | ** leaf. VERSION can also be "current" to select the leaf of the current |
| 44 | 44 | ** version or "latest" to select the most recent check-in. |
| 45 | 45 | ** |
| 46 | 46 | ** If one or more FILES are listed after the VERSION then only the |
| 47 | 47 | ** named files are candidates to be updated. If FILES is omitted, all |
| 48 | -** files in the current checkout are subject to be updated. | |
| 48 | +** files in the current checkout are subject to be updated. Using | |
| 49 | +** a directory name for one of the FILES arguments is the same as | |
| 50 | +** using every subdirectory and file beneath that directory. | |
| 49 | 51 | ** |
| 50 | 52 | ** The -n or --nochange option causes this command to do a "dry run". It |
| 51 | 53 | ** prints out what would have happened but does not actually make any |
| 52 | 54 | ** changes to the current checkout or the repository. |
| 53 | 55 | ** |
| @@ -111,11 +113,11 @@ | ||
| 111 | 113 | tid = db_int(0, "SELECT rid FROM leaves, event" |
| 112 | 114 | " WHERE event.objid=leaves.rid" |
| 113 | 115 | " ORDER BY event.mtime DESC"); |
| 114 | 116 | } |
| 115 | 117 | |
| 116 | - if( tid==vid ) return; /* Nothing to update */ | |
| 118 | + if( !verboseFlag && (tid==vid)) return; /* Nothing to update */ | |
| 117 | 119 | db_begin_transaction(); |
| 118 | 120 | vfile_check_signature(vid, 1); |
| 119 | 121 | if( !nochangeFlag ) undo_begin(); |
| 120 | 122 | load_vfile_from_rid(tid); |
| 121 | 123 | |
| @@ -166,27 +168,37 @@ | ||
| 166 | 168 | ); |
| 167 | 169 | } |
| 168 | 170 | db_finalize(&q); |
| 169 | 171 | |
| 170 | 172 | /* If FILES appear on the command-line, remove from the "fv" table |
| 171 | - ** every entry that is not named on the command-line. | |
| 173 | + ** every entry that is not named on the command-line or which is not | |
| 174 | + ** in a directory named on the command-line. | |
| 172 | 175 | */ |
| 173 | 176 | if( g.argc>=4 ){ |
| 174 | 177 | Blob sql; /* SQL statement to purge unwanted entries */ |
| 175 | - char *zSep = "("; /* Separator in the list of filenames */ | |
| 176 | 178 | Blob treename; /* Normalized filename */ |
| 177 | 179 | int i; /* Loop counter */ |
| 180 | + const char *zSep; /* Term separator */ | |
| 178 | 181 | |
| 179 | 182 | blob_zero(&sql); |
| 180 | - blob_append(&sql, "DELETE FROM fv WHERE fn NOT IN ", -1); | |
| 183 | + blob_append(&sql, "DELETE FROM fv WHERE ", -1); | |
| 184 | + zSep = ""; | |
| 181 | 185 | for(i=3; i<g.argc; i++){ |
| 182 | 186 | file_tree_name(g.argv[i], &treename, 1); |
| 183 | - blob_appendf(&sql, "%s'%q'", zSep, blob_str(&treename)); | |
| 187 | + if( file_isdir(g.argv[i])==1 ){ | |
| 188 | + if( blob_size(&treename)>0 ){ | |
| 189 | + blob_appendf(&sql, "%sfn NOT GLOB '%b/*' ", zSep, &treename); | |
| 190 | + }else{ | |
| 191 | + blob_reset(&sql); | |
| 192 | + break; | |
| 193 | + } | |
| 194 | + }else{ | |
| 195 | + blob_appendf(&sql, "%sfn<>%B ", zSep, &treename); | |
| 196 | + } | |
| 197 | + zSep = "AND "; | |
| 184 | 198 | blob_reset(&treename); |
| 185 | - zSep = ","; | |
| 186 | 199 | } |
| 187 | - blob_append(&sql, ")", -1); | |
| 188 | 200 | db_multi_exec(blob_str(&sql)); |
| 189 | 201 | blob_reset(&sql); |
| 190 | 202 | } |
| 191 | 203 | |
| 192 | 204 | db_prepare(&q, |
| @@ -264,11 +276,15 @@ | ||
| 264 | 276 | blob_reset(&v); |
| 265 | 277 | blob_reset(&e); |
| 266 | 278 | blob_reset(&t); |
| 267 | 279 | blob_reset(&r); |
| 268 | 280 | }else if( verboseFlag ){ |
| 269 | - printf("UNCHANGED %s\n", zName); | |
| 281 | + if( chnged ){ | |
| 282 | + printf("EDITED %s\n", zName); | |
| 283 | + }else{ | |
| 284 | + printf("UNCHANGED %s\n", zName); | |
| 285 | + } | |
| 270 | 286 | } |
| 271 | 287 | free(zFullPath); |
| 272 | 288 | } |
| 273 | 289 | db_finalize(&q); |
| 274 | 290 | |
| 275 | 291 |
| --- src/update.c | |
| +++ src/update.c | |
| @@ -43,11 +43,13 @@ | |
| 43 | ** leaf. VERSION can also be "current" to select the leaf of the current |
| 44 | ** version or "latest" to select the most recent check-in. |
| 45 | ** |
| 46 | ** If one or more FILES are listed after the VERSION then only the |
| 47 | ** named files are candidates to be updated. If FILES is omitted, all |
| 48 | ** files in the current checkout are subject to be updated. |
| 49 | ** |
| 50 | ** The -n or --nochange option causes this command to do a "dry run". It |
| 51 | ** prints out what would have happened but does not actually make any |
| 52 | ** changes to the current checkout or the repository. |
| 53 | ** |
| @@ -111,11 +113,11 @@ | |
| 111 | tid = db_int(0, "SELECT rid FROM leaves, event" |
| 112 | " WHERE event.objid=leaves.rid" |
| 113 | " ORDER BY event.mtime DESC"); |
| 114 | } |
| 115 | |
| 116 | if( tid==vid ) return; /* Nothing to update */ |
| 117 | db_begin_transaction(); |
| 118 | vfile_check_signature(vid, 1); |
| 119 | if( !nochangeFlag ) undo_begin(); |
| 120 | load_vfile_from_rid(tid); |
| 121 | |
| @@ -166,27 +168,37 @@ | |
| 166 | ); |
| 167 | } |
| 168 | db_finalize(&q); |
| 169 | |
| 170 | /* If FILES appear on the command-line, remove from the "fv" table |
| 171 | ** every entry that is not named on the command-line. |
| 172 | */ |
| 173 | if( g.argc>=4 ){ |
| 174 | Blob sql; /* SQL statement to purge unwanted entries */ |
| 175 | char *zSep = "("; /* Separator in the list of filenames */ |
| 176 | Blob treename; /* Normalized filename */ |
| 177 | int i; /* Loop counter */ |
| 178 | |
| 179 | blob_zero(&sql); |
| 180 | blob_append(&sql, "DELETE FROM fv WHERE fn NOT IN ", -1); |
| 181 | for(i=3; i<g.argc; i++){ |
| 182 | file_tree_name(g.argv[i], &treename, 1); |
| 183 | blob_appendf(&sql, "%s'%q'", zSep, blob_str(&treename)); |
| 184 | blob_reset(&treename); |
| 185 | zSep = ","; |
| 186 | } |
| 187 | blob_append(&sql, ")", -1); |
| 188 | db_multi_exec(blob_str(&sql)); |
| 189 | blob_reset(&sql); |
| 190 | } |
| 191 | |
| 192 | db_prepare(&q, |
| @@ -264,11 +276,15 @@ | |
| 264 | blob_reset(&v); |
| 265 | blob_reset(&e); |
| 266 | blob_reset(&t); |
| 267 | blob_reset(&r); |
| 268 | }else if( verboseFlag ){ |
| 269 | printf("UNCHANGED %s\n", zName); |
| 270 | } |
| 271 | free(zFullPath); |
| 272 | } |
| 273 | db_finalize(&q); |
| 274 | |
| 275 |
| --- src/update.c | |
| +++ src/update.c | |
| @@ -43,11 +43,13 @@ | |
| 43 | ** leaf. VERSION can also be "current" to select the leaf of the current |
| 44 | ** version or "latest" to select the most recent check-in. |
| 45 | ** |
| 46 | ** If one or more FILES are listed after the VERSION then only the |
| 47 | ** named files are candidates to be updated. If FILES is omitted, all |
| 48 | ** files in the current checkout are subject to be updated. Using |
| 49 | ** a directory name for one of the FILES arguments is the same as |
| 50 | ** using every subdirectory and file beneath that directory. |
| 51 | ** |
| 52 | ** The -n or --nochange option causes this command to do a "dry run". It |
| 53 | ** prints out what would have happened but does not actually make any |
| 54 | ** changes to the current checkout or the repository. |
| 55 | ** |
| @@ -111,11 +113,11 @@ | |
| 113 | tid = db_int(0, "SELECT rid FROM leaves, event" |
| 114 | " WHERE event.objid=leaves.rid" |
| 115 | " ORDER BY event.mtime DESC"); |
| 116 | } |
| 117 | |
| 118 | if( !verboseFlag && (tid==vid)) return; /* Nothing to update */ |
| 119 | db_begin_transaction(); |
| 120 | vfile_check_signature(vid, 1); |
| 121 | if( !nochangeFlag ) undo_begin(); |
| 122 | load_vfile_from_rid(tid); |
| 123 | |
| @@ -166,27 +168,37 @@ | |
| 168 | ); |
| 169 | } |
| 170 | db_finalize(&q); |
| 171 | |
| 172 | /* If FILES appear on the command-line, remove from the "fv" table |
| 173 | ** every entry that is not named on the command-line or which is not |
| 174 | ** in a directory named on the command-line. |
| 175 | */ |
| 176 | if( g.argc>=4 ){ |
| 177 | Blob sql; /* SQL statement to purge unwanted entries */ |
| 178 | Blob treename; /* Normalized filename */ |
| 179 | int i; /* Loop counter */ |
| 180 | const char *zSep; /* Term separator */ |
| 181 | |
| 182 | blob_zero(&sql); |
| 183 | blob_append(&sql, "DELETE FROM fv WHERE ", -1); |
| 184 | zSep = ""; |
| 185 | for(i=3; i<g.argc; i++){ |
| 186 | file_tree_name(g.argv[i], &treename, 1); |
| 187 | if( file_isdir(g.argv[i])==1 ){ |
| 188 | if( blob_size(&treename)>0 ){ |
| 189 | blob_appendf(&sql, "%sfn NOT GLOB '%b/*' ", zSep, &treename); |
| 190 | }else{ |
| 191 | blob_reset(&sql); |
| 192 | break; |
| 193 | } |
| 194 | }else{ |
| 195 | blob_appendf(&sql, "%sfn<>%B ", zSep, &treename); |
| 196 | } |
| 197 | zSep = "AND "; |
| 198 | blob_reset(&treename); |
| 199 | } |
| 200 | db_multi_exec(blob_str(&sql)); |
| 201 | blob_reset(&sql); |
| 202 | } |
| 203 | |
| 204 | db_prepare(&q, |
| @@ -264,11 +276,15 @@ | |
| 276 | blob_reset(&v); |
| 277 | blob_reset(&e); |
| 278 | blob_reset(&t); |
| 279 | blob_reset(&r); |
| 280 | }else if( verboseFlag ){ |
| 281 | if( chnged ){ |
| 282 | printf("EDITED %s\n", zName); |
| 283 | }else{ |
| 284 | printf("UNCHANGED %s\n", zName); |
| 285 | } |
| 286 | } |
| 287 | free(zFullPath); |
| 288 | } |
| 289 | db_finalize(&q); |
| 290 | |
| 291 |
+25
-9
| --- src/update.c | ||
| +++ src/update.c | ||
| @@ -43,11 +43,13 @@ | ||
| 43 | 43 | ** leaf. VERSION can also be "current" to select the leaf of the current |
| 44 | 44 | ** version or "latest" to select the most recent check-in. |
| 45 | 45 | ** |
| 46 | 46 | ** If one or more FILES are listed after the VERSION then only the |
| 47 | 47 | ** named files are candidates to be updated. If FILES is omitted, all |
| 48 | -** files in the current checkout are subject to be updated. | |
| 48 | +** files in the current checkout are subject to be updated. Using | |
| 49 | +** a directory name for one of the FILES arguments is the same as | |
| 50 | +** using every subdirectory and file beneath that directory. | |
| 49 | 51 | ** |
| 50 | 52 | ** The -n or --nochange option causes this command to do a "dry run". It |
| 51 | 53 | ** prints out what would have happened but does not actually make any |
| 52 | 54 | ** changes to the current checkout or the repository. |
| 53 | 55 | ** |
| @@ -111,11 +113,11 @@ | ||
| 111 | 113 | tid = db_int(0, "SELECT rid FROM leaves, event" |
| 112 | 114 | " WHERE event.objid=leaves.rid" |
| 113 | 115 | " ORDER BY event.mtime DESC"); |
| 114 | 116 | } |
| 115 | 117 | |
| 116 | - if( tid==vid ) return; /* Nothing to update */ | |
| 118 | + if( !verboseFlag && (tid==vid)) return; /* Nothing to update */ | |
| 117 | 119 | db_begin_transaction(); |
| 118 | 120 | vfile_check_signature(vid, 1); |
| 119 | 121 | if( !nochangeFlag ) undo_begin(); |
| 120 | 122 | load_vfile_from_rid(tid); |
| 121 | 123 | |
| @@ -166,27 +168,37 @@ | ||
| 166 | 168 | ); |
| 167 | 169 | } |
| 168 | 170 | db_finalize(&q); |
| 169 | 171 | |
| 170 | 172 | /* If FILES appear on the command-line, remove from the "fv" table |
| 171 | - ** every entry that is not named on the command-line. | |
| 173 | + ** every entry that is not named on the command-line or which is not | |
| 174 | + ** in a directory named on the command-line. | |
| 172 | 175 | */ |
| 173 | 176 | if( g.argc>=4 ){ |
| 174 | 177 | Blob sql; /* SQL statement to purge unwanted entries */ |
| 175 | - char *zSep = "("; /* Separator in the list of filenames */ | |
| 176 | 178 | Blob treename; /* Normalized filename */ |
| 177 | 179 | int i; /* Loop counter */ |
| 180 | + const char *zSep; /* Term separator */ | |
| 178 | 181 | |
| 179 | 182 | blob_zero(&sql); |
| 180 | - blob_append(&sql, "DELETE FROM fv WHERE fn NOT IN ", -1); | |
| 183 | + blob_append(&sql, "DELETE FROM fv WHERE ", -1); | |
| 184 | + zSep = ""; | |
| 181 | 185 | for(i=3; i<g.argc; i++){ |
| 182 | 186 | file_tree_name(g.argv[i], &treename, 1); |
| 183 | - blob_appendf(&sql, "%s'%q'", zSep, blob_str(&treename)); | |
| 187 | + if( file_isdir(g.argv[i])==1 ){ | |
| 188 | + if( blob_size(&treename)>0 ){ | |
| 189 | + blob_appendf(&sql, "%sfn NOT GLOB '%b/*' ", zSep, &treename); | |
| 190 | + }else{ | |
| 191 | + blob_reset(&sql); | |
| 192 | + break; | |
| 193 | + } | |
| 194 | + }else{ | |
| 195 | + blob_appendf(&sql, "%sfn<>%B ", zSep, &treename); | |
| 196 | + } | |
| 197 | + zSep = "AND "; | |
| 184 | 198 | blob_reset(&treename); |
| 185 | - zSep = ","; | |
| 186 | 199 | } |
| 187 | - blob_append(&sql, ")", -1); | |
| 188 | 200 | db_multi_exec(blob_str(&sql)); |
| 189 | 201 | blob_reset(&sql); |
| 190 | 202 | } |
| 191 | 203 | |
| 192 | 204 | db_prepare(&q, |
| @@ -264,11 +276,15 @@ | ||
| 264 | 276 | blob_reset(&v); |
| 265 | 277 | blob_reset(&e); |
| 266 | 278 | blob_reset(&t); |
| 267 | 279 | blob_reset(&r); |
| 268 | 280 | }else if( verboseFlag ){ |
| 269 | - printf("UNCHANGED %s\n", zName); | |
| 281 | + if( chnged ){ | |
| 282 | + printf("EDITED %s\n", zName); | |
| 283 | + }else{ | |
| 284 | + printf("UNCHANGED %s\n", zName); | |
| 285 | + } | |
| 270 | 286 | } |
| 271 | 287 | free(zFullPath); |
| 272 | 288 | } |
| 273 | 289 | db_finalize(&q); |
| 274 | 290 | |
| 275 | 291 |
| --- src/update.c | |
| +++ src/update.c | |
| @@ -43,11 +43,13 @@ | |
| 43 | ** leaf. VERSION can also be "current" to select the leaf of the current |
| 44 | ** version or "latest" to select the most recent check-in. |
| 45 | ** |
| 46 | ** If one or more FILES are listed after the VERSION then only the |
| 47 | ** named files are candidates to be updated. If FILES is omitted, all |
| 48 | ** files in the current checkout are subject to be updated. |
| 49 | ** |
| 50 | ** The -n or --nochange option causes this command to do a "dry run". It |
| 51 | ** prints out what would have happened but does not actually make any |
| 52 | ** changes to the current checkout or the repository. |
| 53 | ** |
| @@ -111,11 +113,11 @@ | |
| 111 | tid = db_int(0, "SELECT rid FROM leaves, event" |
| 112 | " WHERE event.objid=leaves.rid" |
| 113 | " ORDER BY event.mtime DESC"); |
| 114 | } |
| 115 | |
| 116 | if( tid==vid ) return; /* Nothing to update */ |
| 117 | db_begin_transaction(); |
| 118 | vfile_check_signature(vid, 1); |
| 119 | if( !nochangeFlag ) undo_begin(); |
| 120 | load_vfile_from_rid(tid); |
| 121 | |
| @@ -166,27 +168,37 @@ | |
| 166 | ); |
| 167 | } |
| 168 | db_finalize(&q); |
| 169 | |
| 170 | /* If FILES appear on the command-line, remove from the "fv" table |
| 171 | ** every entry that is not named on the command-line. |
| 172 | */ |
| 173 | if( g.argc>=4 ){ |
| 174 | Blob sql; /* SQL statement to purge unwanted entries */ |
| 175 | char *zSep = "("; /* Separator in the list of filenames */ |
| 176 | Blob treename; /* Normalized filename */ |
| 177 | int i; /* Loop counter */ |
| 178 | |
| 179 | blob_zero(&sql); |
| 180 | blob_append(&sql, "DELETE FROM fv WHERE fn NOT IN ", -1); |
| 181 | for(i=3; i<g.argc; i++){ |
| 182 | file_tree_name(g.argv[i], &treename, 1); |
| 183 | blob_appendf(&sql, "%s'%q'", zSep, blob_str(&treename)); |
| 184 | blob_reset(&treename); |
| 185 | zSep = ","; |
| 186 | } |
| 187 | blob_append(&sql, ")", -1); |
| 188 | db_multi_exec(blob_str(&sql)); |
| 189 | blob_reset(&sql); |
| 190 | } |
| 191 | |
| 192 | db_prepare(&q, |
| @@ -264,11 +276,15 @@ | |
| 264 | blob_reset(&v); |
| 265 | blob_reset(&e); |
| 266 | blob_reset(&t); |
| 267 | blob_reset(&r); |
| 268 | }else if( verboseFlag ){ |
| 269 | printf("UNCHANGED %s\n", zName); |
| 270 | } |
| 271 | free(zFullPath); |
| 272 | } |
| 273 | db_finalize(&q); |
| 274 | |
| 275 |
| --- src/update.c | |
| +++ src/update.c | |
| @@ -43,11 +43,13 @@ | |
| 43 | ** leaf. VERSION can also be "current" to select the leaf of the current |
| 44 | ** version or "latest" to select the most recent check-in. |
| 45 | ** |
| 46 | ** If one or more FILES are listed after the VERSION then only the |
| 47 | ** named files are candidates to be updated. If FILES is omitted, all |
| 48 | ** files in the current checkout are subject to be updated. Using |
| 49 | ** a directory name for one of the FILES arguments is the same as |
| 50 | ** using every subdirectory and file beneath that directory. |
| 51 | ** |
| 52 | ** The -n or --nochange option causes this command to do a "dry run". It |
| 53 | ** prints out what would have happened but does not actually make any |
| 54 | ** changes to the current checkout or the repository. |
| 55 | ** |
| @@ -111,11 +113,11 @@ | |
| 113 | tid = db_int(0, "SELECT rid FROM leaves, event" |
| 114 | " WHERE event.objid=leaves.rid" |
| 115 | " ORDER BY event.mtime DESC"); |
| 116 | } |
| 117 | |
| 118 | if( !verboseFlag && (tid==vid)) return; /* Nothing to update */ |
| 119 | db_begin_transaction(); |
| 120 | vfile_check_signature(vid, 1); |
| 121 | if( !nochangeFlag ) undo_begin(); |
| 122 | load_vfile_from_rid(tid); |
| 123 | |
| @@ -166,27 +168,37 @@ | |
| 168 | ); |
| 169 | } |
| 170 | db_finalize(&q); |
| 171 | |
| 172 | /* If FILES appear on the command-line, remove from the "fv" table |
| 173 | ** every entry that is not named on the command-line or which is not |
| 174 | ** in a directory named on the command-line. |
| 175 | */ |
| 176 | if( g.argc>=4 ){ |
| 177 | Blob sql; /* SQL statement to purge unwanted entries */ |
| 178 | Blob treename; /* Normalized filename */ |
| 179 | int i; /* Loop counter */ |
| 180 | const char *zSep; /* Term separator */ |
| 181 | |
| 182 | blob_zero(&sql); |
| 183 | blob_append(&sql, "DELETE FROM fv WHERE ", -1); |
| 184 | zSep = ""; |
| 185 | for(i=3; i<g.argc; i++){ |
| 186 | file_tree_name(g.argv[i], &treename, 1); |
| 187 | if( file_isdir(g.argv[i])==1 ){ |
| 188 | if( blob_size(&treename)>0 ){ |
| 189 | blob_appendf(&sql, "%sfn NOT GLOB '%b/*' ", zSep, &treename); |
| 190 | }else{ |
| 191 | blob_reset(&sql); |
| 192 | break; |
| 193 | } |
| 194 | }else{ |
| 195 | blob_appendf(&sql, "%sfn<>%B ", zSep, &treename); |
| 196 | } |
| 197 | zSep = "AND "; |
| 198 | blob_reset(&treename); |
| 199 | } |
| 200 | db_multi_exec(blob_str(&sql)); |
| 201 | blob_reset(&sql); |
| 202 | } |
| 203 | |
| 204 | db_prepare(&q, |
| @@ -264,11 +276,15 @@ | |
| 276 | blob_reset(&v); |
| 277 | blob_reset(&e); |
| 278 | blob_reset(&t); |
| 279 | blob_reset(&r); |
| 280 | }else if( verboseFlag ){ |
| 281 | if( chnged ){ |
| 282 | printf("EDITED %s\n", zName); |
| 283 | }else{ |
| 284 | printf("UNCHANGED %s\n", zName); |
| 285 | } |
| 286 | } |
| 287 | free(zFullPath); |
| 288 | } |
| 289 | db_finalize(&q); |
| 290 | |
| 291 |