Fossil SCM
merge trunk
Commit
4105aed80d9077456057b2f02d7403f623ed18d6
Parent
5589ebbd6188aa0…
48 files changed
+1
-1
+153
-38
+394
-192
+1
-3
+9
-1
+9
-1
+1
-2
+7
-4
+29
-32
+29
-32
+2
-2
+10
-6
+8
-6
+3
-1
+4
-3
+1
-1
+5
-5
+4
-4
+12
+38
-7
+1
-1
+1
-6
+100
-29
+2
-3
+77
-21
+53
-37
+43
+328
-234
+40
-26
+1
-1
+79
-4
+18
-12
+1
-3
+1
-1
+2
-2
+4
-4
+10
-4
+31
-3
+83
-2
+24
-5
+1
-1
+8
-8
+5
-5
+1
-1
+1
-1
+4
+1
-1
+1
-1
~
src/allrepo.c
~
src/branch.c
~
src/browse.c
~
src/cgi.c
~
src/checkin.c
~
src/checkin.c
~
src/checkout.c
~
src/clone.c
~
src/db.c
~
src/db.c
~
src/diffcmd.c
~
src/foci.c
~
src/http.c
~
src/http_socket.c
~
src/http_ssl.c
~
src/info.c
~
src/json_branch.c
~
src/json_timeline.c
~
src/main.mk
~
src/makemake.tcl
~
src/markdown.c
~
src/moderate.c
~
src/name.c
~
src/purge.c
~
src/report.c
~
src/search.c
~
src/sitemap.c
~
src/sqlite3.c
~
src/sqlite3.h
~
src/stat.c
~
src/style.c
~
src/timeline.c
~
src/undo.c
~
src/xfer.c
~
test/valgrind-www.tcl
~
tools/fossil_chat.tcl
~
win/Makefile.dmc
~
win/Makefile.mingw
~
win/Makefile.mingw.mistachkin
~
win/Makefile.msc
~
www/concepts.wiki
~
www/faq.tcl
~
www/fileformat.wiki
~
www/foss-cklist.wiki
~
www/fossil-v-git.wiki
~
www/index.wiki
~
www/mkindex.tcl
~
www/server.wiki
+1
-1
| --- src/allrepo.c | ||
| +++ src/allrepo.c | ||
| @@ -76,11 +76,11 @@ | ||
| 76 | 76 | |
| 77 | 77 | |
| 78 | 78 | /* |
| 79 | 79 | ** COMMAND: all |
| 80 | 80 | ** |
| 81 | -** Usage: %fossil all (changes|clean|extras|ignore|list|ls|pull|push|rebuild|sync) | |
| 81 | +** Usage: %fossil all SUBCOMMAND ... | |
| 82 | 82 | ** |
| 83 | 83 | ** The ~/.fossil file records the location of all repositories for a |
| 84 | 84 | ** user. This command performs certain operations on all repositories |
| 85 | 85 | ** that can be useful before or after a period of disconnected operation. |
| 86 | 86 | ** |
| 87 | 87 |
| --- src/allrepo.c | |
| +++ src/allrepo.c | |
| @@ -76,11 +76,11 @@ | |
| 76 | |
| 77 | |
| 78 | /* |
| 79 | ** COMMAND: all |
| 80 | ** |
| 81 | ** Usage: %fossil all (changes|clean|extras|ignore|list|ls|pull|push|rebuild|sync) |
| 82 | ** |
| 83 | ** The ~/.fossil file records the location of all repositories for a |
| 84 | ** user. This command performs certain operations on all repositories |
| 85 | ** that can be useful before or after a period of disconnected operation. |
| 86 | ** |
| 87 |
| --- src/allrepo.c | |
| +++ src/allrepo.c | |
| @@ -76,11 +76,11 @@ | |
| 76 | |
| 77 | |
| 78 | /* |
| 79 | ** COMMAND: all |
| 80 | ** |
| 81 | ** Usage: %fossil all SUBCOMMAND ... |
| 82 | ** |
| 83 | ** The ~/.fossil file records the location of all repositories for a |
| 84 | ** user. This command performs certain operations on all repositories |
| 85 | ** that can be useful before or after a period of disconnected operation. |
| 86 | ** |
| 87 |
+153
-38
| --- src/branch.c | ||
| +++ src/branch.c | ||
| @@ -179,47 +179,67 @@ | ||
| 179 | 179 | |
| 180 | 180 | /* Do an autosync push, if requested */ |
| 181 | 181 | if( !isPrivate ) autosync_loop(SYNC_PUSH, db_get_int("autosync-tries", 1)); |
| 182 | 182 | } |
| 183 | 183 | |
| 184 | +#if INTERFACE | |
| 185 | +/* | |
| 186 | +** Allows bits in the mBplqFlags parameter to branch_prepare_list_query(). | |
| 187 | +*/ | |
| 188 | +#define BRL_CLOSED_ONLY 0x001 /* Show only closed branches */ | |
| 189 | +#define BRL_OPEN_ONLY 0x002 /* Show only open branches */ | |
| 190 | +#define BRL_BOTH 0x003 /* Show both open and closed branches */ | |
| 191 | +#define BRL_OPEN_CLOSED_MASK 0x003 | |
| 192 | +#define BRL_MTIME 0x004 /* Include lastest check-in time */ | |
| 193 | +#dfeine BRL_ORDERBY_MTIME 0x008 /* Sort by MTIME. (otherwise sort by name)*/ | |
| 194 | + | |
| 195 | +#endif /* INTERFACE */ | |
| 196 | + | |
| 184 | 197 | /* |
| 185 | 198 | ** Prepare a query that will list branches. |
| 186 | 199 | ** |
| 187 | 200 | ** If (which<0) then the query pulls only closed branches. If |
| 188 | 201 | ** (which>0) then the query pulls all (closed and opened) |
| 189 | 202 | ** branches. Else the query pulls currently-opened branches. |
| 190 | 203 | */ |
| 191 | -void branch_prepare_list_query(Stmt *pQuery, int which ){ | |
| 192 | - if( which < 0 ){ | |
| 193 | - db_prepare(pQuery, | |
| 194 | - "SELECT value FROM tagxref" | |
| 195 | - " WHERE tagid=%d AND value NOT NULL " | |
| 196 | - "EXCEPT " | |
| 197 | - "SELECT value FROM tagxref" | |
| 198 | - " WHERE tagid=%d" | |
| 199 | - " AND rid IN leaf" | |
| 200 | - " AND NOT %z" | |
| 201 | - " ORDER BY value COLLATE nocase /*sort*/", | |
| 202 | - TAG_BRANCH, TAG_BRANCH, leaf_is_closed_sql("tagxref.rid") | |
| 203 | - ); | |
| 204 | - }else if( which>0 ){ | |
| 205 | - db_prepare(pQuery, | |
| 206 | - "SELECT DISTINCT value FROM tagxref" | |
| 207 | - " WHERE tagid=%d AND value NOT NULL" | |
| 208 | - " AND rid IN leaf" | |
| 209 | - " ORDER BY value COLLATE nocase /*sort*/", | |
| 210 | - TAG_BRANCH | |
| 211 | - ); | |
| 212 | - }else{ | |
| 213 | - db_prepare(pQuery, | |
| 214 | - "SELECT DISTINCT value FROM tagxref" | |
| 215 | - " WHERE tagid=%d AND value NOT NULL" | |
| 216 | - " AND rid IN leaf" | |
| 217 | - " AND NOT %z" | |
| 218 | - " ORDER BY value COLLATE nocase /*sort*/", | |
| 219 | - TAG_BRANCH, leaf_is_closed_sql("tagxref.rid") | |
| 220 | - ); | |
| 204 | +void branch_prepare_list_query(Stmt *pQuery, int brFlags){ | |
| 205 | + switch( brFlags & BRL_OPEN_CLOSED_MASK ){ | |
| 206 | + case BRL_CLOSED_ONLY: { | |
| 207 | + db_prepare(pQuery, | |
| 208 | + "SELECT value FROM tagxref" | |
| 209 | + " WHERE tagid=%d AND value NOT NULL " | |
| 210 | + "EXCEPT " | |
| 211 | + "SELECT value FROM tagxref" | |
| 212 | + " WHERE tagid=%d" | |
| 213 | + " AND rid IN leaf" | |
| 214 | + " AND NOT %z" | |
| 215 | + " ORDER BY value COLLATE nocase /*sort*/", | |
| 216 | + TAG_BRANCH, TAG_BRANCH, leaf_is_closed_sql("tagxref.rid") | |
| 217 | + ); | |
| 218 | + break; | |
| 219 | + } | |
| 220 | + case BRL_BOTH: { | |
| 221 | + db_prepare(pQuery, | |
| 222 | + "SELECT DISTINCT value FROM tagxref" | |
| 223 | + " WHERE tagid=%d AND value NOT NULL" | |
| 224 | + " AND rid IN leaf" | |
| 225 | + " ORDER BY value COLLATE nocase /*sort*/", | |
| 226 | + TAG_BRANCH | |
| 227 | + ); | |
| 228 | + break; | |
| 229 | + } | |
| 230 | + case BRL_OPEN_ONLY: { | |
| 231 | + db_prepare(pQuery, | |
| 232 | + "SELECT DISTINCT value FROM tagxref" | |
| 233 | + " WHERE tagid=%d AND value NOT NULL" | |
| 234 | + " AND rid IN leaf" | |
| 235 | + " AND NOT %z" | |
| 236 | + " ORDER BY value COLLATE nocase /*sort*/", | |
| 237 | + TAG_BRANCH, leaf_is_closed_sql("tagxref.rid") | |
| 238 | + ); | |
| 239 | + break; | |
| 240 | + } | |
| 221 | 241 | } |
| 222 | 242 | } |
| 223 | 243 | |
| 224 | 244 | |
| 225 | 245 | /* |
| @@ -260,19 +280,20 @@ | ||
| 260 | 280 | branch_new(); |
| 261 | 281 | }else if( (strncmp(zCmd,"list",n)==0)||(strncmp(zCmd, "ls", n)==0) ){ |
| 262 | 282 | Stmt q; |
| 263 | 283 | int vid; |
| 264 | 284 | char *zCurrent = 0; |
| 265 | - int showAll = find_option("all","a",0)!=0; | |
| 266 | - int showClosed = find_option("closed","c",0)!=0; | |
| 285 | + int brFlags = BRL_OPEN_ONLY; | |
| 286 | + if( find_option("all","a",0)!=0 ) brFlags = BRL_BOTH; | |
| 287 | + if( find_option("closed","c",0)!=0 ) brFlags = BRL_CLOSED_ONLY; | |
| 267 | 288 | |
| 268 | 289 | if( g.localOpen ){ |
| 269 | 290 | vid = db_lget_int("checkout", 0); |
| 270 | 291 | zCurrent = db_text(0, "SELECT value FROM tagxref" |
| 271 | 292 | " WHERE rid=%d AND tagid=%d", vid, TAG_BRANCH); |
| 272 | 293 | } |
| 273 | - branch_prepare_list_query(&q, showAll?1:(showClosed?-1:0)); | |
| 294 | + branch_prepare_list_query(&q, brFlags); | |
| 274 | 295 | while( db_step(&q)==SQLITE_ROW ){ |
| 275 | 296 | const char *zBr = db_column_text(&q, 0); |
| 276 | 297 | int isCur = zCurrent!=0 && fossil_strcmp(zCurrent,zBr)==0; |
| 277 | 298 | fossil_print("%s%s\n", (isCur ? "* " : " "), zBr); |
| 278 | 299 | } |
| @@ -280,36 +301,130 @@ | ||
| 280 | 301 | }else{ |
| 281 | 302 | fossil_fatal("branch subcommand should be one of: " |
| 282 | 303 | "new list ls"); |
| 283 | 304 | } |
| 284 | 305 | } |
| 306 | + | |
| 307 | +static char brlistQuery[] = | |
| 308 | +@ SELECT | |
| 309 | +@ tagxref.value, | |
| 310 | +@ max(event.mtime), | |
| 311 | +@ EXISTS(SELECT 1 FROM tagxref AS tx | |
| 312 | +@ WHERE tx.rid=tagxref.rid | |
| 313 | +@ AND tx.tagid=(SELECT tagid FROM tag WHERE tagname='closed') | |
| 314 | +@ AND tx.tagtype>0), | |
| 315 | +@ (SELECT tagxref.value | |
| 316 | +@ FROM plink CROSS JOIN tagxref | |
| 317 | +@ WHERE plink.pid=event.objid | |
| 318 | +@ AND tagxref.rid=plink.cid | |
| 319 | +@ AND tagxref.tagid=(SELECT tagid FROM tag WHERE tagname='branch') | |
| 320 | +@ AND tagtype>0), | |
| 321 | +@ count(*), | |
| 322 | +@ (SELECT uuid FROM blob WHERE rid=tagxref.rid) | |
| 323 | +@ FROM tagxref, tag, event | |
| 324 | +@ WHERE tagxref.tagid=tag.tagid | |
| 325 | +@ AND tagxref.tagtype>0 | |
| 326 | +@ AND tag.tagname='branch' | |
| 327 | +@ AND event.objid=tagxref.rid | |
| 328 | +@ GROUP BY 1 | |
| 329 | +@ ORDER BY 2 DESC; | |
| 330 | +; | |
| 331 | + | |
| 332 | +/* | |
| 333 | +** This is the new-style branch-list page that shows the branch names | |
| 334 | +** together with their ages (time of last check-in) and whether or not | |
| 335 | +** they are closed or merged to another branch. | |
| 336 | +** | |
| 337 | +** Control jumps to this routine from brlist_page() (the /brlist handler) | |
| 338 | +** if there are no query parameters. | |
| 339 | +*/ | |
| 340 | +static void new_brlist_page(void){ | |
| 341 | + Stmt q; | |
| 342 | + double rNow; | |
| 343 | + login_check_credentials(); | |
| 344 | + if( !g.perm.Read ){ login_needed(); return; } | |
| 345 | + style_header("Branches"); | |
| 346 | + login_anonymous_available(); | |
| 347 | + | |
| 348 | + db_prepare(&q, brlistQuery/*works-like:""*/); | |
| 349 | + rNow = db_double(0.0, "SELECT julianday('now')"); | |
| 350 | + @ <div class="brlist"><table id="branchlisttable"> | |
| 351 | + @ <thead><tr> | |
| 352 | + @ <th>Branch Name</th> | |
| 353 | + @ <th>Age</th> | |
| 354 | + @ <th>Checkins</th> | |
| 355 | + @ <th>Status</th> | |
| 356 | + @ <th>Resolution</th> | |
| 357 | + @ </tr></thead><tbody> | |
| 358 | + while( db_step(&q)==SQLITE_ROW ){ | |
| 359 | + const char *zBranch = db_column_text(&q, 0); | |
| 360 | + double rMtime = db_column_double(&q, 1); | |
| 361 | + int isClosed = db_column_int(&q, 2); | |
| 362 | + const char *zMergeTo = db_column_text(&q, 3); | |
| 363 | + int nCkin = db_column_int(&q, 4); | |
| 364 | + const char *zLastCkin = db_column_text(&q, 5); | |
| 365 | + char *zAge = human_readable_age(rNow - rMtime); | |
| 366 | + sqlite3_int64 iMtime = (sqlite3_int64)(rMtime*86400.0); | |
| 367 | + if( zMergeTo && zMergeTo[0]==0 ) zMergeTo = 0; | |
| 368 | + @ <tr> | |
| 369 | + @ <td>%z(href("%R/timeline?n=100&r=%T",zBranch))%h(zBranch)</a></td> | |
| 370 | + @ <td data-sortkey="%016llx(-iMtime)">%s(zAge)</td> | |
| 371 | + @ <td data-sortkey="%08x(-nCkin)">%d(nCkin)</td> | |
| 372 | + fossil_free(zAge); | |
| 373 | + @ <td>%s(isClosed?"closed":"")</td> | |
| 374 | + if( zMergeTo ){ | |
| 375 | + @ <td>merged into | |
| 376 | + @ %z(href("%R/timeline?f=%s",zLastCkin))%h(zMergeTo)</a></td> | |
| 377 | + }else{ | |
| 378 | + @ <td></td> | |
| 379 | + } | |
| 380 | + @ </tr> | |
| 381 | + } | |
| 382 | + @ </tbody></table></div> | |
| 383 | + db_finalize(&q); | |
| 384 | + output_table_sorting_javascript("branchlisttable","tkktt",2); | |
| 385 | + style_footer(); | |
| 386 | +} | |
| 285 | 387 | |
| 286 | 388 | /* |
| 287 | 389 | ** WEBPAGE: brlist |
| 390 | +** Show a list of branches | |
| 391 | +** Query parameters: | |
| 288 | 392 | ** |
| 289 | -** Show a timeline of all branches | |
| 393 | +** all Show all branches | |
| 394 | +** closed Show only closed branches | |
| 395 | +** open Show only open branches (default behavior) | |
| 396 | +** colortest Show all branches with automatic color | |
| 290 | 397 | */ |
| 291 | 398 | void brlist_page(void){ |
| 292 | 399 | Stmt q; |
| 293 | 400 | int cnt; |
| 294 | 401 | int showClosed = P("closed")!=0; |
| 295 | 402 | int showAll = P("all")!=0; |
| 403 | + int showOpen = P("open")!=0; | |
| 296 | 404 | int colorTest = P("colortest")!=0; |
| 405 | + int brFlags = BRL_OPEN_ONLY; | |
| 297 | 406 | |
| 407 | + if( showClosed==0 && showAll==0 && showOpen==0 && colorTest==0 ){ | |
| 408 | + new_brlist_page(); | |
| 409 | + return; | |
| 410 | + } | |
| 298 | 411 | login_check_credentials(); |
| 299 | 412 | if( !g.perm.Read ){ login_needed(); return; } |
| 300 | 413 | if( colorTest ){ |
| 301 | 414 | showClosed = 0; |
| 302 | 415 | showAll = 1; |
| 303 | 416 | } |
| 417 | + if( showAll ) brFlags = BRL_BOTH; | |
| 418 | + if( showClosed ) brFlags = BRL_CLOSED_ONLY; | |
| 304 | 419 | |
| 305 | 420 | style_header("%s", showClosed ? "Closed Branches" : |
| 306 | 421 | showAll ? "All Branches" : "Open Branches"); |
| 307 | 422 | style_submenu_element("Timeline", "Timeline", "brtimeline"); |
| 308 | 423 | if( showClosed ){ |
| 309 | 424 | style_submenu_element("All", "All", "brlist?all"); |
| 310 | - style_submenu_element("Open","Open","brlist"); | |
| 425 | + style_submenu_element("Open","Open","brlist?open"); | |
| 311 | 426 | }else if( showAll ){ |
| 312 | 427 | style_submenu_element("Closed", "Closed", "brlist?closed"); |
| 313 | 428 | style_submenu_element("Open","Open","brlist"); |
| 314 | 429 | }else{ |
| 315 | 430 | style_submenu_element("All", "All", "brlist?all"); |
| @@ -335,21 +450,21 @@ | ||
| 335 | 450 | @ Closed branches are fixed and do not change (unless they are first |
| 336 | 451 | @ reopened).</li> |
| 337 | 452 | @ </ol> |
| 338 | 453 | style_sidebox_end(); |
| 339 | 454 | |
| 340 | - branch_prepare_list_query(&q, showAll?1:(showClosed?-1:0)); | |
| 455 | + branch_prepare_list_query(&q, brFlags); | |
| 341 | 456 | cnt = 0; |
| 342 | 457 | while( db_step(&q)==SQLITE_ROW ){ |
| 343 | 458 | const char *zBr = db_column_text(&q, 0); |
| 344 | 459 | if( cnt==0 ){ |
| 345 | 460 | if( colorTest ){ |
| 346 | 461 | @ <h2>Default background colors for all branches:</h2> |
| 462 | + }else if( showClosed ){ | |
| 463 | + @ <h2>Closed Branches:</h2> | |
| 347 | 464 | }else if( showAll ){ |
| 348 | 465 | @ <h2>All Branches:</h2> |
| 349 | - }else if( showClosed ){ | |
| 350 | - @ <h2>Closed Branches:</h2> | |
| 351 | 466 | }else{ |
| 352 | 467 | @ <h2>Open Branches:</h2> |
| 353 | 468 | } |
| 354 | 469 | @ <ul> |
| 355 | 470 | cnt++; |
| 356 | 471 |
| --- src/branch.c | |
| +++ src/branch.c | |
| @@ -179,47 +179,67 @@ | |
| 179 | |
| 180 | /* Do an autosync push, if requested */ |
| 181 | if( !isPrivate ) autosync_loop(SYNC_PUSH, db_get_int("autosync-tries", 1)); |
| 182 | } |
| 183 | |
| 184 | /* |
| 185 | ** Prepare a query that will list branches. |
| 186 | ** |
| 187 | ** If (which<0) then the query pulls only closed branches. If |
| 188 | ** (which>0) then the query pulls all (closed and opened) |
| 189 | ** branches. Else the query pulls currently-opened branches. |
| 190 | */ |
| 191 | void branch_prepare_list_query(Stmt *pQuery, int which ){ |
| 192 | if( which < 0 ){ |
| 193 | db_prepare(pQuery, |
| 194 | "SELECT value FROM tagxref" |
| 195 | " WHERE tagid=%d AND value NOT NULL " |
| 196 | "EXCEPT " |
| 197 | "SELECT value FROM tagxref" |
| 198 | " WHERE tagid=%d" |
| 199 | " AND rid IN leaf" |
| 200 | " AND NOT %z" |
| 201 | " ORDER BY value COLLATE nocase /*sort*/", |
| 202 | TAG_BRANCH, TAG_BRANCH, leaf_is_closed_sql("tagxref.rid") |
| 203 | ); |
| 204 | }else if( which>0 ){ |
| 205 | db_prepare(pQuery, |
| 206 | "SELECT DISTINCT value FROM tagxref" |
| 207 | " WHERE tagid=%d AND value NOT NULL" |
| 208 | " AND rid IN leaf" |
| 209 | " ORDER BY value COLLATE nocase /*sort*/", |
| 210 | TAG_BRANCH |
| 211 | ); |
| 212 | }else{ |
| 213 | db_prepare(pQuery, |
| 214 | "SELECT DISTINCT value FROM tagxref" |
| 215 | " WHERE tagid=%d AND value NOT NULL" |
| 216 | " AND rid IN leaf" |
| 217 | " AND NOT %z" |
| 218 | " ORDER BY value COLLATE nocase /*sort*/", |
| 219 | TAG_BRANCH, leaf_is_closed_sql("tagxref.rid") |
| 220 | ); |
| 221 | } |
| 222 | } |
| 223 | |
| 224 | |
| 225 | /* |
| @@ -260,19 +280,20 @@ | |
| 260 | branch_new(); |
| 261 | }else if( (strncmp(zCmd,"list",n)==0)||(strncmp(zCmd, "ls", n)==0) ){ |
| 262 | Stmt q; |
| 263 | int vid; |
| 264 | char *zCurrent = 0; |
| 265 | int showAll = find_option("all","a",0)!=0; |
| 266 | int showClosed = find_option("closed","c",0)!=0; |
| 267 | |
| 268 | if( g.localOpen ){ |
| 269 | vid = db_lget_int("checkout", 0); |
| 270 | zCurrent = db_text(0, "SELECT value FROM tagxref" |
| 271 | " WHERE rid=%d AND tagid=%d", vid, TAG_BRANCH); |
| 272 | } |
| 273 | branch_prepare_list_query(&q, showAll?1:(showClosed?-1:0)); |
| 274 | while( db_step(&q)==SQLITE_ROW ){ |
| 275 | const char *zBr = db_column_text(&q, 0); |
| 276 | int isCur = zCurrent!=0 && fossil_strcmp(zCurrent,zBr)==0; |
| 277 | fossil_print("%s%s\n", (isCur ? "* " : " "), zBr); |
| 278 | } |
| @@ -280,36 +301,130 @@ | |
| 280 | }else{ |
| 281 | fossil_fatal("branch subcommand should be one of: " |
| 282 | "new list ls"); |
| 283 | } |
| 284 | } |
| 285 | |
| 286 | /* |
| 287 | ** WEBPAGE: brlist |
| 288 | ** |
| 289 | ** Show a timeline of all branches |
| 290 | */ |
| 291 | void brlist_page(void){ |
| 292 | Stmt q; |
| 293 | int cnt; |
| 294 | int showClosed = P("closed")!=0; |
| 295 | int showAll = P("all")!=0; |
| 296 | int colorTest = P("colortest")!=0; |
| 297 | |
| 298 | login_check_credentials(); |
| 299 | if( !g.perm.Read ){ login_needed(); return; } |
| 300 | if( colorTest ){ |
| 301 | showClosed = 0; |
| 302 | showAll = 1; |
| 303 | } |
| 304 | |
| 305 | style_header("%s", showClosed ? "Closed Branches" : |
| 306 | showAll ? "All Branches" : "Open Branches"); |
| 307 | style_submenu_element("Timeline", "Timeline", "brtimeline"); |
| 308 | if( showClosed ){ |
| 309 | style_submenu_element("All", "All", "brlist?all"); |
| 310 | style_submenu_element("Open","Open","brlist"); |
| 311 | }else if( showAll ){ |
| 312 | style_submenu_element("Closed", "Closed", "brlist?closed"); |
| 313 | style_submenu_element("Open","Open","brlist"); |
| 314 | }else{ |
| 315 | style_submenu_element("All", "All", "brlist?all"); |
| @@ -335,21 +450,21 @@ | |
| 335 | @ Closed branches are fixed and do not change (unless they are first |
| 336 | @ reopened).</li> |
| 337 | @ </ol> |
| 338 | style_sidebox_end(); |
| 339 | |
| 340 | branch_prepare_list_query(&q, showAll?1:(showClosed?-1:0)); |
| 341 | cnt = 0; |
| 342 | while( db_step(&q)==SQLITE_ROW ){ |
| 343 | const char *zBr = db_column_text(&q, 0); |
| 344 | if( cnt==0 ){ |
| 345 | if( colorTest ){ |
| 346 | @ <h2>Default background colors for all branches:</h2> |
| 347 | }else if( showAll ){ |
| 348 | @ <h2>All Branches:</h2> |
| 349 | }else if( showClosed ){ |
| 350 | @ <h2>Closed Branches:</h2> |
| 351 | }else{ |
| 352 | @ <h2>Open Branches:</h2> |
| 353 | } |
| 354 | @ <ul> |
| 355 | cnt++; |
| 356 |
| --- src/branch.c | |
| +++ src/branch.c | |
| @@ -179,47 +179,67 @@ | |
| 179 | |
| 180 | /* Do an autosync push, if requested */ |
| 181 | if( !isPrivate ) autosync_loop(SYNC_PUSH, db_get_int("autosync-tries", 1)); |
| 182 | } |
| 183 | |
| 184 | #if INTERFACE |
| 185 | /* |
| 186 | ** Allows bits in the mBplqFlags parameter to branch_prepare_list_query(). |
| 187 | */ |
| 188 | #define BRL_CLOSED_ONLY 0x001 /* Show only closed branches */ |
| 189 | #define BRL_OPEN_ONLY 0x002 /* Show only open branches */ |
| 190 | #define BRL_BOTH 0x003 /* Show both open and closed branches */ |
| 191 | #define BRL_OPEN_CLOSED_MASK 0x003 |
| 192 | #define BRL_MTIME 0x004 /* Include lastest check-in time */ |
| 193 | #dfeine BRL_ORDERBY_MTIME 0x008 /* Sort by MTIME. (otherwise sort by name)*/ |
| 194 | |
| 195 | #endif /* INTERFACE */ |
| 196 | |
| 197 | /* |
| 198 | ** Prepare a query that will list branches. |
| 199 | ** |
| 200 | ** If (which<0) then the query pulls only closed branches. If |
| 201 | ** (which>0) then the query pulls all (closed and opened) |
| 202 | ** branches. Else the query pulls currently-opened branches. |
| 203 | */ |
| 204 | void branch_prepare_list_query(Stmt *pQuery, int brFlags){ |
| 205 | switch( brFlags & BRL_OPEN_CLOSED_MASK ){ |
| 206 | case BRL_CLOSED_ONLY: { |
| 207 | db_prepare(pQuery, |
| 208 | "SELECT value FROM tagxref" |
| 209 | " WHERE tagid=%d AND value NOT NULL " |
| 210 | "EXCEPT " |
| 211 | "SELECT value FROM tagxref" |
| 212 | " WHERE tagid=%d" |
| 213 | " AND rid IN leaf" |
| 214 | " AND NOT %z" |
| 215 | " ORDER BY value COLLATE nocase /*sort*/", |
| 216 | TAG_BRANCH, TAG_BRANCH, leaf_is_closed_sql("tagxref.rid") |
| 217 | ); |
| 218 | break; |
| 219 | } |
| 220 | case BRL_BOTH: { |
| 221 | db_prepare(pQuery, |
| 222 | "SELECT DISTINCT value FROM tagxref" |
| 223 | " WHERE tagid=%d AND value NOT NULL" |
| 224 | " AND rid IN leaf" |
| 225 | " ORDER BY value COLLATE nocase /*sort*/", |
| 226 | TAG_BRANCH |
| 227 | ); |
| 228 | break; |
| 229 | } |
| 230 | case BRL_OPEN_ONLY: { |
| 231 | db_prepare(pQuery, |
| 232 | "SELECT DISTINCT value FROM tagxref" |
| 233 | " WHERE tagid=%d AND value NOT NULL" |
| 234 | " AND rid IN leaf" |
| 235 | " AND NOT %z" |
| 236 | " ORDER BY value COLLATE nocase /*sort*/", |
| 237 | TAG_BRANCH, leaf_is_closed_sql("tagxref.rid") |
| 238 | ); |
| 239 | break; |
| 240 | } |
| 241 | } |
| 242 | } |
| 243 | |
| 244 | |
| 245 | /* |
| @@ -260,19 +280,20 @@ | |
| 280 | branch_new(); |
| 281 | }else if( (strncmp(zCmd,"list",n)==0)||(strncmp(zCmd, "ls", n)==0) ){ |
| 282 | Stmt q; |
| 283 | int vid; |
| 284 | char *zCurrent = 0; |
| 285 | int brFlags = BRL_OPEN_ONLY; |
| 286 | if( find_option("all","a",0)!=0 ) brFlags = BRL_BOTH; |
| 287 | if( find_option("closed","c",0)!=0 ) brFlags = BRL_CLOSED_ONLY; |
| 288 | |
| 289 | if( g.localOpen ){ |
| 290 | vid = db_lget_int("checkout", 0); |
| 291 | zCurrent = db_text(0, "SELECT value FROM tagxref" |
| 292 | " WHERE rid=%d AND tagid=%d", vid, TAG_BRANCH); |
| 293 | } |
| 294 | branch_prepare_list_query(&q, brFlags); |
| 295 | while( db_step(&q)==SQLITE_ROW ){ |
| 296 | const char *zBr = db_column_text(&q, 0); |
| 297 | int isCur = zCurrent!=0 && fossil_strcmp(zCurrent,zBr)==0; |
| 298 | fossil_print("%s%s\n", (isCur ? "* " : " "), zBr); |
| 299 | } |
| @@ -280,36 +301,130 @@ | |
| 301 | }else{ |
| 302 | fossil_fatal("branch subcommand should be one of: " |
| 303 | "new list ls"); |
| 304 | } |
| 305 | } |
| 306 | |
| 307 | static char brlistQuery[] = |
| 308 | @ SELECT |
| 309 | @ tagxref.value, |
| 310 | @ max(event.mtime), |
| 311 | @ EXISTS(SELECT 1 FROM tagxref AS tx |
| 312 | @ WHERE tx.rid=tagxref.rid |
| 313 | @ AND tx.tagid=(SELECT tagid FROM tag WHERE tagname='closed') |
| 314 | @ AND tx.tagtype>0), |
| 315 | @ (SELECT tagxref.value |
| 316 | @ FROM plink CROSS JOIN tagxref |
| 317 | @ WHERE plink.pid=event.objid |
| 318 | @ AND tagxref.rid=plink.cid |
| 319 | @ AND tagxref.tagid=(SELECT tagid FROM tag WHERE tagname='branch') |
| 320 | @ AND tagtype>0), |
| 321 | @ count(*), |
| 322 | @ (SELECT uuid FROM blob WHERE rid=tagxref.rid) |
| 323 | @ FROM tagxref, tag, event |
| 324 | @ WHERE tagxref.tagid=tag.tagid |
| 325 | @ AND tagxref.tagtype>0 |
| 326 | @ AND tag.tagname='branch' |
| 327 | @ AND event.objid=tagxref.rid |
| 328 | @ GROUP BY 1 |
| 329 | @ ORDER BY 2 DESC; |
| 330 | ; |
| 331 | |
| 332 | /* |
| 333 | ** This is the new-style branch-list page that shows the branch names |
| 334 | ** together with their ages (time of last check-in) and whether or not |
| 335 | ** they are closed or merged to another branch. |
| 336 | ** |
| 337 | ** Control jumps to this routine from brlist_page() (the /brlist handler) |
| 338 | ** if there are no query parameters. |
| 339 | */ |
| 340 | static void new_brlist_page(void){ |
| 341 | Stmt q; |
| 342 | double rNow; |
| 343 | login_check_credentials(); |
| 344 | if( !g.perm.Read ){ login_needed(); return; } |
| 345 | style_header("Branches"); |
| 346 | login_anonymous_available(); |
| 347 | |
| 348 | db_prepare(&q, brlistQuery/*works-like:""*/); |
| 349 | rNow = db_double(0.0, "SELECT julianday('now')"); |
| 350 | @ <div class="brlist"><table id="branchlisttable"> |
| 351 | @ <thead><tr> |
| 352 | @ <th>Branch Name</th> |
| 353 | @ <th>Age</th> |
| 354 | @ <th>Checkins</th> |
| 355 | @ <th>Status</th> |
| 356 | @ <th>Resolution</th> |
| 357 | @ </tr></thead><tbody> |
| 358 | while( db_step(&q)==SQLITE_ROW ){ |
| 359 | const char *zBranch = db_column_text(&q, 0); |
| 360 | double rMtime = db_column_double(&q, 1); |
| 361 | int isClosed = db_column_int(&q, 2); |
| 362 | const char *zMergeTo = db_column_text(&q, 3); |
| 363 | int nCkin = db_column_int(&q, 4); |
| 364 | const char *zLastCkin = db_column_text(&q, 5); |
| 365 | char *zAge = human_readable_age(rNow - rMtime); |
| 366 | sqlite3_int64 iMtime = (sqlite3_int64)(rMtime*86400.0); |
| 367 | if( zMergeTo && zMergeTo[0]==0 ) zMergeTo = 0; |
| 368 | @ <tr> |
| 369 | @ <td>%z(href("%R/timeline?n=100&r=%T",zBranch))%h(zBranch)</a></td> |
| 370 | @ <td data-sortkey="%016llx(-iMtime)">%s(zAge)</td> |
| 371 | @ <td data-sortkey="%08x(-nCkin)">%d(nCkin)</td> |
| 372 | fossil_free(zAge); |
| 373 | @ <td>%s(isClosed?"closed":"")</td> |
| 374 | if( zMergeTo ){ |
| 375 | @ <td>merged into |
| 376 | @ %z(href("%R/timeline?f=%s",zLastCkin))%h(zMergeTo)</a></td> |
| 377 | }else{ |
| 378 | @ <td></td> |
| 379 | } |
| 380 | @ </tr> |
| 381 | } |
| 382 | @ </tbody></table></div> |
| 383 | db_finalize(&q); |
| 384 | output_table_sorting_javascript("branchlisttable","tkktt",2); |
| 385 | style_footer(); |
| 386 | } |
| 387 | |
| 388 | /* |
| 389 | ** WEBPAGE: brlist |
| 390 | ** Show a list of branches |
| 391 | ** Query parameters: |
| 392 | ** |
| 393 | ** all Show all branches |
| 394 | ** closed Show only closed branches |
| 395 | ** open Show only open branches (default behavior) |
| 396 | ** colortest Show all branches with automatic color |
| 397 | */ |
| 398 | void brlist_page(void){ |
| 399 | Stmt q; |
| 400 | int cnt; |
| 401 | int showClosed = P("closed")!=0; |
| 402 | int showAll = P("all")!=0; |
| 403 | int showOpen = P("open")!=0; |
| 404 | int colorTest = P("colortest")!=0; |
| 405 | int brFlags = BRL_OPEN_ONLY; |
| 406 | |
| 407 | if( showClosed==0 && showAll==0 && showOpen==0 && colorTest==0 ){ |
| 408 | new_brlist_page(); |
| 409 | return; |
| 410 | } |
| 411 | login_check_credentials(); |
| 412 | if( !g.perm.Read ){ login_needed(); return; } |
| 413 | if( colorTest ){ |
| 414 | showClosed = 0; |
| 415 | showAll = 1; |
| 416 | } |
| 417 | if( showAll ) brFlags = BRL_BOTH; |
| 418 | if( showClosed ) brFlags = BRL_CLOSED_ONLY; |
| 419 | |
| 420 | style_header("%s", showClosed ? "Closed Branches" : |
| 421 | showAll ? "All Branches" : "Open Branches"); |
| 422 | style_submenu_element("Timeline", "Timeline", "brtimeline"); |
| 423 | if( showClosed ){ |
| 424 | style_submenu_element("All", "All", "brlist?all"); |
| 425 | style_submenu_element("Open","Open","brlist?open"); |
| 426 | }else if( showAll ){ |
| 427 | style_submenu_element("Closed", "Closed", "brlist?closed"); |
| 428 | style_submenu_element("Open","Open","brlist"); |
| 429 | }else{ |
| 430 | style_submenu_element("All", "All", "brlist?all"); |
| @@ -335,21 +450,21 @@ | |
| 450 | @ Closed branches are fixed and do not change (unless they are first |
| 451 | @ reopened).</li> |
| 452 | @ </ol> |
| 453 | style_sidebox_end(); |
| 454 | |
| 455 | branch_prepare_list_query(&q, brFlags); |
| 456 | cnt = 0; |
| 457 | while( db_step(&q)==SQLITE_ROW ){ |
| 458 | const char *zBr = db_column_text(&q, 0); |
| 459 | if( cnt==0 ){ |
| 460 | if( colorTest ){ |
| 461 | @ <h2>Default background colors for all branches:</h2> |
| 462 | }else if( showClosed ){ |
| 463 | @ <h2>Closed Branches:</h2> |
| 464 | }else if( showAll ){ |
| 465 | @ <h2>All Branches:</h2> |
| 466 | }else{ |
| 467 | @ <h2>Open Branches:</h2> |
| 468 | } |
| 469 | @ <ul> |
| 470 | cnt++; |
| 471 |
+394
-192
| --- src/browse.c | ||
| +++ src/browse.c | ||
| @@ -304,89 +304,206 @@ | ||
| 304 | 304 | |
| 305 | 305 | /* |
| 306 | 306 | ** A single line of the file hierarchy |
| 307 | 307 | */ |
| 308 | 308 | struct FileTreeNode { |
| 309 | - FileTreeNode *pNext; /* Next line in sequence */ | |
| 310 | - FileTreeNode *pPrev; /* Previous line */ | |
| 311 | - FileTreeNode *pParent; /* Directory containing this line */ | |
| 309 | + FileTreeNode *pNext; /* Next entry in an ordered list of them all */ | |
| 310 | + FileTreeNode *pParent; /* Directory containing this entry */ | |
| 311 | + FileTreeNode *pSibling; /* Next element in the same subdirectory */ | |
| 312 | + FileTreeNode *pChild; /* List of child nodes */ | |
| 313 | + FileTreeNode *pLastChild; /* Last child on the pChild list */ | |
| 312 | 314 | char *zName; /* Name of this entry. The "tail" */ |
| 313 | 315 | char *zFullName; /* Full pathname of this entry */ |
| 314 | 316 | char *zUuid; /* SHA1 hash of this file. May be NULL. */ |
| 317 | + double mtime; /* Modification time for this entry */ | |
| 315 | 318 | unsigned nFullName; /* Length of zFullName */ |
| 316 | 319 | unsigned iLevel; /* Levels of parent directories */ |
| 317 | - u8 isDir; /* True if there are children */ | |
| 318 | - u8 isLast; /* True if this is the last child of its parent */ | |
| 319 | 320 | }; |
| 320 | 321 | |
| 321 | 322 | /* |
| 322 | 323 | ** A complete file hierarchy |
| 323 | 324 | */ |
| 324 | 325 | struct FileTree { |
| 325 | 326 | FileTreeNode *pFirst; /* First line of the list */ |
| 326 | 327 | FileTreeNode *pLast; /* Last line of the list */ |
| 328 | + FileTreeNode *pLastTop; /* Last top-level node */ | |
| 327 | 329 | }; |
| 328 | 330 | |
| 329 | 331 | /* |
| 330 | 332 | ** Add one or more new FileTreeNodes to the FileTree object so that the |
| 331 | -** leaf object zPathname is at the end of the node list | |
| 333 | +** leaf object zPathname is at the end of the node list. | |
| 334 | +** | |
| 335 | +** The caller invokes this routine once for each leaf node (each file | |
| 336 | +** as opposed to each directory). This routine fills in any missing | |
| 337 | +** intermediate nodes automatically. | |
| 338 | +** | |
| 339 | +** When constructing a list of FileTreeNodes, all entries that have | |
| 340 | +** a common directory prefix must be added consecutively in order for | |
| 341 | +** the tree to be constructed properly. | |
| 332 | 342 | */ |
| 333 | 343 | static void tree_add_node( |
| 334 | 344 | FileTree *pTree, /* Tree into which nodes are added */ |
| 335 | 345 | const char *zPath, /* The full pathname of file to add */ |
| 336 | - const char *zUuid /* UUID of the file. Might be NULL. */ | |
| 346 | + const char *zUuid, /* UUID of the file. Might be NULL. */ | |
| 347 | + double mtime /* Modification time for this entry */ | |
| 337 | 348 | ){ |
| 338 | 349 | int i; |
| 339 | - FileTreeNode *pParent; | |
| 340 | - FileTreeNode *pChild; | |
| 350 | + FileTreeNode *pParent; /* Parent (directory) of the next node to insert */ | |
| 341 | 351 | |
| 342 | - pChild = pTree->pLast; | |
| 343 | - pParent = pChild ? pChild->pParent : 0; | |
| 352 | + /* Make pParent point to the most recent ancestor of zPath, or | |
| 353 | + ** NULL if there are no prior entires that are a container for zPath. | |
| 354 | + */ | |
| 355 | + pParent = pTree->pLast; | |
| 344 | 356 | while( pParent!=0 && |
| 345 | 357 | ( strncmp(pParent->zFullName, zPath, pParent->nFullName)!=0 |
| 346 | 358 | || zPath[pParent->nFullName]!='/' ) |
| 347 | 359 | ){ |
| 348 | - pChild = pParent; | |
| 349 | - pParent = pChild->pParent; | |
| 360 | + pParent = pParent->pParent; | |
| 350 | 361 | } |
| 351 | 362 | i = pParent ? pParent->nFullName+1 : 0; |
| 352 | - if( pChild ) pChild->isLast = 0; | |
| 353 | 363 | while( zPath[i] ){ |
| 354 | 364 | FileTreeNode *pNew; |
| 355 | 365 | int iStart = i; |
| 356 | 366 | int nByte; |
| 357 | 367 | while( zPath[i] && zPath[i]!='/' ){ i++; } |
| 358 | 368 | nByte = sizeof(*pNew) + i + 1; |
| 359 | 369 | if( zUuid!=0 && zPath[i]==0 ) nByte += UUID_SIZE+1; |
| 360 | 370 | pNew = fossil_malloc( nByte ); |
| 371 | + memset(pNew, 0, sizeof(*pNew)); | |
| 361 | 372 | pNew->zFullName = (char*)&pNew[1]; |
| 362 | 373 | memcpy(pNew->zFullName, zPath, i); |
| 363 | 374 | pNew->zFullName[i] = 0; |
| 364 | 375 | pNew->nFullName = i; |
| 365 | 376 | if( zUuid!=0 && zPath[i]==0 ){ |
| 366 | 377 | pNew->zUuid = pNew->zFullName + i + 1; |
| 367 | 378 | memcpy(pNew->zUuid, zUuid, UUID_SIZE+1); |
| 368 | - }else{ | |
| 369 | - pNew->zUuid = 0; | |
| 370 | 379 | } |
| 371 | 380 | pNew->zName = pNew->zFullName + iStart; |
| 372 | 381 | if( pTree->pLast ){ |
| 373 | 382 | pTree->pLast->pNext = pNew; |
| 374 | 383 | }else{ |
| 375 | 384 | pTree->pFirst = pNew; |
| 376 | 385 | } |
| 377 | - pNew->pPrev = pTree->pLast; | |
| 378 | - pNew->pNext = 0; | |
| 386 | + pTree->pLast = pNew; | |
| 379 | 387 | pNew->pParent = pParent; |
| 380 | - pTree->pLast = pNew; | |
| 381 | - pNew->iLevel = pParent ? pParent->iLevel+1 : 0; | |
| 382 | - pNew->isDir = zPath[i]=='/'; | |
| 383 | - pNew->isLast = 1; | |
| 388 | + if( pParent ){ | |
| 389 | + if( pParent->pChild ){ | |
| 390 | + pParent->pLastChild->pSibling = pNew; | |
| 391 | + }else{ | |
| 392 | + pParent->pChild = pNew; | |
| 393 | + } | |
| 394 | + pNew->iLevel = pParent->iLevel + 1; | |
| 395 | + pParent->pLastChild = pNew; | |
| 396 | + }else{ | |
| 397 | + if( pTree->pLastTop ) pTree->pLastTop->pSibling = pNew; | |
| 398 | + pTree->pLastTop = pNew; | |
| 399 | + } | |
| 400 | + pNew->mtime = mtime; | |
| 384 | 401 | while( zPath[i]=='/' ){ i++; } |
| 385 | 402 | pParent = pNew; |
| 386 | 403 | } |
| 404 | + while( pParent && pParent->pParent ){ | |
| 405 | + if( pParent->pParent->mtime < pParent->mtime ){ | |
| 406 | + pParent->pParent->mtime = pParent->mtime; | |
| 407 | + } | |
| 408 | + pParent = pParent->pParent; | |
| 409 | + } | |
| 410 | +} | |
| 411 | + | |
| 412 | +/* Comparison function for two FileTreeNode objects. Sort first by | |
| 413 | +** mtime (larger numbers first) and then by zName (smaller names first). | |
| 414 | +** | |
| 415 | +** Return negative if pLeft<pRight. | |
| 416 | +** Return positive if pLeft>pRight. | |
| 417 | +** Return zero if pLeft==pRight. | |
| 418 | +*/ | |
| 419 | +static int compareNodes(FileTreeNode *pLeft, FileTreeNode *pRight){ | |
| 420 | + if( pLeft->mtime>pRight->mtime ) return -1; | |
| 421 | + if( pLeft->mtime<pRight->mtime ) return +1; | |
| 422 | + return fossil_stricmp(pLeft->zName, pRight->zName); | |
| 423 | +} | |
| 424 | + | |
| 425 | +/* Merge together two sorted lists of FileTreeNode objects */ | |
| 426 | +static FileTreeNode *mergeNodes(FileTreeNode *pLeft, FileTreeNode *pRight){ | |
| 427 | + FileTreeNode *pEnd; | |
| 428 | + FileTreeNode base; | |
| 429 | + pEnd = &base; | |
| 430 | + while( pLeft && pRight ){ | |
| 431 | + if( compareNodes(pLeft,pRight)<=0 ){ | |
| 432 | + pEnd = pEnd->pSibling = pLeft; | |
| 433 | + pLeft = pLeft->pSibling; | |
| 434 | + }else{ | |
| 435 | + pEnd = pEnd->pSibling = pRight; | |
| 436 | + pRight = pRight->pSibling; | |
| 437 | + } | |
| 438 | + } | |
| 439 | + if( pLeft ){ | |
| 440 | + pEnd->pSibling = pLeft; | |
| 441 | + }else{ | |
| 442 | + pEnd->pSibling = pRight; | |
| 443 | + } | |
| 444 | + return base.pSibling; | |
| 445 | +} | |
| 446 | + | |
| 447 | +/* Sort a list of FileTreeNode objects in mtime order. */ | |
| 448 | +static FileTreeNode *sortNodesByMtime(FileTreeNode *p){ | |
| 449 | + FileTreeNode *a[30]; | |
| 450 | + FileTreeNode *pX; | |
| 451 | + int i; | |
| 452 | + | |
| 453 | + memset(a, 0, sizeof(a)); | |
| 454 | + while( p ){ | |
| 455 | + pX = p; | |
| 456 | + p = pX->pSibling; | |
| 457 | + pX->pSibling = 0; | |
| 458 | + for(i=0; i<count(a)-1 && a[i]!=0; i++){ | |
| 459 | + pX = mergeNodes(a[i], pX); | |
| 460 | + a[i] = 0; | |
| 461 | + } | |
| 462 | + a[i] = mergeNodes(a[i], pX); | |
| 463 | + } | |
| 464 | + pX = 0; | |
| 465 | + for(i=0; i<count(a); i++){ | |
| 466 | + pX = mergeNodes(a[i], pX); | |
| 467 | + } | |
| 468 | + return pX; | |
| 469 | +} | |
| 470 | + | |
| 471 | +/* Sort an entire FileTreeNode tree by mtime | |
| 472 | +** | |
| 473 | +** This routine invalidates the following fields: | |
| 474 | +** | |
| 475 | +** FileTreeNode.pLastChild | |
| 476 | +** FileTreeNode.pNext | |
| 477 | +** | |
| 478 | +** Use relinkTree to reconnect the pNext pointers. | |
| 479 | +*/ | |
| 480 | +static FileTreeNode *sortTreeByMtime(FileTreeNode *p){ | |
| 481 | + FileTreeNode *pX; | |
| 482 | + for(pX=p; pX; pX=pX->pSibling){ | |
| 483 | + if( pX->pChild ) pX->pChild = sortTreeByMtime(pX->pChild); | |
| 484 | + } | |
| 485 | + return sortNodesByMtime(p); | |
| 486 | +} | |
| 487 | + | |
| 488 | +/* Reconstruct the FileTree by reconnecting the FileTreeNode.pNext | |
| 489 | +** fields in sequential order. | |
| 490 | +*/ | |
| 491 | +static void relinkTree(FileTree *pTree, FileTreeNode *pRoot){ | |
| 492 | + while( pRoot ){ | |
| 493 | + if( pTree->pLast ){ | |
| 494 | + pTree->pLast->pNext = pRoot; | |
| 495 | + }else{ | |
| 496 | + pTree->pFirst = pRoot; | |
| 497 | + } | |
| 498 | + pTree->pLast = pRoot; | |
| 499 | + if( pRoot->pChild ) relinkTree(pTree, pRoot->pChild); | |
| 500 | + pRoot = pRoot->pSibling; | |
| 501 | + } | |
| 502 | + if( pTree->pLast ) pTree->pLast->pNext = 0; | |
| 387 | 503 | } |
| 504 | + | |
| 388 | 505 | |
| 389 | 506 | /* |
| 390 | 507 | ** WEBPAGE: tree |
| 391 | 508 | ** |
| 392 | 509 | ** Query parameters: |
| @@ -394,19 +511,23 @@ | ||
| 394 | 511 | ** name=PATH Directory to display. Optional |
| 395 | 512 | ** ci=LABEL Show only files in this check-in. Optional. |
| 396 | 513 | ** re=REGEXP Show only files matching REGEXP. Optional. |
| 397 | 514 | ** expand Begin with the tree fully expanded. |
| 398 | 515 | ** nofiles Show directories (folders) only. Omit files. |
| 516 | +** mtime Order directory elements by decreasing mtime | |
| 399 | 517 | */ |
| 400 | 518 | void page_tree(void){ |
| 401 | 519 | char *zD = fossil_strdup(P("name")); |
| 402 | 520 | int nD = zD ? strlen(zD)+1 : 0; |
| 403 | 521 | const char *zCI = P("ci"); |
| 404 | 522 | int rid = 0; |
| 405 | 523 | char *zUuid = 0; |
| 406 | 524 | Blob dirname; |
| 407 | 525 | Manifest *pM = 0; |
| 526 | + double rNow = 0; | |
| 527 | + char *zNow = 0; | |
| 528 | + int useMtime = atoi(PD("mtime","0")); | |
| 408 | 529 | int nFile = 0; /* Number of files (or folders with "nofiles") */ |
| 409 | 530 | int linkTrunk = 1; /* include link to "trunk" */ |
| 410 | 531 | int linkTip = 1; /* include link to "tip" */ |
| 411 | 532 | const char *zRE; /* the value for the re=REGEXP query parameter */ |
| 412 | 533 | const char *zObjType; /* "files" by default or "folders" for "nofiles" */ |
| @@ -464,14 +585,21 @@ | ||
| 464 | 585 | int trunkRid = symbolic_name_to_rid("tag:trunk", "ci"); |
| 465 | 586 | linkTrunk = trunkRid && rid != trunkRid; |
| 466 | 587 | linkTip = rid != symbolic_name_to_rid("tip", "ci"); |
| 467 | 588 | zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 468 | 589 | url_add_parameter(&sURI, "ci", zCI); |
| 590 | + rNow = db_double(0.0, "SELECT mtime FROM event WHERE objid=%d", rid); | |
| 591 | + zNow = db_text("", "SELECT datetime(mtime,'localtime')" | |
| 592 | + " FROM event WHERE objid=%d", rid); | |
| 469 | 593 | }else{ |
| 470 | 594 | zCI = 0; |
| 471 | 595 | } |
| 472 | 596 | } |
| 597 | + if( zCI==0 ){ | |
| 598 | + rNow = db_double(0.0, "SELECT max(mtime) FROM event"); | |
| 599 | + zNow = db_text("", "SELECT datetime(max(mtime),'localtime') FROM event"); | |
| 600 | + } | |
| 473 | 601 | |
| 474 | 602 | /* Compute the title of the page */ |
| 475 | 603 | blob_zero(&dirname); |
| 476 | 604 | if( zD ){ |
| 477 | 605 | url_add_parameter(&sURI, "name", zD); |
| @@ -483,10 +611,18 @@ | ||
| 483 | 611 | }else{ |
| 484 | 612 | if( zRE ){ |
| 485 | 613 | blob_appendf(&dirname, "matching \"%s\"", zRE); |
| 486 | 614 | } |
| 487 | 615 | } |
| 616 | + if( useMtime ){ | |
| 617 | + style_submenu_element("Sort By Filename","Sort By Filename", "%s", | |
| 618 | + url_render(&sURI, 0, 0, 0, 0)); | |
| 619 | + url_add_parameter(&sURI, "mtime", "1"); | |
| 620 | + }else{ | |
| 621 | + style_submenu_element("Sort By Time","Sort By Time", "%s", | |
| 622 | + url_render(&sURI, "mtime", "1", 0, 0)); | |
| 623 | + } | |
| 488 | 624 | if( zCI ){ |
| 489 | 625 | style_submenu_element("All", "All", "%s", |
| 490 | 626 | url_render(&sURI, "ci", 0, 0, 0)); |
| 491 | 627 | if( nD==0 && !showDirOnly ){ |
| 492 | 628 | style_submenu_element("File Ages", "File Ages", "%R/fileage?name=%s", |
| @@ -499,87 +635,82 @@ | ||
| 499 | 635 | } |
| 500 | 636 | if( linkTip ){ |
| 501 | 637 | style_submenu_element("Tip", "Tip", "%s", |
| 502 | 638 | url_render(&sURI, "ci", "tip", 0, 0)); |
| 503 | 639 | } |
| 504 | - if( !showDirOnly ){ | |
| 505 | - style_submenu_element("Flat-View", "Flat-View", "%s", | |
| 506 | - url_render(&sURI, "type", "flat", 0, 0)); | |
| 507 | - } | |
| 508 | 640 | |
| 509 | 641 | /* Compute the file hierarchy. |
| 510 | 642 | */ |
| 511 | 643 | if( zCI ){ |
| 512 | - Stmt ins, q; | |
| 513 | - ManifestFile *pFile; | |
| 514 | - | |
| 515 | - db_multi_exec( | |
| 516 | - "CREATE TEMP TABLE filelist(" | |
| 517 | - " x TEXT PRIMARY KEY COLLATE nocase," | |
| 518 | - " uuid TEXT" | |
| 519 | - ") WITHOUT ROWID;" | |
| 644 | + Stmt q; | |
| 645 | + compute_fileage(rid, 0); | |
| 646 | + db_prepare(&q, | |
| 647 | + "SELECT filename.name, blob.uuid, fileage.mtime\n" | |
| 648 | + " FROM fileage, filename, blob\n" | |
| 649 | + " WHERE filename.fnid=fileage.fnid\n" | |
| 650 | + " AND blob.rid=fileage.fid\n" | |
| 651 | + " ORDER BY filename.name COLLATE nocase;" | |
| 520 | 652 | ); |
| 521 | - db_prepare(&ins, "INSERT OR IGNORE INTO filelist VALUES(:f,:u)"); | |
| 522 | - manifest_file_rewind(pM); | |
| 523 | - while( (pFile = manifest_file_next(pM,0))!=0 ){ | |
| 524 | - if( nD>0 | |
| 525 | - && (fossil_strncmp(pFile->zName, zD, nD-1)!=0 | |
| 526 | - || pFile->zName[nD-1]!='/') | |
| 527 | - ){ | |
| 528 | - continue; | |
| 529 | - } | |
| 530 | - if( pRE && re_match(pRE, (const u8*)pFile->zName, -1)==0 ) continue; | |
| 531 | - db_bind_text(&ins, ":f", pFile->zName); | |
| 532 | - db_bind_text(&ins, ":u", pFile->zUuid); | |
| 533 | - db_step(&ins); | |
| 534 | - db_reset(&ins); | |
| 535 | - } | |
| 536 | - db_finalize(&ins); | |
| 537 | - db_prepare(&q, "SELECT x, uuid FROM filelist ORDER BY x"); | |
| 538 | 653 | while( db_step(&q)==SQLITE_ROW ){ |
| 539 | - tree_add_node(&sTree, db_column_text(&q,0), db_column_text(&q,1)); | |
| 654 | + const char *zFile = db_column_text(&q,0); | |
| 655 | + const char *zUuid = db_column_text(&q,1); | |
| 656 | + double mtime = db_column_double(&q,2); | |
| 657 | + if( pRE && re_match(pRE, (const unsigned char*)zFile, -1)==0 ) continue; | |
| 658 | + tree_add_node(&sTree, zFile, zUuid, mtime); | |
| 540 | 659 | nFile++; |
| 541 | 660 | } |
| 542 | 661 | db_finalize(&q); |
| 543 | 662 | }else{ |
| 544 | 663 | Stmt q; |
| 545 | - db_prepare(&q, "SELECT name FROM filename ORDER BY name COLLATE nocase"); | |
| 664 | + db_prepare(&q, | |
| 665 | + "SELECT filename.name, blob.uuid, max(event.mtime)\n" | |
| 666 | + " FROM filename, mlink, blob, event\n" | |
| 667 | + " WHERE mlink.fnid=filename.fnid\n" | |
| 668 | + " AND event.objid=mlink.mid\n" | |
| 669 | + " AND blob.rid=mlink.fid\n" | |
| 670 | + " GROUP BY 1 ORDER BY 1 COLLATE nocase"); | |
| 546 | 671 | while( db_step(&q)==SQLITE_ROW ){ |
| 547 | - const char *z = db_column_text(&q, 0); | |
| 548 | - if( nD>0 && (fossil_strncmp(z, zD, nD-1)!=0 || z[nD-1]!='/') ){ | |
| 672 | + const char *zName = db_column_text(&q, 0); | |
| 673 | + const char *zUuid = db_column_text(&q,1); | |
| 674 | + double mtime = db_column_double(&q,2); | |
| 675 | + if( nD>0 && (fossil_strncmp(zName, zD, nD-1)!=0 || zName[nD-1]!='/') ){ | |
| 549 | 676 | continue; |
| 550 | 677 | } |
| 551 | - if( pRE && re_match(pRE, (const u8*)z, -1)==0 ) continue; | |
| 552 | - tree_add_node(&sTree, z, 0); | |
| 678 | + if( pRE && re_match(pRE, (const u8*)zName, -1)==0 ) continue; | |
| 679 | + tree_add_node(&sTree, zName, zUuid, mtime); | |
| 553 | 680 | nFile++; |
| 554 | 681 | } |
| 555 | 682 | db_finalize(&q); |
| 556 | 683 | } |
| 557 | 684 | |
| 558 | 685 | if( showDirOnly ){ |
| 559 | 686 | for(nFile=0, p=sTree.pFirst; p; p=p->pNext){ |
| 560 | - if( p->isDir && p->nFullName>nD ) nFile++; | |
| 687 | + if( p->pChild!=0 && p->nFullName>nD ) nFile++; | |
| 561 | 688 | } |
| 562 | - zObjType = "folders"; | |
| 689 | + zObjType = "Folders"; | |
| 563 | 690 | style_submenu_element("Files","Files","%s", |
| 564 | 691 | url_render(&sURI,"nofiles",0,0,0)); |
| 565 | 692 | }else{ |
| 566 | - zObjType = "files"; | |
| 693 | + zObjType = "Files"; | |
| 567 | 694 | style_submenu_element("Folders","Folders","%s", |
| 568 | 695 | url_render(&sURI,"nofiles","1",0,0)); |
| 569 | 696 | } |
| 570 | 697 | |
| 571 | 698 | if( zCI ){ |
| 572 | - @ <h2>%d(nFile) %s(zObjType) of check-in | |
| 699 | + @ <h2>%s(zObjType) from | |
| 573 | 700 | if( sqlite3_strnicmp(zCI, zUuid, (int)strlen(zCI))!=0 ){ |
| 574 | 701 | @ "%h(zCI)" |
| 575 | 702 | } |
| 576 | - @ [%z(href("vinfo?name=%s",zUuid))%S(zUuid)</a>] %s(blob_str(&dirname))</h2> | |
| 703 | + @ [%z(href("vinfo?name=%s",zUuid))%S(zUuid)</a>] %s(blob_str(&dirname)) | |
| 577 | 704 | }else{ |
| 578 | 705 | int n = db_int(0, "SELECT count(*) FROM plink"); |
| 579 | - @ <h2>%d(nFile) %s(zObjType) from all %d(n) check-ins | |
| 580 | - @ %s(blob_str(&dirname))</h2> | |
| 706 | + @ <h2>%s(zObjType) from all %d(n) check-ins %s(blob_str(&dirname)) | |
| 707 | + } | |
| 708 | + if( useMtime ){ | |
| 709 | + @ sorted by modification time</h2> | |
| 710 | + }else{ | |
| 711 | + @ sorted by filename</h2> | |
| 581 | 712 | } |
| 582 | 713 | |
| 583 | 714 | |
| 584 | 715 | /* Generate tree of lists. |
| 585 | 716 | ** |
| @@ -596,18 +727,33 @@ | ||
| 596 | 727 | if( nD ){ |
| 597 | 728 | @ <li class="dir last"> |
| 598 | 729 | }else{ |
| 599 | 730 | @ <li class="dir subdir last"> |
| 600 | 731 | } |
| 732 | + @ <div class="filetreeline"> | |
| 601 | 733 | @ %z(href("%s",url_render(&sURI,"name",0,0,0)))%h(zProjectName)</a> |
| 734 | + if( zNow ){ | |
| 735 | + @ <div class="filetreeage">%s(zNow)</div> | |
| 736 | + } | |
| 737 | + @ </div> | |
| 602 | 738 | @ <ul> |
| 739 | + if( useMtime ){ | |
| 740 | + p = sortTreeByMtime(sTree.pFirst); | |
| 741 | + memset(&sTree, 0, sizeof(sTree)); | |
| 742 | + relinkTree(&sTree, p); | |
| 743 | + } | |
| 603 | 744 | for(p=sTree.pFirst, nDir=0; p; p=p->pNext){ |
| 604 | - const char *zLastClass = p->isLast ? " last" : ""; | |
| 605 | - if( p->isDir ){ | |
| 745 | + const char *zLastClass = p->pSibling==0 ? " last" : ""; | |
| 746 | + if( p->pChild ){ | |
| 606 | 747 | const char *zSubdirClass = p->nFullName==nD-1 ? " subdir" : ""; |
| 607 | - @ <li class="dir%s(zSubdirClass)%s(zLastClass)"> | |
| 748 | + @ <li class="dir%s(zSubdirClass)%s(zLastClass)"><div class="filetreeline"> | |
| 608 | 749 | @ %z(href("%s",url_render(&sURI,"name",p->zFullName,0,0)))%h(p->zName)</a> |
| 750 | + if( p->mtime>0.0 ){ | |
| 751 | + char *zAge = human_readable_age(rNow - p->mtime); | |
| 752 | + @ <div class="filetreeage">%s(zAge)</div> | |
| 753 | + } | |
| 754 | + @ </div> | |
| 609 | 755 | if( startExpanded || p->nFullName<=nD ){ |
| 610 | 756 | @ <ul id="dir%d(nDir)"> |
| 611 | 757 | }else{ |
| 612 | 758 | @ <ul id="dir%d(nDir)" class="collapsed"> |
| 613 | 759 | } |
| @@ -614,17 +760,23 @@ | ||
| 614 | 760 | nDir++; |
| 615 | 761 | }else if( !showDirOnly ){ |
| 616 | 762 | const char *zFileClass = fileext_class(p->zName); |
| 617 | 763 | char *zLink; |
| 618 | 764 | if( zCI ){ |
| 619 | - zLink = href("%R/artifact/%s",p->zUuid); | |
| 765 | + zLink = href("%R/artifact/%.16s",p->zUuid); | |
| 620 | 766 | }else{ |
| 621 | 767 | zLink = href("%R/finfo?name=%T",p->zFullName); |
| 622 | 768 | } |
| 623 | - @ <li class="%z(zFileClass)%s(zLastClass)">%z(zLink)%h(p->zName)</a> | |
| 769 | + @ <li class="%z(zFileClass)%s(zLastClass)"><div class="filetreeline"> | |
| 770 | + @ %z(zLink)%h(p->zName)</a> | |
| 771 | + if( p->mtime>0 ){ | |
| 772 | + char *zAge = human_readable_age(rNow - p->mtime); | |
| 773 | + @ <div class="filetreeage">%s(zAge)</div> | |
| 774 | + } | |
| 775 | + @ </div> | |
| 624 | 776 | } |
| 625 | - if( p->isLast ){ | |
| 777 | + if( p->pSibling==0 ){ | |
| 626 | 778 | int nClose = p->iLevel - (p->pNext ? p->pNext->iLevel : 0); |
| 627 | 779 | while( nClose-- > 0 ){ |
| 628 | 780 | @ </ul> |
| 629 | 781 | } |
| 630 | 782 | } |
| @@ -687,16 +839,16 @@ | ||
| 687 | 839 | @ checkState(); |
| 688 | 840 | @ outer_ul.onclick = function(e){ |
| 689 | 841 | @ e = e || window.event; |
| 690 | 842 | @ var a = e.target || e.srcElement; |
| 691 | 843 | @ if( a.nodeName!='A' ) return true; |
| 692 | - @ if( a.parentNode==subdir ){ | |
| 844 | + @ if( a.parentNode.parentNode==subdir ){ | |
| 693 | 845 | @ toggleAll(outer_ul); |
| 694 | 846 | @ return false; |
| 695 | 847 | @ } |
| 696 | 848 | @ if( !belowSubdir(a) ) return true; |
| 697 | - @ var ul = a.nextSibling; | |
| 849 | + @ var ul = a.parentNode.nextSibling; | |
| 698 | 850 | @ while( ul && ul.nodeName!='UL' ) ul = ul.nextSibling; |
| 699 | 851 | @ if( !ul ) return true; /* This is a file link, not a directory */ |
| 700 | 852 | @ toggleDir(ul); |
| 701 | 853 | @ return false; |
| 702 | 854 | @ } |
| @@ -724,87 +876,115 @@ | ||
| 724 | 876 | }else{ |
| 725 | 877 | zClass = mprintf("file"); |
| 726 | 878 | } |
| 727 | 879 | return zClass; |
| 728 | 880 | } |
| 881 | + | |
| 882 | +/* | |
| 883 | +** SQL used to compute the age of all files in checkin :ckin whose | |
| 884 | +** names match :glob | |
| 885 | +*/ | |
| 886 | +static const char zComputeFileAgeSetup[] = | |
| 887 | +@ CREATE TABLE IF NOT EXISTS temp.fileage( | |
| 888 | +@ fnid INTEGER PRIMARY KEY, | |
| 889 | +@ fid INTEGER, | |
| 890 | +@ mid INTEGER, | |
| 891 | +@ mtime DATETIME, | |
| 892 | +@ pathname TEXT | |
| 893 | +@ ); | |
| 894 | +@ CREATE VIRTUAL TABLE IF NOT EXISTS temp.foci USING files_of_checkin; | |
| 895 | +; | |
| 896 | + | |
| 897 | +static const char zComputeFileAgeRun[] = | |
| 898 | +@ WITH RECURSIVE | |
| 899 | +@ ckin(x) AS (VALUES(:ckin) UNION ALL | |
| 900 | +@ SELECT pid FROM ckin, plink WHERE cid=x AND isprim) | |
| 901 | +@ INSERT OR IGNORE INTO fileage(fnid, fid, mid, mtime, pathname) | |
| 902 | +@ SELECT mlink.fnid, mlink.fid, x, event.mtime, filename.name | |
| 903 | +@ FROM ckin, mlink, event, filename | |
| 904 | +@ WHERE mlink.mid=ckin.x | |
| 905 | +@ AND mlink.fnid IN (SELECT fnid FROM foci, filename | |
| 906 | +@ WHERE foci.checkinID=:ckin | |
| 907 | +@ AND filename.name=foci.filename | |
| 908 | +@ AND filename.name GLOB :glob) | |
| 909 | +@ AND filename.fnid=mlink.fnid | |
| 910 | +@ AND event.objid=mlink.mid; | |
| 911 | +; | |
| 912 | + | |
| 729 | 913 | |
| 730 | 914 | /* |
| 731 | 915 | ** Look at all file containing in the version "vid". Construct a |
| 732 | 916 | ** temporary table named "fileage" that contains the file-id for each |
| 733 | 917 | ** files, the pathname, the check-in where the file was added, and the |
| 734 | 918 | ** mtime on that checkin. If zGlob and *zGlob then only files matching |
| 735 | 919 | ** the given glob are computed. |
| 736 | 920 | */ |
| 737 | 921 | int compute_fileage(int vid, const char* zGlob){ |
| 738 | - Manifest *pManifest; | |
| 739 | - ManifestFile *pFile; | |
| 740 | - int nFile = 0; | |
| 741 | - double vmtime; | |
| 742 | - Stmt ins; | |
| 743 | - Stmt q1, q2, q3; | |
| 744 | - Stmt upd; | |
| 745 | - if(zGlob && !*zGlob) zGlob = NULL; | |
| 746 | - db_multi_exec( | |
| 747 | - /*"DROP TABLE IF EXISTS temp.fileage;"*/ | |
| 748 | - "CREATE TEMP TABLE fileage(" | |
| 749 | - " fid INTEGER," | |
| 750 | - " mid INTEGER," | |
| 751 | - " mtime DATETIME," | |
| 752 | - " pathname TEXT" | |
| 753 | - ");" | |
| 754 | - "CREATE INDEX fileage_fid ON fileage(fid);" | |
| 755 | - ); | |
| 756 | - pManifest = manifest_get(vid, CFTYPE_MANIFEST, 0); | |
| 757 | - if( pManifest==0 ) return 1; | |
| 758 | - manifest_file_rewind(pManifest); | |
| 759 | - db_prepare(&ins, | |
| 760 | - "INSERT INTO temp.fileage(fid, pathname)" | |
| 761 | - " SELECT rid, :path FROM blob WHERE uuid=:uuid" | |
| 762 | - ); | |
| 763 | - while( (pFile = manifest_file_next(pManifest, 0))!=0 ){ | |
| 764 | - if( zGlob && sqlite3_strglob(zGlob, pFile->zName)!=0 ) continue; | |
| 765 | - db_bind_text(&ins, ":uuid", pFile->zUuid); | |
| 766 | - db_bind_text(&ins, ":path", pFile->zName); | |
| 767 | - db_step(&ins); | |
| 768 | - db_reset(&ins); | |
| 769 | - nFile++; | |
| 770 | - } | |
| 771 | - db_finalize(&ins); | |
| 772 | - manifest_destroy(pManifest); | |
| 773 | - db_prepare(&q1,"SELECT fid FROM mlink WHERE mid=:mid"); | |
| 774 | - db_prepare(&upd, "UPDATE fileage SET mid=:mid, mtime=:vmtime" | |
| 775 | - " WHERE fid=:fid AND mid IS NULL"); | |
| 776 | - db_prepare(&q2,"SELECT pid FROM plink WHERE cid=:vid AND isprim"); | |
| 777 | - db_prepare(&q3,"SELECT mtime FROM event WHERE objid=:vid"); | |
| 778 | - while( nFile>0 && vid>0 ){ | |
| 779 | - db_bind_int(&q3, ":vid", vid); | |
| 780 | - if( db_step(&q3)==SQLITE_ROW ){ | |
| 781 | - vmtime = db_column_double(&q3, 0); | |
| 782 | - }else{ | |
| 783 | - break; | |
| 784 | - } | |
| 785 | - db_reset(&q3); | |
| 786 | - db_bind_int(&q1, ":mid", vid); | |
| 787 | - db_bind_int(&upd, ":mid", vid); | |
| 788 | - db_bind_double(&upd, ":vmtime", vmtime); | |
| 789 | - while( db_step(&q1)==SQLITE_ROW ){ | |
| 790 | - db_bind_int(&upd, ":fid", db_column_int(&q1, 0)); | |
| 791 | - db_step(&upd); | |
| 792 | - nFile -= db_changes(); | |
| 793 | - db_reset(&upd); | |
| 794 | - } | |
| 795 | - db_reset(&q1); | |
| 796 | - db_bind_int(&q2, ":vid", vid); | |
| 797 | - if( db_step(&q2)!=SQLITE_ROW ) break; | |
| 798 | - vid = db_column_int(&q2, 0); | |
| 799 | - db_reset(&q2); | |
| 800 | - } | |
| 801 | - db_finalize(&q1); | |
| 802 | - db_finalize(&upd); | |
| 803 | - db_finalize(&q2); | |
| 804 | - db_finalize(&q3); | |
| 805 | - return 0; | |
| 922 | + Stmt q; | |
| 923 | + db_multi_exec(zComputeFileAgeSetup /*works-like:"constant"*/); | |
| 924 | + db_prepare(&q, zComputeFileAgeRun /*works-like:"constant"*/); | |
| 925 | + db_bind_int(&q, ":ckin", vid); | |
| 926 | + db_bind_text(&q, ":glob", zGlob && zGlob[0] ? zGlob : "*"); | |
| 927 | + db_exec(&q); | |
| 928 | + db_finalize(&q); | |
| 929 | + return 0; | |
| 930 | +} | |
| 931 | + | |
| 932 | +/* | |
| 933 | +** Render the number of days in rAge as a more human-readable time span. | |
| 934 | +** Different units (seconds, minutes, hours, days, months, years) are | |
| 935 | +** selected depending on the magnitude of rAge. | |
| 936 | +** | |
| 937 | +** The string returned is obtained from fossil_malloc() and should be | |
| 938 | +** freed by the caller. | |
| 939 | +*/ | |
| 940 | +char *human_readable_age(double rAge){ | |
| 941 | + if( rAge*86400.0<120 ){ | |
| 942 | + if( rAge*86400.0<1.0 ){ | |
| 943 | + return mprintf("current"); | |
| 944 | + }else{ | |
| 945 | + return mprintf("%d seconds", (int)(rAge*86400.0)); | |
| 946 | + } | |
| 947 | + }else if( rAge*1440.0<90 ){ | |
| 948 | + return mprintf("%.1f minutes", rAge*1440.0); | |
| 949 | + }else if( rAge*24.0<36 ){ | |
| 950 | + return mprintf("%.1f hours", rAge*24.0); | |
| 951 | + }else if( rAge<365.0 ){ | |
| 952 | + return mprintf("%.1f days", rAge); | |
| 953 | + }else{ | |
| 954 | + return mprintf("%.2f years", rAge/365.0); | |
| 955 | + } | |
| 956 | +} | |
| 957 | + | |
| 958 | +/* | |
| 959 | +** COMMAND: test-fileage | |
| 960 | +** | |
| 961 | +** Usage: %fossil test-fileage CHECKIN | |
| 962 | +*/ | |
| 963 | +void test_fileage_cmd(void){ | |
| 964 | + int mid; | |
| 965 | + Stmt q; | |
| 966 | + const char *zGlob = find_option("glob",0,1); | |
| 967 | + db_find_and_open_repository(0,0); | |
| 968 | + verify_all_options(); | |
| 969 | + if( g.argc!=3 ) usage("test-fileage CHECKIN"); | |
| 970 | + mid = name_to_typed_rid(g.argv[2],"ci"); | |
| 971 | + compute_fileage(mid, zGlob); | |
| 972 | + db_prepare(&q, | |
| 973 | + "SELECT fid, mid, julianday('now') - mtime, pathname" | |
| 974 | + " FROM fileage" | |
| 975 | + ); | |
| 976 | + while( db_step(&q)==SQLITE_ROW ){ | |
| 977 | + char *zAge = human_readable_age(db_column_double(&q,2)); | |
| 978 | + fossil_print("%8d %8d %16s %s\n", | |
| 979 | + db_column_int(&q,0), | |
| 980 | + db_column_int(&q,1), | |
| 981 | + zAge, | |
| 982 | + db_column_text(&q,3)); | |
| 983 | + fossil_free(zAge); | |
| 984 | + } | |
| 985 | + db_finalize(&q); | |
| 806 | 986 | } |
| 807 | 987 | |
| 808 | 988 | /* |
| 809 | 989 | ** WEBPAGE: fileage |
| 810 | 990 | ** |
| @@ -814,72 +994,94 @@ | ||
| 814 | 994 | ** (e.g. *.c or *.txt). |
| 815 | 995 | */ |
| 816 | 996 | void fileage_page(void){ |
| 817 | 997 | int rid; |
| 818 | 998 | const char *zName; |
| 819 | - char *zBaseTime; | |
| 820 | 999 | const char *zGlob; |
| 821 | - Stmt q; | |
| 1000 | + const char *zUuid; | |
| 1001 | + const char *zNow; /* Time of checkin */ | |
| 1002 | + Stmt q1, q2; | |
| 822 | 1003 | double baseTime; |
| 823 | - int lastMid = -1; | |
| 824 | 1004 | login_check_credentials(); |
| 825 | 1005 | if( !g.perm.Read ){ login_needed(); return; } |
| 826 | 1006 | zName = P("name"); |
| 827 | 1007 | if( zName==0 ) zName = "tip"; |
| 828 | 1008 | rid = symbolic_name_to_rid(zName, "ci"); |
| 829 | 1009 | if( rid==0 ){ |
| 830 | 1010 | fossil_fatal("not a valid check-in: %s", zName); |
| 831 | 1011 | } |
| 832 | - style_submenu_element("Tree-View", "Tree-View", "%R/tree?ci=%T", zName); | |
| 1012 | + zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid); | |
| 1013 | + baseTime = db_double(0.0,"SELECT mtime FROM event WHERE objid=%d", rid); | |
| 1014 | + zNow = db_text("", "SELECT datetime(mtime,'localtime') FROM event" | |
| 1015 | + " WHERE objid=%d", rid); | |
| 1016 | + style_submenu_element("Tree-View", "Tree-View", "%R/tree?ci=%T&mtime=1", | |
| 1017 | + zName); | |
| 833 | 1018 | style_header("File Ages"); |
| 834 | 1019 | zGlob = P("glob"); |
| 835 | 1020 | compute_fileage(rid,zGlob); |
| 836 | - baseTime = db_double(0.0, "SELECT mtime FROM event WHERE objid=%d", rid); | |
| 837 | - zBaseTime = db_text("","SELECT datetime(%.20g%s)", baseTime, timeline_utc()); | |
| 838 | - @ <h2>File Ages For Check-in | |
| 839 | - @ %z(href("%R/info?name=%T",zName))%h(zName)</a></h2> | |
| 840 | - @ | |
| 841 | - @ <p>The times given are relative to | |
| 842 | - @ %z(href("%R/timeline?c=%T",zBaseTime))%s(zBaseTime)</a>, which is the | |
| 843 | - @ check-in time for | |
| 844 | - @ %z(href("%R/info?name=%T",zName))%h(zName)</a></p> | |
| 845 | - @ | |
| 846 | - @ <table border=0 cellspacing=0 cellpadding=0> | |
| 847 | - db_prepare(&q, | |
| 848 | - "SELECT mtime, (SELECT uuid FROM blob WHERE rid=fid), mid, pathname" | |
| 849 | - " FROM fileage" | |
| 850 | - " ORDER BY mtime DESC, mid, pathname" | |
| 851 | - ); | |
| 852 | - while( db_step(&q)==SQLITE_ROW ){ | |
| 853 | - double age = baseTime - db_column_double(&q, 0); | |
| 854 | - int mid = db_column_int(&q, 2); | |
| 855 | - const char *zFUuid = db_column_text(&q, 1); | |
| 856 | - char zAge[200]; | |
| 857 | - if( lastMid!=mid ){ | |
| 858 | - @ <tr><td colspan=3><hr></tr> | |
| 859 | - lastMid = mid; | |
| 860 | - if( age*86400.0<120 ){ | |
| 861 | - sqlite3_snprintf(sizeof(zAge), zAge, "%d seconds", (int)(age*86400.0)); | |
| 862 | - }else if( age*1440.0<90 ){ | |
| 863 | - sqlite3_snprintf(sizeof(zAge), zAge, "%.1f minutes", age*1440.0); | |
| 864 | - }else if( age*24.0<36 ){ | |
| 865 | - sqlite3_snprintf(sizeof(zAge), zAge, "%.1f hours", age*24.0); | |
| 866 | - }else if( age<365.0 ){ | |
| 867 | - sqlite3_snprintf(sizeof(zAge), zAge, "%.1f days", age); | |
| 868 | - }else{ | |
| 869 | - sqlite3_snprintf(sizeof(zAge), zAge, "%.2f years", age/365.0); | |
| 870 | - } | |
| 871 | - }else{ | |
| 872 | - zAge[0] = 0; | |
| 873 | - } | |
| 874 | - @ <tr> | |
| 875 | - @ <td>%s(zAge) | |
| 876 | - @ <td width="25"> | |
| 877 | - @ <td>%z(href("%R/artifact/%s?ln", zFUuid))%h(db_column_text(&q, 3))</a> | |
| 878 | - @ </tr> | |
| 879 | - @ | |
| 880 | - } | |
| 881 | - @ <tr><td colspan=3><hr></tr> | |
| 882 | - @ </table> | |
| 883 | - db_finalize(&q); | |
| 1021 | + db_multi_exec("CREATE INDEX fileage_ix1 ON fileage(mid,pathname);"); | |
| 1022 | + | |
| 1023 | + @ <h2>Files in | |
| 1024 | + @ %z(href("%R/info?name=%T",zUuid))[%S(zUuid)]</a> | |
| 1025 | + if( zGlob && zGlob[0] ){ | |
| 1026 | + @ that match "%h(zGlob)" and | |
| 1027 | + } | |
| 1028 | + @ ordered by check-in time</h2> | |
| 1029 | + @ | |
| 1030 | + @ <p>Times are relative to the checkin time for | |
| 1031 | + @ %z(href("%R/ci/%s",zUuid))[%S(zUuid)]</a> which is | |
| 1032 | + @ %z(href("%R/timeline?c=%t",zNow))%s(zNow)</a>.</p> | |
| 1033 | + @ | |
| 1034 | + @ <div class='fileage'><table> | |
| 1035 | + @ <tr><th>Time</th><th>Files</th><th>Checkin</th></tr> | |
| 1036 | + db_prepare(&q1, | |
| 1037 | + "SELECT event.mtime, event.objid, blob.uuid,\n" | |
| 1038 | + " coalesce(event.ecomment,event.comment),\n" | |
| 1039 | + " coalesce(event.euser,event.user),\n" | |
| 1040 | + " coalesce((SELECT value FROM tagxref\n" | |
| 1041 | + " WHERE tagtype>0 AND tagid=%d\n" | |
| 1042 | + " AND rid=event.objid),'trunk')\n" | |
| 1043 | + " FROM event, blob\n" | |
| 1044 | + " WHERE event.objid IN (SELECT mid FROM fileage)\n" | |
| 1045 | + " AND blob.rid=event.objid\n" | |
| 1046 | + " ORDER BY event.mtime DESC;", | |
| 1047 | + TAG_BRANCH | |
| 1048 | + ); | |
| 1049 | + db_prepare(&q2, | |
| 1050 | + "SELECT blob.uuid, filename.name\n" | |
| 1051 | + " FROM fileage, blob, filename\n" | |
| 1052 | + " WHERE fileage.mid=:mid AND filename.fnid=fileage.fnid" | |
| 1053 | + " AND blob.rid=fileage.fid;" | |
| 1054 | + ); | |
| 1055 | + while( db_step(&q1)==SQLITE_ROW ){ | |
| 1056 | + double age = baseTime - db_column_double(&q1, 0); | |
| 1057 | + int mid = db_column_int(&q1, 1); | |
| 1058 | + const char *zUuid = db_column_text(&q1, 2); | |
| 1059 | + const char *zComment = db_column_text(&q1, 3); | |
| 1060 | + const char *zUser = db_column_text(&q1, 4); | |
| 1061 | + const char *zBranch = db_column_text(&q1, 5); | |
| 1062 | + char *zAge = human_readable_age(age); | |
| 1063 | + @ <tr><td>%s(zAge)</td> | |
| 1064 | + @ <td> | |
| 1065 | + db_bind_int(&q2, ":mid", mid); | |
| 1066 | + while( db_step(&q2)==SQLITE_ROW ){ | |
| 1067 | + const char *zFUuid = db_column_text(&q2,0); | |
| 1068 | + const char *zFile = db_column_text(&q2,1); | |
| 1069 | + @ %z(href("%R/artifact/%s",zFUuid))%h(zFile)</a><br> | |
| 1070 | + } | |
| 1071 | + db_reset(&q2); | |
| 1072 | + @ </td> | |
| 1073 | + @ <td> | |
| 1074 | + @ %z(href("%R/info/%s",zUuid))[%S(zUuid)]</a> | |
| 1075 | + @ %W(zComment) (user: | |
| 1076 | + @ %z(href("%R/timeline?u=%t&c=%t&nd&n=200",zUser,zUuid))%h(zUser)</a>, | |
| 1077 | + @ branch: | |
| 1078 | + @ %z(href("%R/timeline?r=%t&c=%t&nd&n=200",zBranch,zUuid))%h(zBranch)</a>) | |
| 1079 | + @ </td></tr> | |
| 1080 | + @ | |
| 1081 | + fossil_free(zAge); | |
| 1082 | + } | |
| 1083 | + @ </table></div> | |
| 1084 | + db_finalize(&q1); | |
| 1085 | + db_finalize(&q2); | |
| 884 | 1086 | style_footer(); |
| 885 | 1087 | } |
| 886 | 1088 |
| --- src/browse.c | |
| +++ src/browse.c | |
| @@ -304,89 +304,206 @@ | |
| 304 | |
| 305 | /* |
| 306 | ** A single line of the file hierarchy |
| 307 | */ |
| 308 | struct FileTreeNode { |
| 309 | FileTreeNode *pNext; /* Next line in sequence */ |
| 310 | FileTreeNode *pPrev; /* Previous line */ |
| 311 | FileTreeNode *pParent; /* Directory containing this line */ |
| 312 | char *zName; /* Name of this entry. The "tail" */ |
| 313 | char *zFullName; /* Full pathname of this entry */ |
| 314 | char *zUuid; /* SHA1 hash of this file. May be NULL. */ |
| 315 | unsigned nFullName; /* Length of zFullName */ |
| 316 | unsigned iLevel; /* Levels of parent directories */ |
| 317 | u8 isDir; /* True if there are children */ |
| 318 | u8 isLast; /* True if this is the last child of its parent */ |
| 319 | }; |
| 320 | |
| 321 | /* |
| 322 | ** A complete file hierarchy |
| 323 | */ |
| 324 | struct FileTree { |
| 325 | FileTreeNode *pFirst; /* First line of the list */ |
| 326 | FileTreeNode *pLast; /* Last line of the list */ |
| 327 | }; |
| 328 | |
| 329 | /* |
| 330 | ** Add one or more new FileTreeNodes to the FileTree object so that the |
| 331 | ** leaf object zPathname is at the end of the node list |
| 332 | */ |
| 333 | static void tree_add_node( |
| 334 | FileTree *pTree, /* Tree into which nodes are added */ |
| 335 | const char *zPath, /* The full pathname of file to add */ |
| 336 | const char *zUuid /* UUID of the file. Might be NULL. */ |
| 337 | ){ |
| 338 | int i; |
| 339 | FileTreeNode *pParent; |
| 340 | FileTreeNode *pChild; |
| 341 | |
| 342 | pChild = pTree->pLast; |
| 343 | pParent = pChild ? pChild->pParent : 0; |
| 344 | while( pParent!=0 && |
| 345 | ( strncmp(pParent->zFullName, zPath, pParent->nFullName)!=0 |
| 346 | || zPath[pParent->nFullName]!='/' ) |
| 347 | ){ |
| 348 | pChild = pParent; |
| 349 | pParent = pChild->pParent; |
| 350 | } |
| 351 | i = pParent ? pParent->nFullName+1 : 0; |
| 352 | if( pChild ) pChild->isLast = 0; |
| 353 | while( zPath[i] ){ |
| 354 | FileTreeNode *pNew; |
| 355 | int iStart = i; |
| 356 | int nByte; |
| 357 | while( zPath[i] && zPath[i]!='/' ){ i++; } |
| 358 | nByte = sizeof(*pNew) + i + 1; |
| 359 | if( zUuid!=0 && zPath[i]==0 ) nByte += UUID_SIZE+1; |
| 360 | pNew = fossil_malloc( nByte ); |
| 361 | pNew->zFullName = (char*)&pNew[1]; |
| 362 | memcpy(pNew->zFullName, zPath, i); |
| 363 | pNew->zFullName[i] = 0; |
| 364 | pNew->nFullName = i; |
| 365 | if( zUuid!=0 && zPath[i]==0 ){ |
| 366 | pNew->zUuid = pNew->zFullName + i + 1; |
| 367 | memcpy(pNew->zUuid, zUuid, UUID_SIZE+1); |
| 368 | }else{ |
| 369 | pNew->zUuid = 0; |
| 370 | } |
| 371 | pNew->zName = pNew->zFullName + iStart; |
| 372 | if( pTree->pLast ){ |
| 373 | pTree->pLast->pNext = pNew; |
| 374 | }else{ |
| 375 | pTree->pFirst = pNew; |
| 376 | } |
| 377 | pNew->pPrev = pTree->pLast; |
| 378 | pNew->pNext = 0; |
| 379 | pNew->pParent = pParent; |
| 380 | pTree->pLast = pNew; |
| 381 | pNew->iLevel = pParent ? pParent->iLevel+1 : 0; |
| 382 | pNew->isDir = zPath[i]=='/'; |
| 383 | pNew->isLast = 1; |
| 384 | while( zPath[i]=='/' ){ i++; } |
| 385 | pParent = pNew; |
| 386 | } |
| 387 | } |
| 388 | |
| 389 | /* |
| 390 | ** WEBPAGE: tree |
| 391 | ** |
| 392 | ** Query parameters: |
| @@ -394,19 +511,23 @@ | |
| 394 | ** name=PATH Directory to display. Optional |
| 395 | ** ci=LABEL Show only files in this check-in. Optional. |
| 396 | ** re=REGEXP Show only files matching REGEXP. Optional. |
| 397 | ** expand Begin with the tree fully expanded. |
| 398 | ** nofiles Show directories (folders) only. Omit files. |
| 399 | */ |
| 400 | void page_tree(void){ |
| 401 | char *zD = fossil_strdup(P("name")); |
| 402 | int nD = zD ? strlen(zD)+1 : 0; |
| 403 | const char *zCI = P("ci"); |
| 404 | int rid = 0; |
| 405 | char *zUuid = 0; |
| 406 | Blob dirname; |
| 407 | Manifest *pM = 0; |
| 408 | int nFile = 0; /* Number of files (or folders with "nofiles") */ |
| 409 | int linkTrunk = 1; /* include link to "trunk" */ |
| 410 | int linkTip = 1; /* include link to "tip" */ |
| 411 | const char *zRE; /* the value for the re=REGEXP query parameter */ |
| 412 | const char *zObjType; /* "files" by default or "folders" for "nofiles" */ |
| @@ -464,14 +585,21 @@ | |
| 464 | int trunkRid = symbolic_name_to_rid("tag:trunk", "ci"); |
| 465 | linkTrunk = trunkRid && rid != trunkRid; |
| 466 | linkTip = rid != symbolic_name_to_rid("tip", "ci"); |
| 467 | zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 468 | url_add_parameter(&sURI, "ci", zCI); |
| 469 | }else{ |
| 470 | zCI = 0; |
| 471 | } |
| 472 | } |
| 473 | |
| 474 | /* Compute the title of the page */ |
| 475 | blob_zero(&dirname); |
| 476 | if( zD ){ |
| 477 | url_add_parameter(&sURI, "name", zD); |
| @@ -483,10 +611,18 @@ | |
| 483 | }else{ |
| 484 | if( zRE ){ |
| 485 | blob_appendf(&dirname, "matching \"%s\"", zRE); |
| 486 | } |
| 487 | } |
| 488 | if( zCI ){ |
| 489 | style_submenu_element("All", "All", "%s", |
| 490 | url_render(&sURI, "ci", 0, 0, 0)); |
| 491 | if( nD==0 && !showDirOnly ){ |
| 492 | style_submenu_element("File Ages", "File Ages", "%R/fileage?name=%s", |
| @@ -499,87 +635,82 @@ | |
| 499 | } |
| 500 | if( linkTip ){ |
| 501 | style_submenu_element("Tip", "Tip", "%s", |
| 502 | url_render(&sURI, "ci", "tip", 0, 0)); |
| 503 | } |
| 504 | if( !showDirOnly ){ |
| 505 | style_submenu_element("Flat-View", "Flat-View", "%s", |
| 506 | url_render(&sURI, "type", "flat", 0, 0)); |
| 507 | } |
| 508 | |
| 509 | /* Compute the file hierarchy. |
| 510 | */ |
| 511 | if( zCI ){ |
| 512 | Stmt ins, q; |
| 513 | ManifestFile *pFile; |
| 514 | |
| 515 | db_multi_exec( |
| 516 | "CREATE TEMP TABLE filelist(" |
| 517 | " x TEXT PRIMARY KEY COLLATE nocase," |
| 518 | " uuid TEXT" |
| 519 | ") WITHOUT ROWID;" |
| 520 | ); |
| 521 | db_prepare(&ins, "INSERT OR IGNORE INTO filelist VALUES(:f,:u)"); |
| 522 | manifest_file_rewind(pM); |
| 523 | while( (pFile = manifest_file_next(pM,0))!=0 ){ |
| 524 | if( nD>0 |
| 525 | && (fossil_strncmp(pFile->zName, zD, nD-1)!=0 |
| 526 | || pFile->zName[nD-1]!='/') |
| 527 | ){ |
| 528 | continue; |
| 529 | } |
| 530 | if( pRE && re_match(pRE, (const u8*)pFile->zName, -1)==0 ) continue; |
| 531 | db_bind_text(&ins, ":f", pFile->zName); |
| 532 | db_bind_text(&ins, ":u", pFile->zUuid); |
| 533 | db_step(&ins); |
| 534 | db_reset(&ins); |
| 535 | } |
| 536 | db_finalize(&ins); |
| 537 | db_prepare(&q, "SELECT x, uuid FROM filelist ORDER BY x"); |
| 538 | while( db_step(&q)==SQLITE_ROW ){ |
| 539 | tree_add_node(&sTree, db_column_text(&q,0), db_column_text(&q,1)); |
| 540 | nFile++; |
| 541 | } |
| 542 | db_finalize(&q); |
| 543 | }else{ |
| 544 | Stmt q; |
| 545 | db_prepare(&q, "SELECT name FROM filename ORDER BY name COLLATE nocase"); |
| 546 | while( db_step(&q)==SQLITE_ROW ){ |
| 547 | const char *z = db_column_text(&q, 0); |
| 548 | if( nD>0 && (fossil_strncmp(z, zD, nD-1)!=0 || z[nD-1]!='/') ){ |
| 549 | continue; |
| 550 | } |
| 551 | if( pRE && re_match(pRE, (const u8*)z, -1)==0 ) continue; |
| 552 | tree_add_node(&sTree, z, 0); |
| 553 | nFile++; |
| 554 | } |
| 555 | db_finalize(&q); |
| 556 | } |
| 557 | |
| 558 | if( showDirOnly ){ |
| 559 | for(nFile=0, p=sTree.pFirst; p; p=p->pNext){ |
| 560 | if( p->isDir && p->nFullName>nD ) nFile++; |
| 561 | } |
| 562 | zObjType = "folders"; |
| 563 | style_submenu_element("Files","Files","%s", |
| 564 | url_render(&sURI,"nofiles",0,0,0)); |
| 565 | }else{ |
| 566 | zObjType = "files"; |
| 567 | style_submenu_element("Folders","Folders","%s", |
| 568 | url_render(&sURI,"nofiles","1",0,0)); |
| 569 | } |
| 570 | |
| 571 | if( zCI ){ |
| 572 | @ <h2>%d(nFile) %s(zObjType) of check-in |
| 573 | if( sqlite3_strnicmp(zCI, zUuid, (int)strlen(zCI))!=0 ){ |
| 574 | @ "%h(zCI)" |
| 575 | } |
| 576 | @ [%z(href("vinfo?name=%s",zUuid))%S(zUuid)</a>] %s(blob_str(&dirname))</h2> |
| 577 | }else{ |
| 578 | int n = db_int(0, "SELECT count(*) FROM plink"); |
| 579 | @ <h2>%d(nFile) %s(zObjType) from all %d(n) check-ins |
| 580 | @ %s(blob_str(&dirname))</h2> |
| 581 | } |
| 582 | |
| 583 | |
| 584 | /* Generate tree of lists. |
| 585 | ** |
| @@ -596,18 +727,33 @@ | |
| 596 | if( nD ){ |
| 597 | @ <li class="dir last"> |
| 598 | }else{ |
| 599 | @ <li class="dir subdir last"> |
| 600 | } |
| 601 | @ %z(href("%s",url_render(&sURI,"name",0,0,0)))%h(zProjectName)</a> |
| 602 | @ <ul> |
| 603 | for(p=sTree.pFirst, nDir=0; p; p=p->pNext){ |
| 604 | const char *zLastClass = p->isLast ? " last" : ""; |
| 605 | if( p->isDir ){ |
| 606 | const char *zSubdirClass = p->nFullName==nD-1 ? " subdir" : ""; |
| 607 | @ <li class="dir%s(zSubdirClass)%s(zLastClass)"> |
| 608 | @ %z(href("%s",url_render(&sURI,"name",p->zFullName,0,0)))%h(p->zName)</a> |
| 609 | if( startExpanded || p->nFullName<=nD ){ |
| 610 | @ <ul id="dir%d(nDir)"> |
| 611 | }else{ |
| 612 | @ <ul id="dir%d(nDir)" class="collapsed"> |
| 613 | } |
| @@ -614,17 +760,23 @@ | |
| 614 | nDir++; |
| 615 | }else if( !showDirOnly ){ |
| 616 | const char *zFileClass = fileext_class(p->zName); |
| 617 | char *zLink; |
| 618 | if( zCI ){ |
| 619 | zLink = href("%R/artifact/%s",p->zUuid); |
| 620 | }else{ |
| 621 | zLink = href("%R/finfo?name=%T",p->zFullName); |
| 622 | } |
| 623 | @ <li class="%z(zFileClass)%s(zLastClass)">%z(zLink)%h(p->zName)</a> |
| 624 | } |
| 625 | if( p->isLast ){ |
| 626 | int nClose = p->iLevel - (p->pNext ? p->pNext->iLevel : 0); |
| 627 | while( nClose-- > 0 ){ |
| 628 | @ </ul> |
| 629 | } |
| 630 | } |
| @@ -687,16 +839,16 @@ | |
| 687 | @ checkState(); |
| 688 | @ outer_ul.onclick = function(e){ |
| 689 | @ e = e || window.event; |
| 690 | @ var a = e.target || e.srcElement; |
| 691 | @ if( a.nodeName!='A' ) return true; |
| 692 | @ if( a.parentNode==subdir ){ |
| 693 | @ toggleAll(outer_ul); |
| 694 | @ return false; |
| 695 | @ } |
| 696 | @ if( !belowSubdir(a) ) return true; |
| 697 | @ var ul = a.nextSibling; |
| 698 | @ while( ul && ul.nodeName!='UL' ) ul = ul.nextSibling; |
| 699 | @ if( !ul ) return true; /* This is a file link, not a directory */ |
| 700 | @ toggleDir(ul); |
| 701 | @ return false; |
| 702 | @ } |
| @@ -724,87 +876,115 @@ | |
| 724 | }else{ |
| 725 | zClass = mprintf("file"); |
| 726 | } |
| 727 | return zClass; |
| 728 | } |
| 729 | |
| 730 | /* |
| 731 | ** Look at all file containing in the version "vid". Construct a |
| 732 | ** temporary table named "fileage" that contains the file-id for each |
| 733 | ** files, the pathname, the check-in where the file was added, and the |
| 734 | ** mtime on that checkin. If zGlob and *zGlob then only files matching |
| 735 | ** the given glob are computed. |
| 736 | */ |
| 737 | int compute_fileage(int vid, const char* zGlob){ |
| 738 | Manifest *pManifest; |
| 739 | ManifestFile *pFile; |
| 740 | int nFile = 0; |
| 741 | double vmtime; |
| 742 | Stmt ins; |
| 743 | Stmt q1, q2, q3; |
| 744 | Stmt upd; |
| 745 | if(zGlob && !*zGlob) zGlob = NULL; |
| 746 | db_multi_exec( |
| 747 | /*"DROP TABLE IF EXISTS temp.fileage;"*/ |
| 748 | "CREATE TEMP TABLE fileage(" |
| 749 | " fid INTEGER," |
| 750 | " mid INTEGER," |
| 751 | " mtime DATETIME," |
| 752 | " pathname TEXT" |
| 753 | ");" |
| 754 | "CREATE INDEX fileage_fid ON fileage(fid);" |
| 755 | ); |
| 756 | pManifest = manifest_get(vid, CFTYPE_MANIFEST, 0); |
| 757 | if( pManifest==0 ) return 1; |
| 758 | manifest_file_rewind(pManifest); |
| 759 | db_prepare(&ins, |
| 760 | "INSERT INTO temp.fileage(fid, pathname)" |
| 761 | " SELECT rid, :path FROM blob WHERE uuid=:uuid" |
| 762 | ); |
| 763 | while( (pFile = manifest_file_next(pManifest, 0))!=0 ){ |
| 764 | if( zGlob && sqlite3_strglob(zGlob, pFile->zName)!=0 ) continue; |
| 765 | db_bind_text(&ins, ":uuid", pFile->zUuid); |
| 766 | db_bind_text(&ins, ":path", pFile->zName); |
| 767 | db_step(&ins); |
| 768 | db_reset(&ins); |
| 769 | nFile++; |
| 770 | } |
| 771 | db_finalize(&ins); |
| 772 | manifest_destroy(pManifest); |
| 773 | db_prepare(&q1,"SELECT fid FROM mlink WHERE mid=:mid"); |
| 774 | db_prepare(&upd, "UPDATE fileage SET mid=:mid, mtime=:vmtime" |
| 775 | " WHERE fid=:fid AND mid IS NULL"); |
| 776 | db_prepare(&q2,"SELECT pid FROM plink WHERE cid=:vid AND isprim"); |
| 777 | db_prepare(&q3,"SELECT mtime FROM event WHERE objid=:vid"); |
| 778 | while( nFile>0 && vid>0 ){ |
| 779 | db_bind_int(&q3, ":vid", vid); |
| 780 | if( db_step(&q3)==SQLITE_ROW ){ |
| 781 | vmtime = db_column_double(&q3, 0); |
| 782 | }else{ |
| 783 | break; |
| 784 | } |
| 785 | db_reset(&q3); |
| 786 | db_bind_int(&q1, ":mid", vid); |
| 787 | db_bind_int(&upd, ":mid", vid); |
| 788 | db_bind_double(&upd, ":vmtime", vmtime); |
| 789 | while( db_step(&q1)==SQLITE_ROW ){ |
| 790 | db_bind_int(&upd, ":fid", db_column_int(&q1, 0)); |
| 791 | db_step(&upd); |
| 792 | nFile -= db_changes(); |
| 793 | db_reset(&upd); |
| 794 | } |
| 795 | db_reset(&q1); |
| 796 | db_bind_int(&q2, ":vid", vid); |
| 797 | if( db_step(&q2)!=SQLITE_ROW ) break; |
| 798 | vid = db_column_int(&q2, 0); |
| 799 | db_reset(&q2); |
| 800 | } |
| 801 | db_finalize(&q1); |
| 802 | db_finalize(&upd); |
| 803 | db_finalize(&q2); |
| 804 | db_finalize(&q3); |
| 805 | return 0; |
| 806 | } |
| 807 | |
| 808 | /* |
| 809 | ** WEBPAGE: fileage |
| 810 | ** |
| @@ -814,72 +994,94 @@ | |
| 814 | ** (e.g. *.c or *.txt). |
| 815 | */ |
| 816 | void fileage_page(void){ |
| 817 | int rid; |
| 818 | const char *zName; |
| 819 | char *zBaseTime; |
| 820 | const char *zGlob; |
| 821 | Stmt q; |
| 822 | double baseTime; |
| 823 | int lastMid = -1; |
| 824 | login_check_credentials(); |
| 825 | if( !g.perm.Read ){ login_needed(); return; } |
| 826 | zName = P("name"); |
| 827 | if( zName==0 ) zName = "tip"; |
| 828 | rid = symbolic_name_to_rid(zName, "ci"); |
| 829 | if( rid==0 ){ |
| 830 | fossil_fatal("not a valid check-in: %s", zName); |
| 831 | } |
| 832 | style_submenu_element("Tree-View", "Tree-View", "%R/tree?ci=%T", zName); |
| 833 | style_header("File Ages"); |
| 834 | zGlob = P("glob"); |
| 835 | compute_fileage(rid,zGlob); |
| 836 | baseTime = db_double(0.0, "SELECT mtime FROM event WHERE objid=%d", rid); |
| 837 | zBaseTime = db_text("","SELECT datetime(%.20g%s)", baseTime, timeline_utc()); |
| 838 | @ <h2>File Ages For Check-in |
| 839 | @ %z(href("%R/info?name=%T",zName))%h(zName)</a></h2> |
| 840 | @ |
| 841 | @ <p>The times given are relative to |
| 842 | @ %z(href("%R/timeline?c=%T",zBaseTime))%s(zBaseTime)</a>, which is the |
| 843 | @ check-in time for |
| 844 | @ %z(href("%R/info?name=%T",zName))%h(zName)</a></p> |
| 845 | @ |
| 846 | @ <table border=0 cellspacing=0 cellpadding=0> |
| 847 | db_prepare(&q, |
| 848 | "SELECT mtime, (SELECT uuid FROM blob WHERE rid=fid), mid, pathname" |
| 849 | " FROM fileage" |
| 850 | " ORDER BY mtime DESC, mid, pathname" |
| 851 | ); |
| 852 | while( db_step(&q)==SQLITE_ROW ){ |
| 853 | double age = baseTime - db_column_double(&q, 0); |
| 854 | int mid = db_column_int(&q, 2); |
| 855 | const char *zFUuid = db_column_text(&q, 1); |
| 856 | char zAge[200]; |
| 857 | if( lastMid!=mid ){ |
| 858 | @ <tr><td colspan=3><hr></tr> |
| 859 | lastMid = mid; |
| 860 | if( age*86400.0<120 ){ |
| 861 | sqlite3_snprintf(sizeof(zAge), zAge, "%d seconds", (int)(age*86400.0)); |
| 862 | }else if( age*1440.0<90 ){ |
| 863 | sqlite3_snprintf(sizeof(zAge), zAge, "%.1f minutes", age*1440.0); |
| 864 | }else if( age*24.0<36 ){ |
| 865 | sqlite3_snprintf(sizeof(zAge), zAge, "%.1f hours", age*24.0); |
| 866 | }else if( age<365.0 ){ |
| 867 | sqlite3_snprintf(sizeof(zAge), zAge, "%.1f days", age); |
| 868 | }else{ |
| 869 | sqlite3_snprintf(sizeof(zAge), zAge, "%.2f years", age/365.0); |
| 870 | } |
| 871 | }else{ |
| 872 | zAge[0] = 0; |
| 873 | } |
| 874 | @ <tr> |
| 875 | @ <td>%s(zAge) |
| 876 | @ <td width="25"> |
| 877 | @ <td>%z(href("%R/artifact/%s?ln", zFUuid))%h(db_column_text(&q, 3))</a> |
| 878 | @ </tr> |
| 879 | @ |
| 880 | } |
| 881 | @ <tr><td colspan=3><hr></tr> |
| 882 | @ </table> |
| 883 | db_finalize(&q); |
| 884 | style_footer(); |
| 885 | } |
| 886 |
| --- src/browse.c | |
| +++ src/browse.c | |
| @@ -304,89 +304,206 @@ | |
| 304 | |
| 305 | /* |
| 306 | ** A single line of the file hierarchy |
| 307 | */ |
| 308 | struct FileTreeNode { |
| 309 | FileTreeNode *pNext; /* Next entry in an ordered list of them all */ |
| 310 | FileTreeNode *pParent; /* Directory containing this entry */ |
| 311 | FileTreeNode *pSibling; /* Next element in the same subdirectory */ |
| 312 | FileTreeNode *pChild; /* List of child nodes */ |
| 313 | FileTreeNode *pLastChild; /* Last child on the pChild list */ |
| 314 | char *zName; /* Name of this entry. The "tail" */ |
| 315 | char *zFullName; /* Full pathname of this entry */ |
| 316 | char *zUuid; /* SHA1 hash of this file. May be NULL. */ |
| 317 | double mtime; /* Modification time for this entry */ |
| 318 | unsigned nFullName; /* Length of zFullName */ |
| 319 | unsigned iLevel; /* Levels of parent directories */ |
| 320 | }; |
| 321 | |
| 322 | /* |
| 323 | ** A complete file hierarchy |
| 324 | */ |
| 325 | struct FileTree { |
| 326 | FileTreeNode *pFirst; /* First line of the list */ |
| 327 | FileTreeNode *pLast; /* Last line of the list */ |
| 328 | FileTreeNode *pLastTop; /* Last top-level node */ |
| 329 | }; |
| 330 | |
| 331 | /* |
| 332 | ** Add one or more new FileTreeNodes to the FileTree object so that the |
| 333 | ** leaf object zPathname is at the end of the node list. |
| 334 | ** |
| 335 | ** The caller invokes this routine once for each leaf node (each file |
| 336 | ** as opposed to each directory). This routine fills in any missing |
| 337 | ** intermediate nodes automatically. |
| 338 | ** |
| 339 | ** When constructing a list of FileTreeNodes, all entries that have |
| 340 | ** a common directory prefix must be added consecutively in order for |
| 341 | ** the tree to be constructed properly. |
| 342 | */ |
| 343 | static void tree_add_node( |
| 344 | FileTree *pTree, /* Tree into which nodes are added */ |
| 345 | const char *zPath, /* The full pathname of file to add */ |
| 346 | const char *zUuid, /* UUID of the file. Might be NULL. */ |
| 347 | double mtime /* Modification time for this entry */ |
| 348 | ){ |
| 349 | int i; |
| 350 | FileTreeNode *pParent; /* Parent (directory) of the next node to insert */ |
| 351 | |
| 352 | /* Make pParent point to the most recent ancestor of zPath, or |
| 353 | ** NULL if there are no prior entires that are a container for zPath. |
| 354 | */ |
| 355 | pParent = pTree->pLast; |
| 356 | while( pParent!=0 && |
| 357 | ( strncmp(pParent->zFullName, zPath, pParent->nFullName)!=0 |
| 358 | || zPath[pParent->nFullName]!='/' ) |
| 359 | ){ |
| 360 | pParent = pParent->pParent; |
| 361 | } |
| 362 | i = pParent ? pParent->nFullName+1 : 0; |
| 363 | while( zPath[i] ){ |
| 364 | FileTreeNode *pNew; |
| 365 | int iStart = i; |
| 366 | int nByte; |
| 367 | while( zPath[i] && zPath[i]!='/' ){ i++; } |
| 368 | nByte = sizeof(*pNew) + i + 1; |
| 369 | if( zUuid!=0 && zPath[i]==0 ) nByte += UUID_SIZE+1; |
| 370 | pNew = fossil_malloc( nByte ); |
| 371 | memset(pNew, 0, sizeof(*pNew)); |
| 372 | pNew->zFullName = (char*)&pNew[1]; |
| 373 | memcpy(pNew->zFullName, zPath, i); |
| 374 | pNew->zFullName[i] = 0; |
| 375 | pNew->nFullName = i; |
| 376 | if( zUuid!=0 && zPath[i]==0 ){ |
| 377 | pNew->zUuid = pNew->zFullName + i + 1; |
| 378 | memcpy(pNew->zUuid, zUuid, UUID_SIZE+1); |
| 379 | } |
| 380 | pNew->zName = pNew->zFullName + iStart; |
| 381 | if( pTree->pLast ){ |
| 382 | pTree->pLast->pNext = pNew; |
| 383 | }else{ |
| 384 | pTree->pFirst = pNew; |
| 385 | } |
| 386 | pTree->pLast = pNew; |
| 387 | pNew->pParent = pParent; |
| 388 | if( pParent ){ |
| 389 | if( pParent->pChild ){ |
| 390 | pParent->pLastChild->pSibling = pNew; |
| 391 | }else{ |
| 392 | pParent->pChild = pNew; |
| 393 | } |
| 394 | pNew->iLevel = pParent->iLevel + 1; |
| 395 | pParent->pLastChild = pNew; |
| 396 | }else{ |
| 397 | if( pTree->pLastTop ) pTree->pLastTop->pSibling = pNew; |
| 398 | pTree->pLastTop = pNew; |
| 399 | } |
| 400 | pNew->mtime = mtime; |
| 401 | while( zPath[i]=='/' ){ i++; } |
| 402 | pParent = pNew; |
| 403 | } |
| 404 | while( pParent && pParent->pParent ){ |
| 405 | if( pParent->pParent->mtime < pParent->mtime ){ |
| 406 | pParent->pParent->mtime = pParent->mtime; |
| 407 | } |
| 408 | pParent = pParent->pParent; |
| 409 | } |
| 410 | } |
| 411 | |
| 412 | /* Comparison function for two FileTreeNode objects. Sort first by |
| 413 | ** mtime (larger numbers first) and then by zName (smaller names first). |
| 414 | ** |
| 415 | ** Return negative if pLeft<pRight. |
| 416 | ** Return positive if pLeft>pRight. |
| 417 | ** Return zero if pLeft==pRight. |
| 418 | */ |
| 419 | static int compareNodes(FileTreeNode *pLeft, FileTreeNode *pRight){ |
| 420 | if( pLeft->mtime>pRight->mtime ) return -1; |
| 421 | if( pLeft->mtime<pRight->mtime ) return +1; |
| 422 | return fossil_stricmp(pLeft->zName, pRight->zName); |
| 423 | } |
| 424 | |
| 425 | /* Merge together two sorted lists of FileTreeNode objects */ |
| 426 | static FileTreeNode *mergeNodes(FileTreeNode *pLeft, FileTreeNode *pRight){ |
| 427 | FileTreeNode *pEnd; |
| 428 | FileTreeNode base; |
| 429 | pEnd = &base; |
| 430 | while( pLeft && pRight ){ |
| 431 | if( compareNodes(pLeft,pRight)<=0 ){ |
| 432 | pEnd = pEnd->pSibling = pLeft; |
| 433 | pLeft = pLeft->pSibling; |
| 434 | }else{ |
| 435 | pEnd = pEnd->pSibling = pRight; |
| 436 | pRight = pRight->pSibling; |
| 437 | } |
| 438 | } |
| 439 | if( pLeft ){ |
| 440 | pEnd->pSibling = pLeft; |
| 441 | }else{ |
| 442 | pEnd->pSibling = pRight; |
| 443 | } |
| 444 | return base.pSibling; |
| 445 | } |
| 446 | |
| 447 | /* Sort a list of FileTreeNode objects in mtime order. */ |
| 448 | static FileTreeNode *sortNodesByMtime(FileTreeNode *p){ |
| 449 | FileTreeNode *a[30]; |
| 450 | FileTreeNode *pX; |
| 451 | int i; |
| 452 | |
| 453 | memset(a, 0, sizeof(a)); |
| 454 | while( p ){ |
| 455 | pX = p; |
| 456 | p = pX->pSibling; |
| 457 | pX->pSibling = 0; |
| 458 | for(i=0; i<count(a)-1 && a[i]!=0; i++){ |
| 459 | pX = mergeNodes(a[i], pX); |
| 460 | a[i] = 0; |
| 461 | } |
| 462 | a[i] = mergeNodes(a[i], pX); |
| 463 | } |
| 464 | pX = 0; |
| 465 | for(i=0; i<count(a); i++){ |
| 466 | pX = mergeNodes(a[i], pX); |
| 467 | } |
| 468 | return pX; |
| 469 | } |
| 470 | |
| 471 | /* Sort an entire FileTreeNode tree by mtime |
| 472 | ** |
| 473 | ** This routine invalidates the following fields: |
| 474 | ** |
| 475 | ** FileTreeNode.pLastChild |
| 476 | ** FileTreeNode.pNext |
| 477 | ** |
| 478 | ** Use relinkTree to reconnect the pNext pointers. |
| 479 | */ |
| 480 | static FileTreeNode *sortTreeByMtime(FileTreeNode *p){ |
| 481 | FileTreeNode *pX; |
| 482 | for(pX=p; pX; pX=pX->pSibling){ |
| 483 | if( pX->pChild ) pX->pChild = sortTreeByMtime(pX->pChild); |
| 484 | } |
| 485 | return sortNodesByMtime(p); |
| 486 | } |
| 487 | |
| 488 | /* Reconstruct the FileTree by reconnecting the FileTreeNode.pNext |
| 489 | ** fields in sequential order. |
| 490 | */ |
| 491 | static void relinkTree(FileTree *pTree, FileTreeNode *pRoot){ |
| 492 | while( pRoot ){ |
| 493 | if( pTree->pLast ){ |
| 494 | pTree->pLast->pNext = pRoot; |
| 495 | }else{ |
| 496 | pTree->pFirst = pRoot; |
| 497 | } |
| 498 | pTree->pLast = pRoot; |
| 499 | if( pRoot->pChild ) relinkTree(pTree, pRoot->pChild); |
| 500 | pRoot = pRoot->pSibling; |
| 501 | } |
| 502 | if( pTree->pLast ) pTree->pLast->pNext = 0; |
| 503 | } |
| 504 | |
| 505 | |
| 506 | /* |
| 507 | ** WEBPAGE: tree |
| 508 | ** |
| 509 | ** Query parameters: |
| @@ -394,19 +511,23 @@ | |
| 511 | ** name=PATH Directory to display. Optional |
| 512 | ** ci=LABEL Show only files in this check-in. Optional. |
| 513 | ** re=REGEXP Show only files matching REGEXP. Optional. |
| 514 | ** expand Begin with the tree fully expanded. |
| 515 | ** nofiles Show directories (folders) only. Omit files. |
| 516 | ** mtime Order directory elements by decreasing mtime |
| 517 | */ |
| 518 | void page_tree(void){ |
| 519 | char *zD = fossil_strdup(P("name")); |
| 520 | int nD = zD ? strlen(zD)+1 : 0; |
| 521 | const char *zCI = P("ci"); |
| 522 | int rid = 0; |
| 523 | char *zUuid = 0; |
| 524 | Blob dirname; |
| 525 | Manifest *pM = 0; |
| 526 | double rNow = 0; |
| 527 | char *zNow = 0; |
| 528 | int useMtime = atoi(PD("mtime","0")); |
| 529 | int nFile = 0; /* Number of files (or folders with "nofiles") */ |
| 530 | int linkTrunk = 1; /* include link to "trunk" */ |
| 531 | int linkTip = 1; /* include link to "tip" */ |
| 532 | const char *zRE; /* the value for the re=REGEXP query parameter */ |
| 533 | const char *zObjType; /* "files" by default or "folders" for "nofiles" */ |
| @@ -464,14 +585,21 @@ | |
| 585 | int trunkRid = symbolic_name_to_rid("tag:trunk", "ci"); |
| 586 | linkTrunk = trunkRid && rid != trunkRid; |
| 587 | linkTip = rid != symbolic_name_to_rid("tip", "ci"); |
| 588 | zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 589 | url_add_parameter(&sURI, "ci", zCI); |
| 590 | rNow = db_double(0.0, "SELECT mtime FROM event WHERE objid=%d", rid); |
| 591 | zNow = db_text("", "SELECT datetime(mtime,'localtime')" |
| 592 | " FROM event WHERE objid=%d", rid); |
| 593 | }else{ |
| 594 | zCI = 0; |
| 595 | } |
| 596 | } |
| 597 | if( zCI==0 ){ |
| 598 | rNow = db_double(0.0, "SELECT max(mtime) FROM event"); |
| 599 | zNow = db_text("", "SELECT datetime(max(mtime),'localtime') FROM event"); |
| 600 | } |
| 601 | |
| 602 | /* Compute the title of the page */ |
| 603 | blob_zero(&dirname); |
| 604 | if( zD ){ |
| 605 | url_add_parameter(&sURI, "name", zD); |
| @@ -483,10 +611,18 @@ | |
| 611 | }else{ |
| 612 | if( zRE ){ |
| 613 | blob_appendf(&dirname, "matching \"%s\"", zRE); |
| 614 | } |
| 615 | } |
| 616 | if( useMtime ){ |
| 617 | style_submenu_element("Sort By Filename","Sort By Filename", "%s", |
| 618 | url_render(&sURI, 0, 0, 0, 0)); |
| 619 | url_add_parameter(&sURI, "mtime", "1"); |
| 620 | }else{ |
| 621 | style_submenu_element("Sort By Time","Sort By Time", "%s", |
| 622 | url_render(&sURI, "mtime", "1", 0, 0)); |
| 623 | } |
| 624 | if( zCI ){ |
| 625 | style_submenu_element("All", "All", "%s", |
| 626 | url_render(&sURI, "ci", 0, 0, 0)); |
| 627 | if( nD==0 && !showDirOnly ){ |
| 628 | style_submenu_element("File Ages", "File Ages", "%R/fileage?name=%s", |
| @@ -499,87 +635,82 @@ | |
| 635 | } |
| 636 | if( linkTip ){ |
| 637 | style_submenu_element("Tip", "Tip", "%s", |
| 638 | url_render(&sURI, "ci", "tip", 0, 0)); |
| 639 | } |
| 640 | |
| 641 | /* Compute the file hierarchy. |
| 642 | */ |
| 643 | if( zCI ){ |
| 644 | Stmt q; |
| 645 | compute_fileage(rid, 0); |
| 646 | db_prepare(&q, |
| 647 | "SELECT filename.name, blob.uuid, fileage.mtime\n" |
| 648 | " FROM fileage, filename, blob\n" |
| 649 | " WHERE filename.fnid=fileage.fnid\n" |
| 650 | " AND blob.rid=fileage.fid\n" |
| 651 | " ORDER BY filename.name COLLATE nocase;" |
| 652 | ); |
| 653 | while( db_step(&q)==SQLITE_ROW ){ |
| 654 | const char *zFile = db_column_text(&q,0); |
| 655 | const char *zUuid = db_column_text(&q,1); |
| 656 | double mtime = db_column_double(&q,2); |
| 657 | if( pRE && re_match(pRE, (const unsigned char*)zFile, -1)==0 ) continue; |
| 658 | tree_add_node(&sTree, zFile, zUuid, mtime); |
| 659 | nFile++; |
| 660 | } |
| 661 | db_finalize(&q); |
| 662 | }else{ |
| 663 | Stmt q; |
| 664 | db_prepare(&q, |
| 665 | "SELECT filename.name, blob.uuid, max(event.mtime)\n" |
| 666 | " FROM filename, mlink, blob, event\n" |
| 667 | " WHERE mlink.fnid=filename.fnid\n" |
| 668 | " AND event.objid=mlink.mid\n" |
| 669 | " AND blob.rid=mlink.fid\n" |
| 670 | " GROUP BY 1 ORDER BY 1 COLLATE nocase"); |
| 671 | while( db_step(&q)==SQLITE_ROW ){ |
| 672 | const char *zName = db_column_text(&q, 0); |
| 673 | const char *zUuid = db_column_text(&q,1); |
| 674 | double mtime = db_column_double(&q,2); |
| 675 | if( nD>0 && (fossil_strncmp(zName, zD, nD-1)!=0 || zName[nD-1]!='/') ){ |
| 676 | continue; |
| 677 | } |
| 678 | if( pRE && re_match(pRE, (const u8*)zName, -1)==0 ) continue; |
| 679 | tree_add_node(&sTree, zName, zUuid, mtime); |
| 680 | nFile++; |
| 681 | } |
| 682 | db_finalize(&q); |
| 683 | } |
| 684 | |
| 685 | if( showDirOnly ){ |
| 686 | for(nFile=0, p=sTree.pFirst; p; p=p->pNext){ |
| 687 | if( p->pChild!=0 && p->nFullName>nD ) nFile++; |
| 688 | } |
| 689 | zObjType = "Folders"; |
| 690 | style_submenu_element("Files","Files","%s", |
| 691 | url_render(&sURI,"nofiles",0,0,0)); |
| 692 | }else{ |
| 693 | zObjType = "Files"; |
| 694 | style_submenu_element("Folders","Folders","%s", |
| 695 | url_render(&sURI,"nofiles","1",0,0)); |
| 696 | } |
| 697 | |
| 698 | if( zCI ){ |
| 699 | @ <h2>%s(zObjType) from |
| 700 | if( sqlite3_strnicmp(zCI, zUuid, (int)strlen(zCI))!=0 ){ |
| 701 | @ "%h(zCI)" |
| 702 | } |
| 703 | @ [%z(href("vinfo?name=%s",zUuid))%S(zUuid)</a>] %s(blob_str(&dirname)) |
| 704 | }else{ |
| 705 | int n = db_int(0, "SELECT count(*) FROM plink"); |
| 706 | @ <h2>%s(zObjType) from all %d(n) check-ins %s(blob_str(&dirname)) |
| 707 | } |
| 708 | if( useMtime ){ |
| 709 | @ sorted by modification time</h2> |
| 710 | }else{ |
| 711 | @ sorted by filename</h2> |
| 712 | } |
| 713 | |
| 714 | |
| 715 | /* Generate tree of lists. |
| 716 | ** |
| @@ -596,18 +727,33 @@ | |
| 727 | if( nD ){ |
| 728 | @ <li class="dir last"> |
| 729 | }else{ |
| 730 | @ <li class="dir subdir last"> |
| 731 | } |
| 732 | @ <div class="filetreeline"> |
| 733 | @ %z(href("%s",url_render(&sURI,"name",0,0,0)))%h(zProjectName)</a> |
| 734 | if( zNow ){ |
| 735 | @ <div class="filetreeage">%s(zNow)</div> |
| 736 | } |
| 737 | @ </div> |
| 738 | @ <ul> |
| 739 | if( useMtime ){ |
| 740 | p = sortTreeByMtime(sTree.pFirst); |
| 741 | memset(&sTree, 0, sizeof(sTree)); |
| 742 | relinkTree(&sTree, p); |
| 743 | } |
| 744 | for(p=sTree.pFirst, nDir=0; p; p=p->pNext){ |
| 745 | const char *zLastClass = p->pSibling==0 ? " last" : ""; |
| 746 | if( p->pChild ){ |
| 747 | const char *zSubdirClass = p->nFullName==nD-1 ? " subdir" : ""; |
| 748 | @ <li class="dir%s(zSubdirClass)%s(zLastClass)"><div class="filetreeline"> |
| 749 | @ %z(href("%s",url_render(&sURI,"name",p->zFullName,0,0)))%h(p->zName)</a> |
| 750 | if( p->mtime>0.0 ){ |
| 751 | char *zAge = human_readable_age(rNow - p->mtime); |
| 752 | @ <div class="filetreeage">%s(zAge)</div> |
| 753 | } |
| 754 | @ </div> |
| 755 | if( startExpanded || p->nFullName<=nD ){ |
| 756 | @ <ul id="dir%d(nDir)"> |
| 757 | }else{ |
| 758 | @ <ul id="dir%d(nDir)" class="collapsed"> |
| 759 | } |
| @@ -614,17 +760,23 @@ | |
| 760 | nDir++; |
| 761 | }else if( !showDirOnly ){ |
| 762 | const char *zFileClass = fileext_class(p->zName); |
| 763 | char *zLink; |
| 764 | if( zCI ){ |
| 765 | zLink = href("%R/artifact/%.16s",p->zUuid); |
| 766 | }else{ |
| 767 | zLink = href("%R/finfo?name=%T",p->zFullName); |
| 768 | } |
| 769 | @ <li class="%z(zFileClass)%s(zLastClass)"><div class="filetreeline"> |
| 770 | @ %z(zLink)%h(p->zName)</a> |
| 771 | if( p->mtime>0 ){ |
| 772 | char *zAge = human_readable_age(rNow - p->mtime); |
| 773 | @ <div class="filetreeage">%s(zAge)</div> |
| 774 | } |
| 775 | @ </div> |
| 776 | } |
| 777 | if( p->pSibling==0 ){ |
| 778 | int nClose = p->iLevel - (p->pNext ? p->pNext->iLevel : 0); |
| 779 | while( nClose-- > 0 ){ |
| 780 | @ </ul> |
| 781 | } |
| 782 | } |
| @@ -687,16 +839,16 @@ | |
| 839 | @ checkState(); |
| 840 | @ outer_ul.onclick = function(e){ |
| 841 | @ e = e || window.event; |
| 842 | @ var a = e.target || e.srcElement; |
| 843 | @ if( a.nodeName!='A' ) return true; |
| 844 | @ if( a.parentNode.parentNode==subdir ){ |
| 845 | @ toggleAll(outer_ul); |
| 846 | @ return false; |
| 847 | @ } |
| 848 | @ if( !belowSubdir(a) ) return true; |
| 849 | @ var ul = a.parentNode.nextSibling; |
| 850 | @ while( ul && ul.nodeName!='UL' ) ul = ul.nextSibling; |
| 851 | @ if( !ul ) return true; /* This is a file link, not a directory */ |
| 852 | @ toggleDir(ul); |
| 853 | @ return false; |
| 854 | @ } |
| @@ -724,87 +876,115 @@ | |
| 876 | }else{ |
| 877 | zClass = mprintf("file"); |
| 878 | } |
| 879 | return zClass; |
| 880 | } |
| 881 | |
| 882 | /* |
| 883 | ** SQL used to compute the age of all files in checkin :ckin whose |
| 884 | ** names match :glob |
| 885 | */ |
| 886 | static const char zComputeFileAgeSetup[] = |
| 887 | @ CREATE TABLE IF NOT EXISTS temp.fileage( |
| 888 | @ fnid INTEGER PRIMARY KEY, |
| 889 | @ fid INTEGER, |
| 890 | @ mid INTEGER, |
| 891 | @ mtime DATETIME, |
| 892 | @ pathname TEXT |
| 893 | @ ); |
| 894 | @ CREATE VIRTUAL TABLE IF NOT EXISTS temp.foci USING files_of_checkin; |
| 895 | ; |
| 896 | |
| 897 | static const char zComputeFileAgeRun[] = |
| 898 | @ WITH RECURSIVE |
| 899 | @ ckin(x) AS (VALUES(:ckin) UNION ALL |
| 900 | @ SELECT pid FROM ckin, plink WHERE cid=x AND isprim) |
| 901 | @ INSERT OR IGNORE INTO fileage(fnid, fid, mid, mtime, pathname) |
| 902 | @ SELECT mlink.fnid, mlink.fid, x, event.mtime, filename.name |
| 903 | @ FROM ckin, mlink, event, filename |
| 904 | @ WHERE mlink.mid=ckin.x |
| 905 | @ AND mlink.fnid IN (SELECT fnid FROM foci, filename |
| 906 | @ WHERE foci.checkinID=:ckin |
| 907 | @ AND filename.name=foci.filename |
| 908 | @ AND filename.name GLOB :glob) |
| 909 | @ AND filename.fnid=mlink.fnid |
| 910 | @ AND event.objid=mlink.mid; |
| 911 | ; |
| 912 | |
| 913 | |
| 914 | /* |
| 915 | ** Look at all file containing in the version "vid". Construct a |
| 916 | ** temporary table named "fileage" that contains the file-id for each |
| 917 | ** files, the pathname, the check-in where the file was added, and the |
| 918 | ** mtime on that checkin. If zGlob and *zGlob then only files matching |
| 919 | ** the given glob are computed. |
| 920 | */ |
| 921 | int compute_fileage(int vid, const char* zGlob){ |
| 922 | Stmt q; |
| 923 | db_multi_exec(zComputeFileAgeSetup /*works-like:"constant"*/); |
| 924 | db_prepare(&q, zComputeFileAgeRun /*works-like:"constant"*/); |
| 925 | db_bind_int(&q, ":ckin", vid); |
| 926 | db_bind_text(&q, ":glob", zGlob && zGlob[0] ? zGlob : "*"); |
| 927 | db_exec(&q); |
| 928 | db_finalize(&q); |
| 929 | return 0; |
| 930 | } |
| 931 | |
| 932 | /* |
| 933 | ** Render the number of days in rAge as a more human-readable time span. |
| 934 | ** Different units (seconds, minutes, hours, days, months, years) are |
| 935 | ** selected depending on the magnitude of rAge. |
| 936 | ** |
| 937 | ** The string returned is obtained from fossil_malloc() and should be |
| 938 | ** freed by the caller. |
| 939 | */ |
| 940 | char *human_readable_age(double rAge){ |
| 941 | if( rAge*86400.0<120 ){ |
| 942 | if( rAge*86400.0<1.0 ){ |
| 943 | return mprintf("current"); |
| 944 | }else{ |
| 945 | return mprintf("%d seconds", (int)(rAge*86400.0)); |
| 946 | } |
| 947 | }else if( rAge*1440.0<90 ){ |
| 948 | return mprintf("%.1f minutes", rAge*1440.0); |
| 949 | }else if( rAge*24.0<36 ){ |
| 950 | return mprintf("%.1f hours", rAge*24.0); |
| 951 | }else if( rAge<365.0 ){ |
| 952 | return mprintf("%.1f days", rAge); |
| 953 | }else{ |
| 954 | return mprintf("%.2f years", rAge/365.0); |
| 955 | } |
| 956 | } |
| 957 | |
| 958 | /* |
| 959 | ** COMMAND: test-fileage |
| 960 | ** |
| 961 | ** Usage: %fossil test-fileage CHECKIN |
| 962 | */ |
| 963 | void test_fileage_cmd(void){ |
| 964 | int mid; |
| 965 | Stmt q; |
| 966 | const char *zGlob = find_option("glob",0,1); |
| 967 | db_find_and_open_repository(0,0); |
| 968 | verify_all_options(); |
| 969 | if( g.argc!=3 ) usage("test-fileage CHECKIN"); |
| 970 | mid = name_to_typed_rid(g.argv[2],"ci"); |
| 971 | compute_fileage(mid, zGlob); |
| 972 | db_prepare(&q, |
| 973 | "SELECT fid, mid, julianday('now') - mtime, pathname" |
| 974 | " FROM fileage" |
| 975 | ); |
| 976 | while( db_step(&q)==SQLITE_ROW ){ |
| 977 | char *zAge = human_readable_age(db_column_double(&q,2)); |
| 978 | fossil_print("%8d %8d %16s %s\n", |
| 979 | db_column_int(&q,0), |
| 980 | db_column_int(&q,1), |
| 981 | zAge, |
| 982 | db_column_text(&q,3)); |
| 983 | fossil_free(zAge); |
| 984 | } |
| 985 | db_finalize(&q); |
| 986 | } |
| 987 | |
| 988 | /* |
| 989 | ** WEBPAGE: fileage |
| 990 | ** |
| @@ -814,72 +994,94 @@ | |
| 994 | ** (e.g. *.c or *.txt). |
| 995 | */ |
| 996 | void fileage_page(void){ |
| 997 | int rid; |
| 998 | const char *zName; |
| 999 | const char *zGlob; |
| 1000 | const char *zUuid; |
| 1001 | const char *zNow; /* Time of checkin */ |
| 1002 | Stmt q1, q2; |
| 1003 | double baseTime; |
| 1004 | login_check_credentials(); |
| 1005 | if( !g.perm.Read ){ login_needed(); return; } |
| 1006 | zName = P("name"); |
| 1007 | if( zName==0 ) zName = "tip"; |
| 1008 | rid = symbolic_name_to_rid(zName, "ci"); |
| 1009 | if( rid==0 ){ |
| 1010 | fossil_fatal("not a valid check-in: %s", zName); |
| 1011 | } |
| 1012 | zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 1013 | baseTime = db_double(0.0,"SELECT mtime FROM event WHERE objid=%d", rid); |
| 1014 | zNow = db_text("", "SELECT datetime(mtime,'localtime') FROM event" |
| 1015 | " WHERE objid=%d", rid); |
| 1016 | style_submenu_element("Tree-View", "Tree-View", "%R/tree?ci=%T&mtime=1", |
| 1017 | zName); |
| 1018 | style_header("File Ages"); |
| 1019 | zGlob = P("glob"); |
| 1020 | compute_fileage(rid,zGlob); |
| 1021 | db_multi_exec("CREATE INDEX fileage_ix1 ON fileage(mid,pathname);"); |
| 1022 | |
| 1023 | @ <h2>Files in |
| 1024 | @ %z(href("%R/info?name=%T",zUuid))[%S(zUuid)]</a> |
| 1025 | if( zGlob && zGlob[0] ){ |
| 1026 | @ that match "%h(zGlob)" and |
| 1027 | } |
| 1028 | @ ordered by check-in time</h2> |
| 1029 | @ |
| 1030 | @ <p>Times are relative to the checkin time for |
| 1031 | @ %z(href("%R/ci/%s",zUuid))[%S(zUuid)]</a> which is |
| 1032 | @ %z(href("%R/timeline?c=%t",zNow))%s(zNow)</a>.</p> |
| 1033 | @ |
| 1034 | @ <div class='fileage'><table> |
| 1035 | @ <tr><th>Time</th><th>Files</th><th>Checkin</th></tr> |
| 1036 | db_prepare(&q1, |
| 1037 | "SELECT event.mtime, event.objid, blob.uuid,\n" |
| 1038 | " coalesce(event.ecomment,event.comment),\n" |
| 1039 | " coalesce(event.euser,event.user),\n" |
| 1040 | " coalesce((SELECT value FROM tagxref\n" |
| 1041 | " WHERE tagtype>0 AND tagid=%d\n" |
| 1042 | " AND rid=event.objid),'trunk')\n" |
| 1043 | " FROM event, blob\n" |
| 1044 | " WHERE event.objid IN (SELECT mid FROM fileage)\n" |
| 1045 | " AND blob.rid=event.objid\n" |
| 1046 | " ORDER BY event.mtime DESC;", |
| 1047 | TAG_BRANCH |
| 1048 | ); |
| 1049 | db_prepare(&q2, |
| 1050 | "SELECT blob.uuid, filename.name\n" |
| 1051 | " FROM fileage, blob, filename\n" |
| 1052 | " WHERE fileage.mid=:mid AND filename.fnid=fileage.fnid" |
| 1053 | " AND blob.rid=fileage.fid;" |
| 1054 | ); |
| 1055 | while( db_step(&q1)==SQLITE_ROW ){ |
| 1056 | double age = baseTime - db_column_double(&q1, 0); |
| 1057 | int mid = db_column_int(&q1, 1); |
| 1058 | const char *zUuid = db_column_text(&q1, 2); |
| 1059 | const char *zComment = db_column_text(&q1, 3); |
| 1060 | const char *zUser = db_column_text(&q1, 4); |
| 1061 | const char *zBranch = db_column_text(&q1, 5); |
| 1062 | char *zAge = human_readable_age(age); |
| 1063 | @ <tr><td>%s(zAge)</td> |
| 1064 | @ <td> |
| 1065 | db_bind_int(&q2, ":mid", mid); |
| 1066 | while( db_step(&q2)==SQLITE_ROW ){ |
| 1067 | const char *zFUuid = db_column_text(&q2,0); |
| 1068 | const char *zFile = db_column_text(&q2,1); |
| 1069 | @ %z(href("%R/artifact/%s",zFUuid))%h(zFile)</a><br> |
| 1070 | } |
| 1071 | db_reset(&q2); |
| 1072 | @ </td> |
| 1073 | @ <td> |
| 1074 | @ %z(href("%R/info/%s",zUuid))[%S(zUuid)]</a> |
| 1075 | @ %W(zComment) (user: |
| 1076 | @ %z(href("%R/timeline?u=%t&c=%t&nd&n=200",zUser,zUuid))%h(zUser)</a>, |
| 1077 | @ branch: |
| 1078 | @ %z(href("%R/timeline?r=%t&c=%t&nd&n=200",zBranch,zUuid))%h(zBranch)</a>) |
| 1079 | @ </td></tr> |
| 1080 | @ |
| 1081 | fossil_free(zAge); |
| 1082 | } |
| 1083 | @ </table></div> |
| 1084 | db_finalize(&q1); |
| 1085 | db_finalize(&q2); |
| 1086 | style_footer(); |
| 1087 | } |
| 1088 |
+1
-3
| --- src/cgi.c | ||
| +++ src/cgi.c | ||
| @@ -342,13 +342,11 @@ | ||
| 342 | 342 | ** case of most /getfile calls for specific versions, the only way the |
| 343 | 343 | ** content changes is if someone breaks the SCM. And if that happens, a |
| 344 | 344 | ** stale cache is the least of the problem. So we provide an Expires |
| 345 | 345 | ** header set to a reasonable period (default: one week). |
| 346 | 346 | */ |
| 347 | - /*time_t expires = time(0) + atoi(db_config("constant_expires","604800"));*/ | |
| 348 | - time_t expires = time(0) + 604800; | |
| 349 | - fprintf(g.httpOut, "Expires: %s\r\n", cgi_rfc822_datestamp(expires)); | |
| 347 | + fprintf(g.httpOut, "Cache-control: max-age=28800\r\n"); | |
| 350 | 348 | }else{ |
| 351 | 349 | fprintf(g.httpOut, "Cache-control: no-cache\r\n"); |
| 352 | 350 | } |
| 353 | 351 | |
| 354 | 352 | /* Content intended for logged in users should only be cached in |
| 355 | 353 |
| --- src/cgi.c | |
| +++ src/cgi.c | |
| @@ -342,13 +342,11 @@ | |
| 342 | ** case of most /getfile calls for specific versions, the only way the |
| 343 | ** content changes is if someone breaks the SCM. And if that happens, a |
| 344 | ** stale cache is the least of the problem. So we provide an Expires |
| 345 | ** header set to a reasonable period (default: one week). |
| 346 | */ |
| 347 | /*time_t expires = time(0) + atoi(db_config("constant_expires","604800"));*/ |
| 348 | time_t expires = time(0) + 604800; |
| 349 | fprintf(g.httpOut, "Expires: %s\r\n", cgi_rfc822_datestamp(expires)); |
| 350 | }else{ |
| 351 | fprintf(g.httpOut, "Cache-control: no-cache\r\n"); |
| 352 | } |
| 353 | |
| 354 | /* Content intended for logged in users should only be cached in |
| 355 |
| --- src/cgi.c | |
| +++ src/cgi.c | |
| @@ -342,13 +342,11 @@ | |
| 342 | ** case of most /getfile calls for specific versions, the only way the |
| 343 | ** content changes is if someone breaks the SCM. And if that happens, a |
| 344 | ** stale cache is the least of the problem. So we provide an Expires |
| 345 | ** header set to a reasonable period (default: one week). |
| 346 | */ |
| 347 | fprintf(g.httpOut, "Cache-control: max-age=28800\r\n"); |
| 348 | }else{ |
| 349 | fprintf(g.httpOut, "Cache-control: no-cache\r\n"); |
| 350 | } |
| 351 | |
| 352 | /* Content intended for logged in users should only be cached in |
| 353 |
+9
-1
| --- src/checkin.c | ||
| +++ src/checkin.c | ||
| @@ -65,11 +65,11 @@ | ||
| 65 | 65 | |
| 66 | 66 | db_prepare(&q, |
| 67 | 67 | "SELECT pathname, deleted, chnged, rid, coalesce(origname!=pathname,0)" |
| 68 | 68 | " FROM vfile " |
| 69 | 69 | " WHERE is_selected(id) %s" |
| 70 | - " AND (chnged OR deleted OR rid=0 OR pathname!=origname) ORDER BY 1", | |
| 70 | + " AND (chnged OR deleted OR rid=0 OR pathname!=origname) ORDER BY 1 /*scan*/", | |
| 71 | 71 | blob_sql_text(&where) |
| 72 | 72 | ); |
| 73 | 73 | blob_zero(&rewrittenPathname); |
| 74 | 74 | while( db_step(&q)==SQLITE_ROW ){ |
| 75 | 75 | const char *zPathname = db_column_text(&q,0); |
| @@ -498,10 +498,11 @@ | ||
| 498 | 498 | " ORDER BY 1", |
| 499 | 499 | fossil_all_reserved_names(0) |
| 500 | 500 | ); |
| 501 | 501 | db_multi_exec("DELETE FROM sfile WHERE x IN (SELECT pathname FROM vfile)"); |
| 502 | 502 | blob_zero(&rewrittenPathname); |
| 503 | + g.allowSymlinks = 1; /* Report on symbolic links */ | |
| 503 | 504 | while( db_step(&q)==SQLITE_ROW ){ |
| 504 | 505 | zDisplayName = zPathname = db_column_text(&q, 0); |
| 505 | 506 | if( cwdRelative ) { |
| 506 | 507 | char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname); |
| 507 | 508 | file_relative_name(zFullName, &rewrittenPathname, 0); |
| @@ -569,10 +570,11 @@ | ||
| 569 | 570 | ** argument. Matching files, if any, are removed |
| 570 | 571 | ** prior to checking for any empty directories; |
| 571 | 572 | ** therefore, directories that contain only files |
| 572 | 573 | ** that were removed will be removed as well. |
| 573 | 574 | ** -f|--force Remove files without prompting. |
| 575 | +** --verily Shorthand for: -f --emptydirs --dotfiles | |
| 574 | 576 | ** --clean <CSG> Never prompt for files matching this |
| 575 | 577 | ** comma separated list of glob patterns. |
| 576 | 578 | ** --ignore <CSG> Ignore files matching patterns from the |
| 577 | 579 | ** comma separated list of glob patterns. |
| 578 | 580 | ** --keep <CSG> Keep files matching this comma separated |
| @@ -613,10 +615,15 @@ | ||
| 613 | 615 | zIgnoreFlag = find_option("ignore",0,1); |
| 614 | 616 | verboseFlag = find_option("verbose","v",0)!=0; |
| 615 | 617 | zKeepFlag = find_option("keep",0,1); |
| 616 | 618 | zCleanFlag = find_option("clean",0,1); |
| 617 | 619 | db_must_be_within_tree(); |
| 620 | + if( find_option("verily",0,0)!=0 ){ | |
| 621 | + allFileFlag = allDirFlag = 1; | |
| 622 | + emptyDirsFlag = 1; | |
| 623 | + scanFlags |= SCAN_ALL; | |
| 624 | + } | |
| 618 | 625 | if( zIgnoreFlag==0 ){ |
| 619 | 626 | zIgnoreFlag = db_get("ignore-glob", 0); |
| 620 | 627 | } |
| 621 | 628 | if( zKeepFlag==0 ){ |
| 622 | 629 | zKeepFlag = db_get("keep-glob", 0); |
| @@ -646,10 +653,11 @@ | ||
| 646 | 653 | } |
| 647 | 654 | pIgnore = glob_create(zIgnoreFlag); |
| 648 | 655 | pKeep = glob_create(zKeepFlag); |
| 649 | 656 | pClean = glob_create(zCleanFlag); |
| 650 | 657 | nRoot = (int)strlen(g.zLocalRoot); |
| 658 | + g.allowSymlinks = 1; /* Find symlinks too */ | |
| 651 | 659 | if( !dirsOnlyFlag ){ |
| 652 | 660 | Stmt q; |
| 653 | 661 | Blob repo; |
| 654 | 662 | locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags, |
| 655 | 663 | extremeFlag ? 0 : pIgnore, 0); |
| 656 | 664 |
| --- src/checkin.c | |
| +++ src/checkin.c | |
| @@ -65,11 +65,11 @@ | |
| 65 | |
| 66 | db_prepare(&q, |
| 67 | "SELECT pathname, deleted, chnged, rid, coalesce(origname!=pathname,0)" |
| 68 | " FROM vfile " |
| 69 | " WHERE is_selected(id) %s" |
| 70 | " AND (chnged OR deleted OR rid=0 OR pathname!=origname) ORDER BY 1", |
| 71 | blob_sql_text(&where) |
| 72 | ); |
| 73 | blob_zero(&rewrittenPathname); |
| 74 | while( db_step(&q)==SQLITE_ROW ){ |
| 75 | const char *zPathname = db_column_text(&q,0); |
| @@ -498,10 +498,11 @@ | |
| 498 | " ORDER BY 1", |
| 499 | fossil_all_reserved_names(0) |
| 500 | ); |
| 501 | db_multi_exec("DELETE FROM sfile WHERE x IN (SELECT pathname FROM vfile)"); |
| 502 | blob_zero(&rewrittenPathname); |
| 503 | while( db_step(&q)==SQLITE_ROW ){ |
| 504 | zDisplayName = zPathname = db_column_text(&q, 0); |
| 505 | if( cwdRelative ) { |
| 506 | char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname); |
| 507 | file_relative_name(zFullName, &rewrittenPathname, 0); |
| @@ -569,10 +570,11 @@ | |
| 569 | ** argument. Matching files, if any, are removed |
| 570 | ** prior to checking for any empty directories; |
| 571 | ** therefore, directories that contain only files |
| 572 | ** that were removed will be removed as well. |
| 573 | ** -f|--force Remove files without prompting. |
| 574 | ** --clean <CSG> Never prompt for files matching this |
| 575 | ** comma separated list of glob patterns. |
| 576 | ** --ignore <CSG> Ignore files matching patterns from the |
| 577 | ** comma separated list of glob patterns. |
| 578 | ** --keep <CSG> Keep files matching this comma separated |
| @@ -613,10 +615,15 @@ | |
| 613 | zIgnoreFlag = find_option("ignore",0,1); |
| 614 | verboseFlag = find_option("verbose","v",0)!=0; |
| 615 | zKeepFlag = find_option("keep",0,1); |
| 616 | zCleanFlag = find_option("clean",0,1); |
| 617 | db_must_be_within_tree(); |
| 618 | if( zIgnoreFlag==0 ){ |
| 619 | zIgnoreFlag = db_get("ignore-glob", 0); |
| 620 | } |
| 621 | if( zKeepFlag==0 ){ |
| 622 | zKeepFlag = db_get("keep-glob", 0); |
| @@ -646,10 +653,11 @@ | |
| 646 | } |
| 647 | pIgnore = glob_create(zIgnoreFlag); |
| 648 | pKeep = glob_create(zKeepFlag); |
| 649 | pClean = glob_create(zCleanFlag); |
| 650 | nRoot = (int)strlen(g.zLocalRoot); |
| 651 | if( !dirsOnlyFlag ){ |
| 652 | Stmt q; |
| 653 | Blob repo; |
| 654 | locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags, |
| 655 | extremeFlag ? 0 : pIgnore, 0); |
| 656 |
| --- src/checkin.c | |
| +++ src/checkin.c | |
| @@ -65,11 +65,11 @@ | |
| 65 | |
| 66 | db_prepare(&q, |
| 67 | "SELECT pathname, deleted, chnged, rid, coalesce(origname!=pathname,0)" |
| 68 | " FROM vfile " |
| 69 | " WHERE is_selected(id) %s" |
| 70 | " AND (chnged OR deleted OR rid=0 OR pathname!=origname) ORDER BY 1 /*scan*/", |
| 71 | blob_sql_text(&where) |
| 72 | ); |
| 73 | blob_zero(&rewrittenPathname); |
| 74 | while( db_step(&q)==SQLITE_ROW ){ |
| 75 | const char *zPathname = db_column_text(&q,0); |
| @@ -498,10 +498,11 @@ | |
| 498 | " ORDER BY 1", |
| 499 | fossil_all_reserved_names(0) |
| 500 | ); |
| 501 | db_multi_exec("DELETE FROM sfile WHERE x IN (SELECT pathname FROM vfile)"); |
| 502 | blob_zero(&rewrittenPathname); |
| 503 | g.allowSymlinks = 1; /* Report on symbolic links */ |
| 504 | while( db_step(&q)==SQLITE_ROW ){ |
| 505 | zDisplayName = zPathname = db_column_text(&q, 0); |
| 506 | if( cwdRelative ) { |
| 507 | char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname); |
| 508 | file_relative_name(zFullName, &rewrittenPathname, 0); |
| @@ -569,10 +570,11 @@ | |
| 570 | ** argument. Matching files, if any, are removed |
| 571 | ** prior to checking for any empty directories; |
| 572 | ** therefore, directories that contain only files |
| 573 | ** that were removed will be removed as well. |
| 574 | ** -f|--force Remove files without prompting. |
| 575 | ** --verily Shorthand for: -f --emptydirs --dotfiles |
| 576 | ** --clean <CSG> Never prompt for files matching this |
| 577 | ** comma separated list of glob patterns. |
| 578 | ** --ignore <CSG> Ignore files matching patterns from the |
| 579 | ** comma separated list of glob patterns. |
| 580 | ** --keep <CSG> Keep files matching this comma separated |
| @@ -613,10 +615,15 @@ | |
| 615 | zIgnoreFlag = find_option("ignore",0,1); |
| 616 | verboseFlag = find_option("verbose","v",0)!=0; |
| 617 | zKeepFlag = find_option("keep",0,1); |
| 618 | zCleanFlag = find_option("clean",0,1); |
| 619 | db_must_be_within_tree(); |
| 620 | if( find_option("verily",0,0)!=0 ){ |
| 621 | allFileFlag = allDirFlag = 1; |
| 622 | emptyDirsFlag = 1; |
| 623 | scanFlags |= SCAN_ALL; |
| 624 | } |
| 625 | if( zIgnoreFlag==0 ){ |
| 626 | zIgnoreFlag = db_get("ignore-glob", 0); |
| 627 | } |
| 628 | if( zKeepFlag==0 ){ |
| 629 | zKeepFlag = db_get("keep-glob", 0); |
| @@ -646,10 +653,11 @@ | |
| 653 | } |
| 654 | pIgnore = glob_create(zIgnoreFlag); |
| 655 | pKeep = glob_create(zKeepFlag); |
| 656 | pClean = glob_create(zCleanFlag); |
| 657 | nRoot = (int)strlen(g.zLocalRoot); |
| 658 | g.allowSymlinks = 1; /* Find symlinks too */ |
| 659 | if( !dirsOnlyFlag ){ |
| 660 | Stmt q; |
| 661 | Blob repo; |
| 662 | locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags, |
| 663 | extremeFlag ? 0 : pIgnore, 0); |
| 664 |
+9
-1
| --- src/checkin.c | ||
| +++ src/checkin.c | ||
| @@ -65,11 +65,11 @@ | ||
| 65 | 65 | |
| 66 | 66 | db_prepare(&q, |
| 67 | 67 | "SELECT pathname, deleted, chnged, rid, coalesce(origname!=pathname,0)" |
| 68 | 68 | " FROM vfile " |
| 69 | 69 | " WHERE is_selected(id) %s" |
| 70 | - " AND (chnged OR deleted OR rid=0 OR pathname!=origname) ORDER BY 1", | |
| 70 | + " AND (chnged OR deleted OR rid=0 OR pathname!=origname) ORDER BY 1 /*scan*/", | |
| 71 | 71 | blob_sql_text(&where) |
| 72 | 72 | ); |
| 73 | 73 | blob_zero(&rewrittenPathname); |
| 74 | 74 | while( db_step(&q)==SQLITE_ROW ){ |
| 75 | 75 | const char *zPathname = db_column_text(&q,0); |
| @@ -498,10 +498,11 @@ | ||
| 498 | 498 | " ORDER BY 1", |
| 499 | 499 | fossil_all_reserved_names(0) |
| 500 | 500 | ); |
| 501 | 501 | db_multi_exec("DELETE FROM sfile WHERE x IN (SELECT pathname FROM vfile)"); |
| 502 | 502 | blob_zero(&rewrittenPathname); |
| 503 | + g.allowSymlinks = 1; /* Report on symbolic links */ | |
| 503 | 504 | while( db_step(&q)==SQLITE_ROW ){ |
| 504 | 505 | zDisplayName = zPathname = db_column_text(&q, 0); |
| 505 | 506 | if( cwdRelative ) { |
| 506 | 507 | char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname); |
| 507 | 508 | file_relative_name(zFullName, &rewrittenPathname, 0); |
| @@ -569,10 +570,11 @@ | ||
| 569 | 570 | ** argument. Matching files, if any, are removed |
| 570 | 571 | ** prior to checking for any empty directories; |
| 571 | 572 | ** therefore, directories that contain only files |
| 572 | 573 | ** that were removed will be removed as well. |
| 573 | 574 | ** -f|--force Remove files without prompting. |
| 575 | +** --verily Shorthand for: -f --emptydirs --dotfiles | |
| 574 | 576 | ** --clean <CSG> Never prompt for files matching this |
| 575 | 577 | ** comma separated list of glob patterns. |
| 576 | 578 | ** --ignore <CSG> Ignore files matching patterns from the |
| 577 | 579 | ** comma separated list of glob patterns. |
| 578 | 580 | ** --keep <CSG> Keep files matching this comma separated |
| @@ -613,10 +615,15 @@ | ||
| 613 | 615 | zIgnoreFlag = find_option("ignore",0,1); |
| 614 | 616 | verboseFlag = find_option("verbose","v",0)!=0; |
| 615 | 617 | zKeepFlag = find_option("keep",0,1); |
| 616 | 618 | zCleanFlag = find_option("clean",0,1); |
| 617 | 619 | db_must_be_within_tree(); |
| 620 | + if( find_option("verily",0,0)!=0 ){ | |
| 621 | + allFileFlag = allDirFlag = 1; | |
| 622 | + emptyDirsFlag = 1; | |
| 623 | + scanFlags |= SCAN_ALL; | |
| 624 | + } | |
| 618 | 625 | if( zIgnoreFlag==0 ){ |
| 619 | 626 | zIgnoreFlag = db_get("ignore-glob", 0); |
| 620 | 627 | } |
| 621 | 628 | if( zKeepFlag==0 ){ |
| 622 | 629 | zKeepFlag = db_get("keep-glob", 0); |
| @@ -646,10 +653,11 @@ | ||
| 646 | 653 | } |
| 647 | 654 | pIgnore = glob_create(zIgnoreFlag); |
| 648 | 655 | pKeep = glob_create(zKeepFlag); |
| 649 | 656 | pClean = glob_create(zCleanFlag); |
| 650 | 657 | nRoot = (int)strlen(g.zLocalRoot); |
| 658 | + g.allowSymlinks = 1; /* Find symlinks too */ | |
| 651 | 659 | if( !dirsOnlyFlag ){ |
| 652 | 660 | Stmt q; |
| 653 | 661 | Blob repo; |
| 654 | 662 | locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags, |
| 655 | 663 | extremeFlag ? 0 : pIgnore, 0); |
| 656 | 664 |
| --- src/checkin.c | |
| +++ src/checkin.c | |
| @@ -65,11 +65,11 @@ | |
| 65 | |
| 66 | db_prepare(&q, |
| 67 | "SELECT pathname, deleted, chnged, rid, coalesce(origname!=pathname,0)" |
| 68 | " FROM vfile " |
| 69 | " WHERE is_selected(id) %s" |
| 70 | " AND (chnged OR deleted OR rid=0 OR pathname!=origname) ORDER BY 1", |
| 71 | blob_sql_text(&where) |
| 72 | ); |
| 73 | blob_zero(&rewrittenPathname); |
| 74 | while( db_step(&q)==SQLITE_ROW ){ |
| 75 | const char *zPathname = db_column_text(&q,0); |
| @@ -498,10 +498,11 @@ | |
| 498 | " ORDER BY 1", |
| 499 | fossil_all_reserved_names(0) |
| 500 | ); |
| 501 | db_multi_exec("DELETE FROM sfile WHERE x IN (SELECT pathname FROM vfile)"); |
| 502 | blob_zero(&rewrittenPathname); |
| 503 | while( db_step(&q)==SQLITE_ROW ){ |
| 504 | zDisplayName = zPathname = db_column_text(&q, 0); |
| 505 | if( cwdRelative ) { |
| 506 | char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname); |
| 507 | file_relative_name(zFullName, &rewrittenPathname, 0); |
| @@ -569,10 +570,11 @@ | |
| 569 | ** argument. Matching files, if any, are removed |
| 570 | ** prior to checking for any empty directories; |
| 571 | ** therefore, directories that contain only files |
| 572 | ** that were removed will be removed as well. |
| 573 | ** -f|--force Remove files without prompting. |
| 574 | ** --clean <CSG> Never prompt for files matching this |
| 575 | ** comma separated list of glob patterns. |
| 576 | ** --ignore <CSG> Ignore files matching patterns from the |
| 577 | ** comma separated list of glob patterns. |
| 578 | ** --keep <CSG> Keep files matching this comma separated |
| @@ -613,10 +615,15 @@ | |
| 613 | zIgnoreFlag = find_option("ignore",0,1); |
| 614 | verboseFlag = find_option("verbose","v",0)!=0; |
| 615 | zKeepFlag = find_option("keep",0,1); |
| 616 | zCleanFlag = find_option("clean",0,1); |
| 617 | db_must_be_within_tree(); |
| 618 | if( zIgnoreFlag==0 ){ |
| 619 | zIgnoreFlag = db_get("ignore-glob", 0); |
| 620 | } |
| 621 | if( zKeepFlag==0 ){ |
| 622 | zKeepFlag = db_get("keep-glob", 0); |
| @@ -646,10 +653,11 @@ | |
| 646 | } |
| 647 | pIgnore = glob_create(zIgnoreFlag); |
| 648 | pKeep = glob_create(zKeepFlag); |
| 649 | pClean = glob_create(zCleanFlag); |
| 650 | nRoot = (int)strlen(g.zLocalRoot); |
| 651 | if( !dirsOnlyFlag ){ |
| 652 | Stmt q; |
| 653 | Blob repo; |
| 654 | locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags, |
| 655 | extremeFlag ? 0 : pIgnore, 0); |
| 656 |
| --- src/checkin.c | |
| +++ src/checkin.c | |
| @@ -65,11 +65,11 @@ | |
| 65 | |
| 66 | db_prepare(&q, |
| 67 | "SELECT pathname, deleted, chnged, rid, coalesce(origname!=pathname,0)" |
| 68 | " FROM vfile " |
| 69 | " WHERE is_selected(id) %s" |
| 70 | " AND (chnged OR deleted OR rid=0 OR pathname!=origname) ORDER BY 1 /*scan*/", |
| 71 | blob_sql_text(&where) |
| 72 | ); |
| 73 | blob_zero(&rewrittenPathname); |
| 74 | while( db_step(&q)==SQLITE_ROW ){ |
| 75 | const char *zPathname = db_column_text(&q,0); |
| @@ -498,10 +498,11 @@ | |
| 498 | " ORDER BY 1", |
| 499 | fossil_all_reserved_names(0) |
| 500 | ); |
| 501 | db_multi_exec("DELETE FROM sfile WHERE x IN (SELECT pathname FROM vfile)"); |
| 502 | blob_zero(&rewrittenPathname); |
| 503 | g.allowSymlinks = 1; /* Report on symbolic links */ |
| 504 | while( db_step(&q)==SQLITE_ROW ){ |
| 505 | zDisplayName = zPathname = db_column_text(&q, 0); |
| 506 | if( cwdRelative ) { |
| 507 | char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname); |
| 508 | file_relative_name(zFullName, &rewrittenPathname, 0); |
| @@ -569,10 +570,11 @@ | |
| 570 | ** argument. Matching files, if any, are removed |
| 571 | ** prior to checking for any empty directories; |
| 572 | ** therefore, directories that contain only files |
| 573 | ** that were removed will be removed as well. |
| 574 | ** -f|--force Remove files without prompting. |
| 575 | ** --verily Shorthand for: -f --emptydirs --dotfiles |
| 576 | ** --clean <CSG> Never prompt for files matching this |
| 577 | ** comma separated list of glob patterns. |
| 578 | ** --ignore <CSG> Ignore files matching patterns from the |
| 579 | ** comma separated list of glob patterns. |
| 580 | ** --keep <CSG> Keep files matching this comma separated |
| @@ -613,10 +615,15 @@ | |
| 615 | zIgnoreFlag = find_option("ignore",0,1); |
| 616 | verboseFlag = find_option("verbose","v",0)!=0; |
| 617 | zKeepFlag = find_option("keep",0,1); |
| 618 | zCleanFlag = find_option("clean",0,1); |
| 619 | db_must_be_within_tree(); |
| 620 | if( find_option("verily",0,0)!=0 ){ |
| 621 | allFileFlag = allDirFlag = 1; |
| 622 | emptyDirsFlag = 1; |
| 623 | scanFlags |= SCAN_ALL; |
| 624 | } |
| 625 | if( zIgnoreFlag==0 ){ |
| 626 | zIgnoreFlag = db_get("ignore-glob", 0); |
| 627 | } |
| 628 | if( zKeepFlag==0 ){ |
| 629 | zKeepFlag = db_get("keep-glob", 0); |
| @@ -646,10 +653,11 @@ | |
| 653 | } |
| 654 | pIgnore = glob_create(zIgnoreFlag); |
| 655 | pKeep = glob_create(zKeepFlag); |
| 656 | pClean = glob_create(zCleanFlag); |
| 657 | nRoot = (int)strlen(g.zLocalRoot); |
| 658 | g.allowSymlinks = 1; /* Find symlinks too */ |
| 659 | if( !dirsOnlyFlag ){ |
| 660 | Stmt q; |
| 661 | Blob repo; |
| 662 | locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags, |
| 663 | extremeFlag ? 0 : pIgnore, 0); |
| 664 |
+1
-2
| --- src/checkout.c | ||
| +++ src/checkout.c | ||
| @@ -305,12 +305,11 @@ | ||
| 305 | 305 | |
| 306 | 306 | if( !forceFlag && unsaved_changes(0) ){ |
| 307 | 307 | fossil_fatal("there are unsaved changes in the current checkout"); |
| 308 | 308 | } |
| 309 | 309 | if( !forceFlag |
| 310 | - && db_exists("SELECT 1 FROM %s.sqlite_master WHERE name='stash'", | |
| 311 | - db_name("localdb")) | |
| 310 | + && db_table_exists("localdb","stash") | |
| 312 | 311 | && db_exists("SELECT 1 FROM %s.stash", db_name("localdb")) |
| 313 | 312 | ){ |
| 314 | 313 | fossil_fatal("closing the checkout will delete your stash"); |
| 315 | 314 | } |
| 316 | 315 | if( db_is_writeable("repository") ){ |
| 317 | 316 |
| --- src/checkout.c | |
| +++ src/checkout.c | |
| @@ -305,12 +305,11 @@ | |
| 305 | |
| 306 | if( !forceFlag && unsaved_changes(0) ){ |
| 307 | fossil_fatal("there are unsaved changes in the current checkout"); |
| 308 | } |
| 309 | if( !forceFlag |
| 310 | && db_exists("SELECT 1 FROM %s.sqlite_master WHERE name='stash'", |
| 311 | db_name("localdb")) |
| 312 | && db_exists("SELECT 1 FROM %s.stash", db_name("localdb")) |
| 313 | ){ |
| 314 | fossil_fatal("closing the checkout will delete your stash"); |
| 315 | } |
| 316 | if( db_is_writeable("repository") ){ |
| 317 |
| --- src/checkout.c | |
| +++ src/checkout.c | |
| @@ -305,12 +305,11 @@ | |
| 305 | |
| 306 | if( !forceFlag && unsaved_changes(0) ){ |
| 307 | fossil_fatal("there are unsaved changes in the current checkout"); |
| 308 | } |
| 309 | if( !forceFlag |
| 310 | && db_table_exists("localdb","stash") |
| 311 | && db_exists("SELECT 1 FROM %s.stash", db_name("localdb")) |
| 312 | ){ |
| 313 | fossil_fatal("closing the checkout will delete your stash"); |
| 314 | } |
| 315 | if( db_is_writeable("repository") ){ |
| 316 |
+7
-4
| --- src/clone.c | ||
| +++ src/clone.c | ||
| @@ -110,23 +110,26 @@ | ||
| 110 | 110 | ** --once Don't save url. |
| 111 | 111 | ** --private Also clone private branches |
| 112 | 112 | ** --ssl-identity=filename Use the SSL identity if requested by the server |
| 113 | 113 | ** --ssh-command|-c 'command' Use this SSH command |
| 114 | 114 | ** --httpauth|-B 'user:pass' Add HTTP Basic Authorization to requests |
| 115 | +** --verbose Show more statistics in output | |
| 115 | 116 | ** |
| 116 | 117 | ** See also: init |
| 117 | 118 | */ |
| 118 | 119 | void clone_cmd(void){ |
| 119 | 120 | char *zPassword; |
| 120 | 121 | const char *zDefaultUser; /* Optional name of the default user */ |
| 121 | 122 | const char *zHttpAuth; /* HTTP Authorization user:pass information */ |
| 122 | 123 | int nErr = 0; |
| 123 | - int bPrivate = 0; /* Also clone private branches */ | |
| 124 | 124 | int urlFlags = URL_PROMPT_PW | URL_REMEMBER; |
| 125 | + int syncFlags = SYNC_CLONE; | |
| 125 | 126 | |
| 126 | - if( find_option("private",0,0)!=0 ) bPrivate = SYNC_PRIVATE; | |
| 127 | + /* Also clone private branches */ | |
| 128 | + if( find_option("private",0,0)!=0 ) syncFlags |= SYNC_PRIVATE; | |
| 127 | 129 | if( find_option("once",0,0)!=0) urlFlags &= ~URL_REMEMBER; |
| 130 | + if( find_option("verbose",0,0)!=0) syncFlags |= SYNC_VERBOSE; | |
| 128 | 131 | zHttpAuth = find_option("httpauth","B",1); |
| 129 | 132 | zDefaultUser = find_option("admin-user","A",1); |
| 130 | 133 | clone_ssh_find_options(); |
| 131 | 134 | url_proxy_options(); |
| 132 | 135 | |
| @@ -147,11 +150,11 @@ | ||
| 147 | 150 | file_copy(g.url.name, g.argv[3]); |
| 148 | 151 | db_close(1); |
| 149 | 152 | db_open_repository(g.argv[3]); |
| 150 | 153 | db_record_repository_filename(g.argv[3]); |
| 151 | 154 | url_remember(); |
| 152 | - if( !bPrivate ) delete_private_content(); | |
| 155 | + if( !(syncFlags & SYNC_PRIVATE) ) delete_private_content(); | |
| 153 | 156 | shun_artifacts(); |
| 154 | 157 | db_create_default_users(1, zDefaultUser); |
| 155 | 158 | if( zDefaultUser ){ |
| 156 | 159 | g.zLogin = zDefaultUser; |
| 157 | 160 | }else{ |
| @@ -184,11 +187,11 @@ | ||
| 184 | 187 | ); |
| 185 | 188 | url_enable_proxy(0); |
| 186 | 189 | clone_ssh_db_set_options(); |
| 187 | 190 | url_get_password_if_needed(); |
| 188 | 191 | g.xlinkClusterOnly = 1; |
| 189 | - nErr = client_sync(SYNC_CLONE | bPrivate,CONFIGSET_ALL,0); | |
| 192 | + nErr = client_sync(syncFlags,CONFIGSET_ALL,0); | |
| 190 | 193 | g.xlinkClusterOnly = 0; |
| 191 | 194 | verify_cancel(); |
| 192 | 195 | db_end_transaction(0); |
| 193 | 196 | db_close(1); |
| 194 | 197 | if( nErr ){ |
| 195 | 198 |
| --- src/clone.c | |
| +++ src/clone.c | |
| @@ -110,23 +110,26 @@ | |
| 110 | ** --once Don't save url. |
| 111 | ** --private Also clone private branches |
| 112 | ** --ssl-identity=filename Use the SSL identity if requested by the server |
| 113 | ** --ssh-command|-c 'command' Use this SSH command |
| 114 | ** --httpauth|-B 'user:pass' Add HTTP Basic Authorization to requests |
| 115 | ** |
| 116 | ** See also: init |
| 117 | */ |
| 118 | void clone_cmd(void){ |
| 119 | char *zPassword; |
| 120 | const char *zDefaultUser; /* Optional name of the default user */ |
| 121 | const char *zHttpAuth; /* HTTP Authorization user:pass information */ |
| 122 | int nErr = 0; |
| 123 | int bPrivate = 0; /* Also clone private branches */ |
| 124 | int urlFlags = URL_PROMPT_PW | URL_REMEMBER; |
| 125 | |
| 126 | if( find_option("private",0,0)!=0 ) bPrivate = SYNC_PRIVATE; |
| 127 | if( find_option("once",0,0)!=0) urlFlags &= ~URL_REMEMBER; |
| 128 | zHttpAuth = find_option("httpauth","B",1); |
| 129 | zDefaultUser = find_option("admin-user","A",1); |
| 130 | clone_ssh_find_options(); |
| 131 | url_proxy_options(); |
| 132 | |
| @@ -147,11 +150,11 @@ | |
| 147 | file_copy(g.url.name, g.argv[3]); |
| 148 | db_close(1); |
| 149 | db_open_repository(g.argv[3]); |
| 150 | db_record_repository_filename(g.argv[3]); |
| 151 | url_remember(); |
| 152 | if( !bPrivate ) delete_private_content(); |
| 153 | shun_artifacts(); |
| 154 | db_create_default_users(1, zDefaultUser); |
| 155 | if( zDefaultUser ){ |
| 156 | g.zLogin = zDefaultUser; |
| 157 | }else{ |
| @@ -184,11 +187,11 @@ | |
| 184 | ); |
| 185 | url_enable_proxy(0); |
| 186 | clone_ssh_db_set_options(); |
| 187 | url_get_password_if_needed(); |
| 188 | g.xlinkClusterOnly = 1; |
| 189 | nErr = client_sync(SYNC_CLONE | bPrivate,CONFIGSET_ALL,0); |
| 190 | g.xlinkClusterOnly = 0; |
| 191 | verify_cancel(); |
| 192 | db_end_transaction(0); |
| 193 | db_close(1); |
| 194 | if( nErr ){ |
| 195 |
| --- src/clone.c | |
| +++ src/clone.c | |
| @@ -110,23 +110,26 @@ | |
| 110 | ** --once Don't save url. |
| 111 | ** --private Also clone private branches |
| 112 | ** --ssl-identity=filename Use the SSL identity if requested by the server |
| 113 | ** --ssh-command|-c 'command' Use this SSH command |
| 114 | ** --httpauth|-B 'user:pass' Add HTTP Basic Authorization to requests |
| 115 | ** --verbose Show more statistics in output |
| 116 | ** |
| 117 | ** See also: init |
| 118 | */ |
| 119 | void clone_cmd(void){ |
| 120 | char *zPassword; |
| 121 | const char *zDefaultUser; /* Optional name of the default user */ |
| 122 | const char *zHttpAuth; /* HTTP Authorization user:pass information */ |
| 123 | int nErr = 0; |
| 124 | int urlFlags = URL_PROMPT_PW | URL_REMEMBER; |
| 125 | int syncFlags = SYNC_CLONE; |
| 126 | |
| 127 | /* Also clone private branches */ |
| 128 | if( find_option("private",0,0)!=0 ) syncFlags |= SYNC_PRIVATE; |
| 129 | if( find_option("once",0,0)!=0) urlFlags &= ~URL_REMEMBER; |
| 130 | if( find_option("verbose",0,0)!=0) syncFlags |= SYNC_VERBOSE; |
| 131 | zHttpAuth = find_option("httpauth","B",1); |
| 132 | zDefaultUser = find_option("admin-user","A",1); |
| 133 | clone_ssh_find_options(); |
| 134 | url_proxy_options(); |
| 135 | |
| @@ -147,11 +150,11 @@ | |
| 150 | file_copy(g.url.name, g.argv[3]); |
| 151 | db_close(1); |
| 152 | db_open_repository(g.argv[3]); |
| 153 | db_record_repository_filename(g.argv[3]); |
| 154 | url_remember(); |
| 155 | if( !(syncFlags & SYNC_PRIVATE) ) delete_private_content(); |
| 156 | shun_artifacts(); |
| 157 | db_create_default_users(1, zDefaultUser); |
| 158 | if( zDefaultUser ){ |
| 159 | g.zLogin = zDefaultUser; |
| 160 | }else{ |
| @@ -184,11 +187,11 @@ | |
| 187 | ); |
| 188 | url_enable_proxy(0); |
| 189 | clone_ssh_db_set_options(); |
| 190 | url_get_password_if_needed(); |
| 191 | g.xlinkClusterOnly = 1; |
| 192 | nErr = client_sync(syncFlags,CONFIGSET_ALL,0); |
| 193 | g.xlinkClusterOnly = 0; |
| 194 | verify_cancel(); |
| 195 | db_end_transaction(0); |
| 196 | db_close(1); |
| 197 | if( nErr ){ |
| 198 |
M
src/db.c
+29
-32
| --- src/db.c | ||
| +++ src/db.c | ||
| @@ -958,30 +958,47 @@ | ||
| 958 | 958 | g.zConfigDbType = "configdb"; |
| 959 | 959 | } |
| 960 | 960 | g.zConfigDbName = zDbName; |
| 961 | 961 | } |
| 962 | 962 | |
| 963 | +/* | |
| 964 | +** Return TRUE if zTable exists. | |
| 965 | +*/ | |
| 966 | +int db_table_exists( | |
| 967 | + const char *zDb, /* One of: NULL, "configdb", "localdb", "repository" */ | |
| 968 | + const char *zTable /* Name of table */ | |
| 969 | +){ | |
| 970 | + return sqlite3_table_column_metadata(g.db, | |
| 971 | + zDb ? db_name(zDb) : 0, zTable, 0, | |
| 972 | + 0, 0, 0, 0, 0)==SQLITE_OK; | |
| 973 | +} | |
| 974 | + | |
| 975 | +/* | |
| 976 | +** Return TRUE if zTable exists and contains column zColumn. | |
| 977 | +** Return FALSE if zTable does not exist or if zTable exists | |
| 978 | +** but lacks zColumn. | |
| 979 | +*/ | |
| 980 | +int db_table_has_column( | |
| 981 | + const char *zDb, /* One of: NULL, "config", "localdb", "repository" */ | |
| 982 | + const char *zTable, /* Name of table */ | |
| 983 | + const char *zColumn /* Name of column in table */ | |
| 984 | +){ | |
| 985 | + return sqlite3_table_column_metadata(g.db, | |
| 986 | + zDb ? db_name(zDb) : 0, zTable, zColumn, | |
| 987 | + 0, 0, 0, 0, 0)==SQLITE_OK; | |
| 988 | +} | |
| 963 | 989 | |
| 964 | 990 | /* |
| 965 | 991 | ** Returns TRUE if zTable exists in the local database but lacks column |
| 966 | 992 | ** zColumn |
| 967 | 993 | */ |
| 968 | 994 | static int db_local_table_exists_but_lacks_column( |
| 969 | 995 | const char *zTable, |
| 970 | 996 | const char *zColumn |
| 971 | 997 | ){ |
| 972 | - char *zDef = db_text(0, "SELECT sql FROM %s.sqlite_master" | |
| 973 | - " WHERE name==%Q /*scan*/", | |
| 974 | - db_name("localdb"), zTable); | |
| 975 | - int rc = 0; | |
| 976 | - if( zDef ){ | |
| 977 | - char *zPattern = mprintf("* %s *", zColumn); | |
| 978 | - rc = sqlite3_strglob(zPattern, zDef)!=0; | |
| 979 | - fossil_free(zPattern); | |
| 980 | - fossil_free(zDef); | |
| 981 | - } | |
| 982 | - return rc; | |
| 998 | + return db_table_exists(db_name("localdb"), zTable) | |
| 999 | + && !db_table_has_column(db_name("localdb"), zTable, zColumn); | |
| 983 | 1000 | } |
| 984 | 1001 | |
| 985 | 1002 | /* |
| 986 | 1003 | ** If zDbName is a valid local database file, open it and return |
| 987 | 1004 | ** true. If it is not a valid local database file, return 0. |
| @@ -1255,10 +1272,11 @@ | ||
| 1255 | 1272 | fossil_fatal("not in a local checkout"); |
| 1256 | 1273 | return; |
| 1257 | 1274 | } |
| 1258 | 1275 | db_open_or_attach(zRepo, "test_repo", 0); |
| 1259 | 1276 | db_lset("repository", blob_str(&repo)); |
| 1277 | + db_record_repository_filename(blob_str(&repo)); | |
| 1260 | 1278 | db_close(1); |
| 1261 | 1279 | } |
| 1262 | 1280 | |
| 1263 | 1281 | |
| 1264 | 1282 | /* |
| @@ -2047,31 +2065,10 @@ | ||
| 2047 | 2065 | } |
| 2048 | 2066 | void db_lset_int(const char *zName, int value){ |
| 2049 | 2067 | db_multi_exec("REPLACE INTO vvar(name,value) VALUES(%Q,%d)", zName, value); |
| 2050 | 2068 | } |
| 2051 | 2069 | |
| 2052 | -/* | |
| 2053 | -** Returns non-0 if the database (which must be open) table identified | |
| 2054 | -** by zTableName has a column named zColName (case-sensitive), else | |
| 2055 | -** returns 0. | |
| 2056 | -*/ | |
| 2057 | -int db_table_has_column(const char *zTableName, const char *zColName){ | |
| 2058 | - Stmt q = empty_Stmt; | |
| 2059 | - int rc = 0; | |
| 2060 | - db_prepare( &q, "PRAGMA table_info(%Q)", zTableName ); | |
| 2061 | - while(SQLITE_ROW == db_step(&q)){ | |
| 2062 | - /* Columns: (cid, name, type, notnull, dflt_value, pk) */ | |
| 2063 | - const char *zCol = db_column_text(&q, 1); | |
| 2064 | - if( 0==fossil_strcmp(zColName, zCol) ){ | |
| 2065 | - rc = 1; | |
| 2066 | - break; | |
| 2067 | - } | |
| 2068 | - } | |
| 2069 | - db_finalize(&q); | |
| 2070 | - return rc; | |
| 2071 | -} | |
| 2072 | - | |
| 2073 | 2070 | /* |
| 2074 | 2071 | ** Record the name of a local repository in the global_config() database. |
| 2075 | 2072 | ** The repository filename %s is recorded as an entry with a "name" field |
| 2076 | 2073 | ** of the following form: |
| 2077 | 2074 | ** |
| 2078 | 2075 |
| --- src/db.c | |
| +++ src/db.c | |
| @@ -958,30 +958,47 @@ | |
| 958 | g.zConfigDbType = "configdb"; |
| 959 | } |
| 960 | g.zConfigDbName = zDbName; |
| 961 | } |
| 962 | |
| 963 | |
| 964 | /* |
| 965 | ** Returns TRUE if zTable exists in the local database but lacks column |
| 966 | ** zColumn |
| 967 | */ |
| 968 | static int db_local_table_exists_but_lacks_column( |
| 969 | const char *zTable, |
| 970 | const char *zColumn |
| 971 | ){ |
| 972 | char *zDef = db_text(0, "SELECT sql FROM %s.sqlite_master" |
| 973 | " WHERE name==%Q /*scan*/", |
| 974 | db_name("localdb"), zTable); |
| 975 | int rc = 0; |
| 976 | if( zDef ){ |
| 977 | char *zPattern = mprintf("* %s *", zColumn); |
| 978 | rc = sqlite3_strglob(zPattern, zDef)!=0; |
| 979 | fossil_free(zPattern); |
| 980 | fossil_free(zDef); |
| 981 | } |
| 982 | return rc; |
| 983 | } |
| 984 | |
| 985 | /* |
| 986 | ** If zDbName is a valid local database file, open it and return |
| 987 | ** true. If it is not a valid local database file, return 0. |
| @@ -1255,10 +1272,11 @@ | |
| 1255 | fossil_fatal("not in a local checkout"); |
| 1256 | return; |
| 1257 | } |
| 1258 | db_open_or_attach(zRepo, "test_repo", 0); |
| 1259 | db_lset("repository", blob_str(&repo)); |
| 1260 | db_close(1); |
| 1261 | } |
| 1262 | |
| 1263 | |
| 1264 | /* |
| @@ -2047,31 +2065,10 @@ | |
| 2047 | } |
| 2048 | void db_lset_int(const char *zName, int value){ |
| 2049 | db_multi_exec("REPLACE INTO vvar(name,value) VALUES(%Q,%d)", zName, value); |
| 2050 | } |
| 2051 | |
| 2052 | /* |
| 2053 | ** Returns non-0 if the database (which must be open) table identified |
| 2054 | ** by zTableName has a column named zColName (case-sensitive), else |
| 2055 | ** returns 0. |
| 2056 | */ |
| 2057 | int db_table_has_column(const char *zTableName, const char *zColName){ |
| 2058 | Stmt q = empty_Stmt; |
| 2059 | int rc = 0; |
| 2060 | db_prepare( &q, "PRAGMA table_info(%Q)", zTableName ); |
| 2061 | while(SQLITE_ROW == db_step(&q)){ |
| 2062 | /* Columns: (cid, name, type, notnull, dflt_value, pk) */ |
| 2063 | const char *zCol = db_column_text(&q, 1); |
| 2064 | if( 0==fossil_strcmp(zColName, zCol) ){ |
| 2065 | rc = 1; |
| 2066 | break; |
| 2067 | } |
| 2068 | } |
| 2069 | db_finalize(&q); |
| 2070 | return rc; |
| 2071 | } |
| 2072 | |
| 2073 | /* |
| 2074 | ** Record the name of a local repository in the global_config() database. |
| 2075 | ** The repository filename %s is recorded as an entry with a "name" field |
| 2076 | ** of the following form: |
| 2077 | ** |
| 2078 |
| --- src/db.c | |
| +++ src/db.c | |
| @@ -958,30 +958,47 @@ | |
| 958 | g.zConfigDbType = "configdb"; |
| 959 | } |
| 960 | g.zConfigDbName = zDbName; |
| 961 | } |
| 962 | |
| 963 | /* |
| 964 | ** Return TRUE if zTable exists. |
| 965 | */ |
| 966 | int db_table_exists( |
| 967 | const char *zDb, /* One of: NULL, "configdb", "localdb", "repository" */ |
| 968 | const char *zTable /* Name of table */ |
| 969 | ){ |
| 970 | return sqlite3_table_column_metadata(g.db, |
| 971 | zDb ? db_name(zDb) : 0, zTable, 0, |
| 972 | 0, 0, 0, 0, 0)==SQLITE_OK; |
| 973 | } |
| 974 | |
| 975 | /* |
| 976 | ** Return TRUE if zTable exists and contains column zColumn. |
| 977 | ** Return FALSE if zTable does not exist or if zTable exists |
| 978 | ** but lacks zColumn. |
| 979 | */ |
| 980 | int db_table_has_column( |
| 981 | const char *zDb, /* One of: NULL, "config", "localdb", "repository" */ |
| 982 | const char *zTable, /* Name of table */ |
| 983 | const char *zColumn /* Name of column in table */ |
| 984 | ){ |
| 985 | return sqlite3_table_column_metadata(g.db, |
| 986 | zDb ? db_name(zDb) : 0, zTable, zColumn, |
| 987 | 0, 0, 0, 0, 0)==SQLITE_OK; |
| 988 | } |
| 989 | |
| 990 | /* |
| 991 | ** Returns TRUE if zTable exists in the local database but lacks column |
| 992 | ** zColumn |
| 993 | */ |
| 994 | static int db_local_table_exists_but_lacks_column( |
| 995 | const char *zTable, |
| 996 | const char *zColumn |
| 997 | ){ |
| 998 | return db_table_exists(db_name("localdb"), zTable) |
| 999 | && !db_table_has_column(db_name("localdb"), zTable, zColumn); |
| 1000 | } |
| 1001 | |
| 1002 | /* |
| 1003 | ** If zDbName is a valid local database file, open it and return |
| 1004 | ** true. If it is not a valid local database file, return 0. |
| @@ -1255,10 +1272,11 @@ | |
| 1272 | fossil_fatal("not in a local checkout"); |
| 1273 | return; |
| 1274 | } |
| 1275 | db_open_or_attach(zRepo, "test_repo", 0); |
| 1276 | db_lset("repository", blob_str(&repo)); |
| 1277 | db_record_repository_filename(blob_str(&repo)); |
| 1278 | db_close(1); |
| 1279 | } |
| 1280 | |
| 1281 | |
| 1282 | /* |
| @@ -2047,31 +2065,10 @@ | |
| 2065 | } |
| 2066 | void db_lset_int(const char *zName, int value){ |
| 2067 | db_multi_exec("REPLACE INTO vvar(name,value) VALUES(%Q,%d)", zName, value); |
| 2068 | } |
| 2069 | |
| 2070 | /* |
| 2071 | ** Record the name of a local repository in the global_config() database. |
| 2072 | ** The repository filename %s is recorded as an entry with a "name" field |
| 2073 | ** of the following form: |
| 2074 | ** |
| 2075 |
M
src/db.c
+29
-32
| --- src/db.c | ||
| +++ src/db.c | ||
| @@ -958,30 +958,47 @@ | ||
| 958 | 958 | g.zConfigDbType = "configdb"; |
| 959 | 959 | } |
| 960 | 960 | g.zConfigDbName = zDbName; |
| 961 | 961 | } |
| 962 | 962 | |
| 963 | +/* | |
| 964 | +** Return TRUE if zTable exists. | |
| 965 | +*/ | |
| 966 | +int db_table_exists( | |
| 967 | + const char *zDb, /* One of: NULL, "configdb", "localdb", "repository" */ | |
| 968 | + const char *zTable /* Name of table */ | |
| 969 | +){ | |
| 970 | + return sqlite3_table_column_metadata(g.db, | |
| 971 | + zDb ? db_name(zDb) : 0, zTable, 0, | |
| 972 | + 0, 0, 0, 0, 0)==SQLITE_OK; | |
| 973 | +} | |
| 974 | + | |
| 975 | +/* | |
| 976 | +** Return TRUE if zTable exists and contains column zColumn. | |
| 977 | +** Return FALSE if zTable does not exist or if zTable exists | |
| 978 | +** but lacks zColumn. | |
| 979 | +*/ | |
| 980 | +int db_table_has_column( | |
| 981 | + const char *zDb, /* One of: NULL, "config", "localdb", "repository" */ | |
| 982 | + const char *zTable, /* Name of table */ | |
| 983 | + const char *zColumn /* Name of column in table */ | |
| 984 | +){ | |
| 985 | + return sqlite3_table_column_metadata(g.db, | |
| 986 | + zDb ? db_name(zDb) : 0, zTable, zColumn, | |
| 987 | + 0, 0, 0, 0, 0)==SQLITE_OK; | |
| 988 | +} | |
| 963 | 989 | |
| 964 | 990 | /* |
| 965 | 991 | ** Returns TRUE if zTable exists in the local database but lacks column |
| 966 | 992 | ** zColumn |
| 967 | 993 | */ |
| 968 | 994 | static int db_local_table_exists_but_lacks_column( |
| 969 | 995 | const char *zTable, |
| 970 | 996 | const char *zColumn |
| 971 | 997 | ){ |
| 972 | - char *zDef = db_text(0, "SELECT sql FROM %s.sqlite_master" | |
| 973 | - " WHERE name==%Q /*scan*/", | |
| 974 | - db_name("localdb"), zTable); | |
| 975 | - int rc = 0; | |
| 976 | - if( zDef ){ | |
| 977 | - char *zPattern = mprintf("* %s *", zColumn); | |
| 978 | - rc = sqlite3_strglob(zPattern, zDef)!=0; | |
| 979 | - fossil_free(zPattern); | |
| 980 | - fossil_free(zDef); | |
| 981 | - } | |
| 982 | - return rc; | |
| 998 | + return db_table_exists(db_name("localdb"), zTable) | |
| 999 | + && !db_table_has_column(db_name("localdb"), zTable, zColumn); | |
| 983 | 1000 | } |
| 984 | 1001 | |
| 985 | 1002 | /* |
| 986 | 1003 | ** If zDbName is a valid local database file, open it and return |
| 987 | 1004 | ** true. If it is not a valid local database file, return 0. |
| @@ -1255,10 +1272,11 @@ | ||
| 1255 | 1272 | fossil_fatal("not in a local checkout"); |
| 1256 | 1273 | return; |
| 1257 | 1274 | } |
| 1258 | 1275 | db_open_or_attach(zRepo, "test_repo", 0); |
| 1259 | 1276 | db_lset("repository", blob_str(&repo)); |
| 1277 | + db_record_repository_filename(blob_str(&repo)); | |
| 1260 | 1278 | db_close(1); |
| 1261 | 1279 | } |
| 1262 | 1280 | |
| 1263 | 1281 | |
| 1264 | 1282 | /* |
| @@ -2047,31 +2065,10 @@ | ||
| 2047 | 2065 | } |
| 2048 | 2066 | void db_lset_int(const char *zName, int value){ |
| 2049 | 2067 | db_multi_exec("REPLACE INTO vvar(name,value) VALUES(%Q,%d)", zName, value); |
| 2050 | 2068 | } |
| 2051 | 2069 | |
| 2052 | -/* | |
| 2053 | -** Returns non-0 if the database (which must be open) table identified | |
| 2054 | -** by zTableName has a column named zColName (case-sensitive), else | |
| 2055 | -** returns 0. | |
| 2056 | -*/ | |
| 2057 | -int db_table_has_column(const char *zTableName, const char *zColName){ | |
| 2058 | - Stmt q = empty_Stmt; | |
| 2059 | - int rc = 0; | |
| 2060 | - db_prepare( &q, "PRAGMA table_info(%Q)", zTableName ); | |
| 2061 | - while(SQLITE_ROW == db_step(&q)){ | |
| 2062 | - /* Columns: (cid, name, type, notnull, dflt_value, pk) */ | |
| 2063 | - const char *zCol = db_column_text(&q, 1); | |
| 2064 | - if( 0==fossil_strcmp(zColName, zCol) ){ | |
| 2065 | - rc = 1; | |
| 2066 | - break; | |
| 2067 | - } | |
| 2068 | - } | |
| 2069 | - db_finalize(&q); | |
| 2070 | - return rc; | |
| 2071 | -} | |
| 2072 | - | |
| 2073 | 2070 | /* |
| 2074 | 2071 | ** Record the name of a local repository in the global_config() database. |
| 2075 | 2072 | ** The repository filename %s is recorded as an entry with a "name" field |
| 2076 | 2073 | ** of the following form: |
| 2077 | 2074 | ** |
| 2078 | 2075 |
| --- src/db.c | |
| +++ src/db.c | |
| @@ -958,30 +958,47 @@ | |
| 958 | g.zConfigDbType = "configdb"; |
| 959 | } |
| 960 | g.zConfigDbName = zDbName; |
| 961 | } |
| 962 | |
| 963 | |
| 964 | /* |
| 965 | ** Returns TRUE if zTable exists in the local database but lacks column |
| 966 | ** zColumn |
| 967 | */ |
| 968 | static int db_local_table_exists_but_lacks_column( |
| 969 | const char *zTable, |
| 970 | const char *zColumn |
| 971 | ){ |
| 972 | char *zDef = db_text(0, "SELECT sql FROM %s.sqlite_master" |
| 973 | " WHERE name==%Q /*scan*/", |
| 974 | db_name("localdb"), zTable); |
| 975 | int rc = 0; |
| 976 | if( zDef ){ |
| 977 | char *zPattern = mprintf("* %s *", zColumn); |
| 978 | rc = sqlite3_strglob(zPattern, zDef)!=0; |
| 979 | fossil_free(zPattern); |
| 980 | fossil_free(zDef); |
| 981 | } |
| 982 | return rc; |
| 983 | } |
| 984 | |
| 985 | /* |
| 986 | ** If zDbName is a valid local database file, open it and return |
| 987 | ** true. If it is not a valid local database file, return 0. |
| @@ -1255,10 +1272,11 @@ | |
| 1255 | fossil_fatal("not in a local checkout"); |
| 1256 | return; |
| 1257 | } |
| 1258 | db_open_or_attach(zRepo, "test_repo", 0); |
| 1259 | db_lset("repository", blob_str(&repo)); |
| 1260 | db_close(1); |
| 1261 | } |
| 1262 | |
| 1263 | |
| 1264 | /* |
| @@ -2047,31 +2065,10 @@ | |
| 2047 | } |
| 2048 | void db_lset_int(const char *zName, int value){ |
| 2049 | db_multi_exec("REPLACE INTO vvar(name,value) VALUES(%Q,%d)", zName, value); |
| 2050 | } |
| 2051 | |
| 2052 | /* |
| 2053 | ** Returns non-0 if the database (which must be open) table identified |
| 2054 | ** by zTableName has a column named zColName (case-sensitive), else |
| 2055 | ** returns 0. |
| 2056 | */ |
| 2057 | int db_table_has_column(const char *zTableName, const char *zColName){ |
| 2058 | Stmt q = empty_Stmt; |
| 2059 | int rc = 0; |
| 2060 | db_prepare( &q, "PRAGMA table_info(%Q)", zTableName ); |
| 2061 | while(SQLITE_ROW == db_step(&q)){ |
| 2062 | /* Columns: (cid, name, type, notnull, dflt_value, pk) */ |
| 2063 | const char *zCol = db_column_text(&q, 1); |
| 2064 | if( 0==fossil_strcmp(zColName, zCol) ){ |
| 2065 | rc = 1; |
| 2066 | break; |
| 2067 | } |
| 2068 | } |
| 2069 | db_finalize(&q); |
| 2070 | return rc; |
| 2071 | } |
| 2072 | |
| 2073 | /* |
| 2074 | ** Record the name of a local repository in the global_config() database. |
| 2075 | ** The repository filename %s is recorded as an entry with a "name" field |
| 2076 | ** of the following form: |
| 2077 | ** |
| 2078 |
| --- src/db.c | |
| +++ src/db.c | |
| @@ -958,30 +958,47 @@ | |
| 958 | g.zConfigDbType = "configdb"; |
| 959 | } |
| 960 | g.zConfigDbName = zDbName; |
| 961 | } |
| 962 | |
| 963 | /* |
| 964 | ** Return TRUE if zTable exists. |
| 965 | */ |
| 966 | int db_table_exists( |
| 967 | const char *zDb, /* One of: NULL, "configdb", "localdb", "repository" */ |
| 968 | const char *zTable /* Name of table */ |
| 969 | ){ |
| 970 | return sqlite3_table_column_metadata(g.db, |
| 971 | zDb ? db_name(zDb) : 0, zTable, 0, |
| 972 | 0, 0, 0, 0, 0)==SQLITE_OK; |
| 973 | } |
| 974 | |
| 975 | /* |
| 976 | ** Return TRUE if zTable exists and contains column zColumn. |
| 977 | ** Return FALSE if zTable does not exist or if zTable exists |
| 978 | ** but lacks zColumn. |
| 979 | */ |
| 980 | int db_table_has_column( |
| 981 | const char *zDb, /* One of: NULL, "config", "localdb", "repository" */ |
| 982 | const char *zTable, /* Name of table */ |
| 983 | const char *zColumn /* Name of column in table */ |
| 984 | ){ |
| 985 | return sqlite3_table_column_metadata(g.db, |
| 986 | zDb ? db_name(zDb) : 0, zTable, zColumn, |
| 987 | 0, 0, 0, 0, 0)==SQLITE_OK; |
| 988 | } |
| 989 | |
| 990 | /* |
| 991 | ** Returns TRUE if zTable exists in the local database but lacks column |
| 992 | ** zColumn |
| 993 | */ |
| 994 | static int db_local_table_exists_but_lacks_column( |
| 995 | const char *zTable, |
| 996 | const char *zColumn |
| 997 | ){ |
| 998 | return db_table_exists(db_name("localdb"), zTable) |
| 999 | && !db_table_has_column(db_name("localdb"), zTable, zColumn); |
| 1000 | } |
| 1001 | |
| 1002 | /* |
| 1003 | ** If zDbName is a valid local database file, open it and return |
| 1004 | ** true. If it is not a valid local database file, return 0. |
| @@ -1255,10 +1272,11 @@ | |
| 1272 | fossil_fatal("not in a local checkout"); |
| 1273 | return; |
| 1274 | } |
| 1275 | db_open_or_attach(zRepo, "test_repo", 0); |
| 1276 | db_lset("repository", blob_str(&repo)); |
| 1277 | db_record_repository_filename(blob_str(&repo)); |
| 1278 | db_close(1); |
| 1279 | } |
| 1280 | |
| 1281 | |
| 1282 | /* |
| @@ -2047,31 +2065,10 @@ | |
| 2065 | } |
| 2066 | void db_lset_int(const char *zName, int value){ |
| 2067 | db_multi_exec("REPLACE INTO vvar(name,value) VALUES(%Q,%d)", zName, value); |
| 2068 | } |
| 2069 | |
| 2070 | /* |
| 2071 | ** Record the name of a local repository in the global_config() database. |
| 2072 | ** The repository filename %s is recorded as an entry with a "name" field |
| 2073 | ** of the following form: |
| 2074 | ** |
| 2075 |
+2
-2
| --- src/diffcmd.c | ||
| +++ src/diffcmd.c | ||
| @@ -363,20 +363,20 @@ | ||
| 363 | 363 | "SELECT pathname, 0, 0, 1, 0, islink" |
| 364 | 364 | " FROM vfile v2" |
| 365 | 365 | " WHERE v2.vid=%d" |
| 366 | 366 | " AND NOT EXISTS(SELECT 1 FROM vfile v1" |
| 367 | 367 | " WHERE v1.vid=%d AND v1.pathname=v2.pathname)" |
| 368 | - " ORDER BY 1", | |
| 368 | + " ORDER BY 1 /*scan*/", | |
| 369 | 369 | rid, vid, rid, vid, vid, rid |
| 370 | 370 | ); |
| 371 | 371 | }else{ |
| 372 | 372 | blob_append_sql(&sql, |
| 373 | 373 | "SELECT pathname, deleted, chnged , rid==0, rid, islink" |
| 374 | 374 | " FROM vfile" |
| 375 | 375 | " WHERE vid=%d" |
| 376 | 376 | " AND (deleted OR chnged OR rid==0)" |
| 377 | - " ORDER BY pathname", | |
| 377 | + " ORDER BY pathname /*scan*/", | |
| 378 | 378 | vid |
| 379 | 379 | ); |
| 380 | 380 | } |
| 381 | 381 | db_prepare(&q, "%s", blob_sql_text(&sql)); |
| 382 | 382 | while( db_step(&q)==SQLITE_ROW ){ |
| 383 | 383 |
| --- src/diffcmd.c | |
| +++ src/diffcmd.c | |
| @@ -363,20 +363,20 @@ | |
| 363 | "SELECT pathname, 0, 0, 1, 0, islink" |
| 364 | " FROM vfile v2" |
| 365 | " WHERE v2.vid=%d" |
| 366 | " AND NOT EXISTS(SELECT 1 FROM vfile v1" |
| 367 | " WHERE v1.vid=%d AND v1.pathname=v2.pathname)" |
| 368 | " ORDER BY 1", |
| 369 | rid, vid, rid, vid, vid, rid |
| 370 | ); |
| 371 | }else{ |
| 372 | blob_append_sql(&sql, |
| 373 | "SELECT pathname, deleted, chnged , rid==0, rid, islink" |
| 374 | " FROM vfile" |
| 375 | " WHERE vid=%d" |
| 376 | " AND (deleted OR chnged OR rid==0)" |
| 377 | " ORDER BY pathname", |
| 378 | vid |
| 379 | ); |
| 380 | } |
| 381 | db_prepare(&q, "%s", blob_sql_text(&sql)); |
| 382 | while( db_step(&q)==SQLITE_ROW ){ |
| 383 |
| --- src/diffcmd.c | |
| +++ src/diffcmd.c | |
| @@ -363,20 +363,20 @@ | |
| 363 | "SELECT pathname, 0, 0, 1, 0, islink" |
| 364 | " FROM vfile v2" |
| 365 | " WHERE v2.vid=%d" |
| 366 | " AND NOT EXISTS(SELECT 1 FROM vfile v1" |
| 367 | " WHERE v1.vid=%d AND v1.pathname=v2.pathname)" |
| 368 | " ORDER BY 1 /*scan*/", |
| 369 | rid, vid, rid, vid, vid, rid |
| 370 | ); |
| 371 | }else{ |
| 372 | blob_append_sql(&sql, |
| 373 | "SELECT pathname, deleted, chnged , rid==0, rid, islink" |
| 374 | " FROM vfile" |
| 375 | " WHERE vid=%d" |
| 376 | " AND (deleted OR chnged OR rid==0)" |
| 377 | " ORDER BY pathname /*scan*/", |
| 378 | vid |
| 379 | ); |
| 380 | } |
| 381 | db_prepare(&q, "%s", blob_sql_text(&sql)); |
| 382 | while( db_step(&q)==SQLITE_ROW ){ |
| 383 |
+10
-6
| --- src/foci.c | ||
| +++ src/foci.c | ||
| @@ -46,11 +46,12 @@ | ||
| 46 | 46 | sqlite3_vtab base; /* Base class - must be first */ |
| 47 | 47 | }; |
| 48 | 48 | struct FociCursor { |
| 49 | 49 | sqlite3_vtab_cursor base; /* Base class - must be first */ |
| 50 | 50 | Manifest *pMan; /* Current manifest */ |
| 51 | - int iFile; /* Index of current file */ | |
| 51 | + ManifestFile *pFile; /* Current file */ | |
| 52 | + int iFile; /* File index */ | |
| 52 | 53 | }; |
| 53 | 54 | #endif /* INTERFACE */ |
| 54 | 55 | |
| 55 | 56 | |
| 56 | 57 | /* |
| @@ -127,17 +128,18 @@ | ||
| 127 | 128 | /* |
| 128 | 129 | ** Move a focivfs cursor to the next entry in the file. |
| 129 | 130 | */ |
| 130 | 131 | static int fociNext(sqlite3_vtab_cursor *pCursor){ |
| 131 | 132 | FociCursor *pCsr = (FociCursor *)pCursor; |
| 133 | + pCsr->pFile = manifest_file_next(pCsr->pMan, 0); | |
| 132 | 134 | pCsr->iFile++; |
| 133 | 135 | return SQLITE_OK; |
| 134 | 136 | } |
| 135 | 137 | |
| 136 | 138 | static int fociEof(sqlite3_vtab_cursor *pCursor){ |
| 137 | 139 | FociCursor *pCsr = (FociCursor *)pCursor; |
| 138 | - return pCsr->pMan==0 || pCsr->iFile>=pCsr->pMan->nFile; | |
| 140 | + return pCsr->pFile==0; | |
| 139 | 141 | } |
| 140 | 142 | |
| 141 | 143 | static int fociFilter( |
| 142 | 144 | sqlite3_vtab_cursor *pCursor, |
| 143 | 145 | int idxNum, const char *idxStr, |
| @@ -146,10 +148,12 @@ | ||
| 146 | 148 | FociCursor *pCur = (FociCursor *)pCursor; |
| 147 | 149 | manifest_destroy(pCur->pMan); |
| 148 | 150 | if( idxNum ){ |
| 149 | 151 | pCur->pMan = manifest_get(sqlite3_value_int(argv[0]), CFTYPE_MANIFEST, 0); |
| 150 | 152 | pCur->iFile = 0; |
| 153 | + manifest_file_rewind(pCur->pMan); | |
| 154 | + pCur->pFile = manifest_file_next(pCur->pMan, 0); | |
| 151 | 155 | }else{ |
| 152 | 156 | pCur->pMan = 0; |
| 153 | 157 | pCur->iFile = 0; |
| 154 | 158 | } |
| 155 | 159 | return SQLITE_OK; |
| @@ -164,23 +168,23 @@ | ||
| 164 | 168 | switch( i ){ |
| 165 | 169 | case 0: /* checkinID */ |
| 166 | 170 | sqlite3_result_int(ctx, pCsr->pMan->rid); |
| 167 | 171 | break; |
| 168 | 172 | case 1: /* filename */ |
| 169 | - sqlite3_result_text(ctx, pCsr->pMan->aFile[pCsr->iFile].zName, -1, | |
| 173 | + sqlite3_result_text(ctx, pCsr->pFile->zName, -1, | |
| 170 | 174 | SQLITE_TRANSIENT); |
| 171 | 175 | break; |
| 172 | 176 | case 2: /* uuid */ |
| 173 | - sqlite3_result_text(ctx, pCsr->pMan->aFile[pCsr->iFile].zUuid, -1, | |
| 177 | + sqlite3_result_text(ctx, pCsr->pFile->zUuid, -1, | |
| 174 | 178 | SQLITE_TRANSIENT); |
| 175 | 179 | break; |
| 176 | 180 | case 3: /* previousName */ |
| 177 | - sqlite3_result_text(ctx, pCsr->pMan->aFile[pCsr->iFile].zPrior, -1, | |
| 181 | + sqlite3_result_text(ctx, pCsr->pFile->zPrior, -1, | |
| 178 | 182 | SQLITE_TRANSIENT); |
| 179 | 183 | break; |
| 180 | 184 | case 4: /* perm */ |
| 181 | - sqlite3_result_text(ctx, pCsr->pMan->aFile[pCsr->iFile].zPerm, -1, | |
| 185 | + sqlite3_result_text(ctx, pCsr->pFile->zPerm, -1, | |
| 182 | 186 | SQLITE_TRANSIENT); |
| 183 | 187 | break; |
| 184 | 188 | } |
| 185 | 189 | return SQLITE_OK; |
| 186 | 190 | } |
| 187 | 191 |
| --- src/foci.c | |
| +++ src/foci.c | |
| @@ -46,11 +46,12 @@ | |
| 46 | sqlite3_vtab base; /* Base class - must be first */ |
| 47 | }; |
| 48 | struct FociCursor { |
| 49 | sqlite3_vtab_cursor base; /* Base class - must be first */ |
| 50 | Manifest *pMan; /* Current manifest */ |
| 51 | int iFile; /* Index of current file */ |
| 52 | }; |
| 53 | #endif /* INTERFACE */ |
| 54 | |
| 55 | |
| 56 | /* |
| @@ -127,17 +128,18 @@ | |
| 127 | /* |
| 128 | ** Move a focivfs cursor to the next entry in the file. |
| 129 | */ |
| 130 | static int fociNext(sqlite3_vtab_cursor *pCursor){ |
| 131 | FociCursor *pCsr = (FociCursor *)pCursor; |
| 132 | pCsr->iFile++; |
| 133 | return SQLITE_OK; |
| 134 | } |
| 135 | |
| 136 | static int fociEof(sqlite3_vtab_cursor *pCursor){ |
| 137 | FociCursor *pCsr = (FociCursor *)pCursor; |
| 138 | return pCsr->pMan==0 || pCsr->iFile>=pCsr->pMan->nFile; |
| 139 | } |
| 140 | |
| 141 | static int fociFilter( |
| 142 | sqlite3_vtab_cursor *pCursor, |
| 143 | int idxNum, const char *idxStr, |
| @@ -146,10 +148,12 @@ | |
| 146 | FociCursor *pCur = (FociCursor *)pCursor; |
| 147 | manifest_destroy(pCur->pMan); |
| 148 | if( idxNum ){ |
| 149 | pCur->pMan = manifest_get(sqlite3_value_int(argv[0]), CFTYPE_MANIFEST, 0); |
| 150 | pCur->iFile = 0; |
| 151 | }else{ |
| 152 | pCur->pMan = 0; |
| 153 | pCur->iFile = 0; |
| 154 | } |
| 155 | return SQLITE_OK; |
| @@ -164,23 +168,23 @@ | |
| 164 | switch( i ){ |
| 165 | case 0: /* checkinID */ |
| 166 | sqlite3_result_int(ctx, pCsr->pMan->rid); |
| 167 | break; |
| 168 | case 1: /* filename */ |
| 169 | sqlite3_result_text(ctx, pCsr->pMan->aFile[pCsr->iFile].zName, -1, |
| 170 | SQLITE_TRANSIENT); |
| 171 | break; |
| 172 | case 2: /* uuid */ |
| 173 | sqlite3_result_text(ctx, pCsr->pMan->aFile[pCsr->iFile].zUuid, -1, |
| 174 | SQLITE_TRANSIENT); |
| 175 | break; |
| 176 | case 3: /* previousName */ |
| 177 | sqlite3_result_text(ctx, pCsr->pMan->aFile[pCsr->iFile].zPrior, -1, |
| 178 | SQLITE_TRANSIENT); |
| 179 | break; |
| 180 | case 4: /* perm */ |
| 181 | sqlite3_result_text(ctx, pCsr->pMan->aFile[pCsr->iFile].zPerm, -1, |
| 182 | SQLITE_TRANSIENT); |
| 183 | break; |
| 184 | } |
| 185 | return SQLITE_OK; |
| 186 | } |
| 187 |
| --- src/foci.c | |
| +++ src/foci.c | |
| @@ -46,11 +46,12 @@ | |
| 46 | sqlite3_vtab base; /* Base class - must be first */ |
| 47 | }; |
| 48 | struct FociCursor { |
| 49 | sqlite3_vtab_cursor base; /* Base class - must be first */ |
| 50 | Manifest *pMan; /* Current manifest */ |
| 51 | ManifestFile *pFile; /* Current file */ |
| 52 | int iFile; /* File index */ |
| 53 | }; |
| 54 | #endif /* INTERFACE */ |
| 55 | |
| 56 | |
| 57 | /* |
| @@ -127,17 +128,18 @@ | |
| 128 | /* |
| 129 | ** Move a focivfs cursor to the next entry in the file. |
| 130 | */ |
| 131 | static int fociNext(sqlite3_vtab_cursor *pCursor){ |
| 132 | FociCursor *pCsr = (FociCursor *)pCursor; |
| 133 | pCsr->pFile = manifest_file_next(pCsr->pMan, 0); |
| 134 | pCsr->iFile++; |
| 135 | return SQLITE_OK; |
| 136 | } |
| 137 | |
| 138 | static int fociEof(sqlite3_vtab_cursor *pCursor){ |
| 139 | FociCursor *pCsr = (FociCursor *)pCursor; |
| 140 | return pCsr->pFile==0; |
| 141 | } |
| 142 | |
| 143 | static int fociFilter( |
| 144 | sqlite3_vtab_cursor *pCursor, |
| 145 | int idxNum, const char *idxStr, |
| @@ -146,10 +148,12 @@ | |
| 148 | FociCursor *pCur = (FociCursor *)pCursor; |
| 149 | manifest_destroy(pCur->pMan); |
| 150 | if( idxNum ){ |
| 151 | pCur->pMan = manifest_get(sqlite3_value_int(argv[0]), CFTYPE_MANIFEST, 0); |
| 152 | pCur->iFile = 0; |
| 153 | manifest_file_rewind(pCur->pMan); |
| 154 | pCur->pFile = manifest_file_next(pCur->pMan, 0); |
| 155 | }else{ |
| 156 | pCur->pMan = 0; |
| 157 | pCur->iFile = 0; |
| 158 | } |
| 159 | return SQLITE_OK; |
| @@ -164,23 +168,23 @@ | |
| 168 | switch( i ){ |
| 169 | case 0: /* checkinID */ |
| 170 | sqlite3_result_int(ctx, pCsr->pMan->rid); |
| 171 | break; |
| 172 | case 1: /* filename */ |
| 173 | sqlite3_result_text(ctx, pCsr->pFile->zName, -1, |
| 174 | SQLITE_TRANSIENT); |
| 175 | break; |
| 176 | case 2: /* uuid */ |
| 177 | sqlite3_result_text(ctx, pCsr->pFile->zUuid, -1, |
| 178 | SQLITE_TRANSIENT); |
| 179 | break; |
| 180 | case 3: /* previousName */ |
| 181 | sqlite3_result_text(ctx, pCsr->pFile->zPrior, -1, |
| 182 | SQLITE_TRANSIENT); |
| 183 | break; |
| 184 | case 4: /* perm */ |
| 185 | sqlite3_result_text(ctx, pCsr->pFile->zPerm, -1, |
| 186 | SQLITE_TRANSIENT); |
| 187 | break; |
| 188 | } |
| 189 | return SQLITE_OK; |
| 190 | } |
| 191 |
+8
-6
| --- src/http.c | ||
| +++ src/http.c | ||
| @@ -285,11 +285,11 @@ | ||
| 285 | 285 | g.zHttpAuth = prompt_for_httpauth_creds(); |
| 286 | 286 | transport_close(&g.url); |
| 287 | 287 | return http_exchange(pSend, pReply, useLogin, maxRedirect); |
| 288 | 288 | } |
| 289 | 289 | } |
| 290 | - if( rc!=200 && rc!=302 ){ | |
| 290 | + if( rc!=200 && rc!=301 && rc!=302 ){ | |
| 291 | 291 | int ii; |
| 292 | 292 | for(ii=7; zLine[ii] && zLine[ii]!=' '; ii++){} |
| 293 | 293 | while( zLine[ii]==' ' ) ii++; |
| 294 | 294 | fossil_warning("server says: %s", &zLine[ii]); |
| 295 | 295 | goto write_err; |
| @@ -299,11 +299,11 @@ | ||
| 299 | 299 | }else{ |
| 300 | 300 | closeConnection = 0; |
| 301 | 301 | } |
| 302 | 302 | }else if( g.url.isSsh && fossil_strnicmp(zLine, "status:", 7)==0 ){ |
| 303 | 303 | if( sscanf(zLine, "Status: %d", &rc)!=1 ) goto write_err; |
| 304 | - if( rc!=200 && rc!=302 ){ | |
| 304 | + if( rc!=200 && rc!=301 && rc!=302 ){ | |
| 305 | 305 | int ii; |
| 306 | 306 | for(ii=7; zLine[ii] && zLine[ii]!=' '; ii++){} |
| 307 | 307 | while( zLine[ii]==' ' ) ii++; |
| 308 | 308 | fossil_warning("server says: %s", &zLine[ii]); |
| 309 | 309 | goto write_err; |
| @@ -319,11 +319,12 @@ | ||
| 319 | 319 | if( c=='c' || c=='C' ){ |
| 320 | 320 | closeConnection = 1; |
| 321 | 321 | }else if( c=='k' || c=='K' ){ |
| 322 | 322 | closeConnection = 0; |
| 323 | 323 | } |
| 324 | - }else if( rc==302 && fossil_strnicmp(zLine, "location:", 9)==0 ){ | |
| 324 | + }else if( ( rc==301 || rc==302 ) && | |
| 325 | + fossil_strnicmp(zLine, "location:", 9)==0 ){ | |
| 325 | 326 | int i, j; |
| 326 | 327 | |
| 327 | 328 | if ( --maxRedirect == 0){ |
| 328 | 329 | fossil_warning("redirect limit exceeded"); |
| 329 | 330 | goto write_err; |
| @@ -336,16 +337,17 @@ | ||
| 336 | 337 | j = strlen(zLine) - 1; |
| 337 | 338 | while( j>4 && fossil_strcmp(&zLine[j-4],"/xfer")==0 ){ |
| 338 | 339 | j -= 4; |
| 339 | 340 | zLine[j] = 0; |
| 340 | 341 | } |
| 341 | - fossil_print("redirect to %s\n", &zLine[i]); | |
| 342 | + transport_close(&g.url); | |
| 343 | + transport_global_shutdown(&g.url); | |
| 344 | + fossil_print("redirect with status %d to %s\n", rc, &zLine[i]); | |
| 342 | 345 | url_parse(&zLine[i], 0); |
| 343 | 346 | fSeenHttpAuth = 0; |
| 344 | 347 | if( g.zHttpAuth ) free(g.zHttpAuth); |
| 345 | 348 | g.zHttpAuth = get_httpauth(); |
| 346 | - transport_close(&g.url); | |
| 347 | 349 | return http_exchange(pSend, pReply, useLogin, maxRedirect); |
| 348 | 350 | }else if( fossil_strnicmp(zLine, "content-type: ", 14)==0 ){ |
| 349 | 351 | if( fossil_strnicmp(&zLine[14], "application/x-fossil-debug", -1)==0 ){ |
| 350 | 352 | isCompressed = 0; |
| 351 | 353 | }else if( fossil_strnicmp(&zLine[14], |
| @@ -359,11 +361,11 @@ | ||
| 359 | 361 | if( iLength<0 ){ |
| 360 | 362 | fossil_warning("server did not reply"); |
| 361 | 363 | goto write_err; |
| 362 | 364 | } |
| 363 | 365 | if( rc!=200 ){ |
| 364 | - fossil_warning("\"location:\" missing from 302 redirect reply"); | |
| 366 | + fossil_warning("\"location:\" missing from %d redirect reply", rc); | |
| 365 | 367 | goto write_err; |
| 366 | 368 | } |
| 367 | 369 | |
| 368 | 370 | /* |
| 369 | 371 | ** Extract the reply payload that follows the header |
| 370 | 372 |
| --- src/http.c | |
| +++ src/http.c | |
| @@ -285,11 +285,11 @@ | |
| 285 | g.zHttpAuth = prompt_for_httpauth_creds(); |
| 286 | transport_close(&g.url); |
| 287 | return http_exchange(pSend, pReply, useLogin, maxRedirect); |
| 288 | } |
| 289 | } |
| 290 | if( rc!=200 && rc!=302 ){ |
| 291 | int ii; |
| 292 | for(ii=7; zLine[ii] && zLine[ii]!=' '; ii++){} |
| 293 | while( zLine[ii]==' ' ) ii++; |
| 294 | fossil_warning("server says: %s", &zLine[ii]); |
| 295 | goto write_err; |
| @@ -299,11 +299,11 @@ | |
| 299 | }else{ |
| 300 | closeConnection = 0; |
| 301 | } |
| 302 | }else if( g.url.isSsh && fossil_strnicmp(zLine, "status:", 7)==0 ){ |
| 303 | if( sscanf(zLine, "Status: %d", &rc)!=1 ) goto write_err; |
| 304 | if( rc!=200 && rc!=302 ){ |
| 305 | int ii; |
| 306 | for(ii=7; zLine[ii] && zLine[ii]!=' '; ii++){} |
| 307 | while( zLine[ii]==' ' ) ii++; |
| 308 | fossil_warning("server says: %s", &zLine[ii]); |
| 309 | goto write_err; |
| @@ -319,11 +319,12 @@ | |
| 319 | if( c=='c' || c=='C' ){ |
| 320 | closeConnection = 1; |
| 321 | }else if( c=='k' || c=='K' ){ |
| 322 | closeConnection = 0; |
| 323 | } |
| 324 | }else if( rc==302 && fossil_strnicmp(zLine, "location:", 9)==0 ){ |
| 325 | int i, j; |
| 326 | |
| 327 | if ( --maxRedirect == 0){ |
| 328 | fossil_warning("redirect limit exceeded"); |
| 329 | goto write_err; |
| @@ -336,16 +337,17 @@ | |
| 336 | j = strlen(zLine) - 1; |
| 337 | while( j>4 && fossil_strcmp(&zLine[j-4],"/xfer")==0 ){ |
| 338 | j -= 4; |
| 339 | zLine[j] = 0; |
| 340 | } |
| 341 | fossil_print("redirect to %s\n", &zLine[i]); |
| 342 | url_parse(&zLine[i], 0); |
| 343 | fSeenHttpAuth = 0; |
| 344 | if( g.zHttpAuth ) free(g.zHttpAuth); |
| 345 | g.zHttpAuth = get_httpauth(); |
| 346 | transport_close(&g.url); |
| 347 | return http_exchange(pSend, pReply, useLogin, maxRedirect); |
| 348 | }else if( fossil_strnicmp(zLine, "content-type: ", 14)==0 ){ |
| 349 | if( fossil_strnicmp(&zLine[14], "application/x-fossil-debug", -1)==0 ){ |
| 350 | isCompressed = 0; |
| 351 | }else if( fossil_strnicmp(&zLine[14], |
| @@ -359,11 +361,11 @@ | |
| 359 | if( iLength<0 ){ |
| 360 | fossil_warning("server did not reply"); |
| 361 | goto write_err; |
| 362 | } |
| 363 | if( rc!=200 ){ |
| 364 | fossil_warning("\"location:\" missing from 302 redirect reply"); |
| 365 | goto write_err; |
| 366 | } |
| 367 | |
| 368 | /* |
| 369 | ** Extract the reply payload that follows the header |
| 370 |
| --- src/http.c | |
| +++ src/http.c | |
| @@ -285,11 +285,11 @@ | |
| 285 | g.zHttpAuth = prompt_for_httpauth_creds(); |
| 286 | transport_close(&g.url); |
| 287 | return http_exchange(pSend, pReply, useLogin, maxRedirect); |
| 288 | } |
| 289 | } |
| 290 | if( rc!=200 && rc!=301 && rc!=302 ){ |
| 291 | int ii; |
| 292 | for(ii=7; zLine[ii] && zLine[ii]!=' '; ii++){} |
| 293 | while( zLine[ii]==' ' ) ii++; |
| 294 | fossil_warning("server says: %s", &zLine[ii]); |
| 295 | goto write_err; |
| @@ -299,11 +299,11 @@ | |
| 299 | }else{ |
| 300 | closeConnection = 0; |
| 301 | } |
| 302 | }else if( g.url.isSsh && fossil_strnicmp(zLine, "status:", 7)==0 ){ |
| 303 | if( sscanf(zLine, "Status: %d", &rc)!=1 ) goto write_err; |
| 304 | if( rc!=200 && rc!=301 && rc!=302 ){ |
| 305 | int ii; |
| 306 | for(ii=7; zLine[ii] && zLine[ii]!=' '; ii++){} |
| 307 | while( zLine[ii]==' ' ) ii++; |
| 308 | fossil_warning("server says: %s", &zLine[ii]); |
| 309 | goto write_err; |
| @@ -319,11 +319,12 @@ | |
| 319 | if( c=='c' || c=='C' ){ |
| 320 | closeConnection = 1; |
| 321 | }else if( c=='k' || c=='K' ){ |
| 322 | closeConnection = 0; |
| 323 | } |
| 324 | }else if( ( rc==301 || rc==302 ) && |
| 325 | fossil_strnicmp(zLine, "location:", 9)==0 ){ |
| 326 | int i, j; |
| 327 | |
| 328 | if ( --maxRedirect == 0){ |
| 329 | fossil_warning("redirect limit exceeded"); |
| 330 | goto write_err; |
| @@ -336,16 +337,17 @@ | |
| 337 | j = strlen(zLine) - 1; |
| 338 | while( j>4 && fossil_strcmp(&zLine[j-4],"/xfer")==0 ){ |
| 339 | j -= 4; |
| 340 | zLine[j] = 0; |
| 341 | } |
| 342 | transport_close(&g.url); |
| 343 | transport_global_shutdown(&g.url); |
| 344 | fossil_print("redirect with status %d to %s\n", rc, &zLine[i]); |
| 345 | url_parse(&zLine[i], 0); |
| 346 | fSeenHttpAuth = 0; |
| 347 | if( g.zHttpAuth ) free(g.zHttpAuth); |
| 348 | g.zHttpAuth = get_httpauth(); |
| 349 | return http_exchange(pSend, pReply, useLogin, maxRedirect); |
| 350 | }else if( fossil_strnicmp(zLine, "content-type: ", 14)==0 ){ |
| 351 | if( fossil_strnicmp(&zLine[14], "application/x-fossil-debug", -1)==0 ){ |
| 352 | isCompressed = 0; |
| 353 | }else if( fossil_strnicmp(&zLine[14], |
| @@ -359,11 +361,11 @@ | |
| 361 | if( iLength<0 ){ |
| 362 | fossil_warning("server did not reply"); |
| 363 | goto write_err; |
| 364 | } |
| 365 | if( rc!=200 ){ |
| 366 | fossil_warning("\"location:\" missing from %d redirect reply", rc); |
| 367 | goto write_err; |
| 368 | } |
| 369 | |
| 370 | /* |
| 371 | ** Extract the reply payload that follows the header |
| 372 |
+3
-1
| --- src/http_socket.c | ||
| +++ src/http_socket.c | ||
| @@ -45,10 +45,11 @@ | ||
| 45 | 45 | ** There can only be a single socket connection open at a time. |
| 46 | 46 | ** State information about that socket is stored in the following |
| 47 | 47 | ** local variables: |
| 48 | 48 | */ |
| 49 | 49 | static int socketIsInit = 0; /* True after global initialization */ |
| 50 | +static int addrIsInit = 0; /* True once addr is initialized */ | |
| 50 | 51 | #if defined(_WIN32) |
| 51 | 52 | static WSADATA socketInfo; /* Windows socket initialize data */ |
| 52 | 53 | #endif |
| 53 | 54 | static int iSocket = -1; /* The socket on which we talk to the server */ |
| 54 | 55 | static char *socketErrMsg = 0; /* Text of most recent socket error */ |
| @@ -105,10 +106,11 @@ | ||
| 105 | 106 | WSACleanup(); |
| 106 | 107 | #endif |
| 107 | 108 | socket_clear_errmsg(); |
| 108 | 109 | socketIsInit = 0; |
| 109 | 110 | } |
| 111 | + addrIsInit = 0; | |
| 110 | 112 | } |
| 111 | 113 | |
| 112 | 114 | /* |
| 113 | 115 | ** Close the currently open socket. If no socket is open, this routine |
| 114 | 116 | ** is a no-op. |
| @@ -133,14 +135,14 @@ | ||
| 133 | 135 | ** |
| 134 | 136 | ** Return the number of errors. |
| 135 | 137 | */ |
| 136 | 138 | int socket_open(UrlData *pUrlData){ |
| 137 | 139 | static struct sockaddr_in addr; /* The server address */ |
| 138 | - static int addrIsInit = 0; /* True once addr is initialized */ | |
| 139 | 140 | |
| 140 | 141 | socket_global_init(); |
| 141 | 142 | if( !addrIsInit ){ |
| 143 | + memset(&addr, 0, sizeof(addr)); | |
| 142 | 144 | addr.sin_family = AF_INET; |
| 143 | 145 | addr.sin_port = htons(pUrlData->port); |
| 144 | 146 | *(int*)&addr.sin_addr = inet_addr(pUrlData->name); |
| 145 | 147 | if( -1 == *(int*)&addr.sin_addr ){ |
| 146 | 148 | #ifndef FOSSIL_STATIC_LINK |
| 147 | 149 |
| --- src/http_socket.c | |
| +++ src/http_socket.c | |
| @@ -45,10 +45,11 @@ | |
| 45 | ** There can only be a single socket connection open at a time. |
| 46 | ** State information about that socket is stored in the following |
| 47 | ** local variables: |
| 48 | */ |
| 49 | static int socketIsInit = 0; /* True after global initialization */ |
| 50 | #if defined(_WIN32) |
| 51 | static WSADATA socketInfo; /* Windows socket initialize data */ |
| 52 | #endif |
| 53 | static int iSocket = -1; /* The socket on which we talk to the server */ |
| 54 | static char *socketErrMsg = 0; /* Text of most recent socket error */ |
| @@ -105,10 +106,11 @@ | |
| 105 | WSACleanup(); |
| 106 | #endif |
| 107 | socket_clear_errmsg(); |
| 108 | socketIsInit = 0; |
| 109 | } |
| 110 | } |
| 111 | |
| 112 | /* |
| 113 | ** Close the currently open socket. If no socket is open, this routine |
| 114 | ** is a no-op. |
| @@ -133,14 +135,14 @@ | |
| 133 | ** |
| 134 | ** Return the number of errors. |
| 135 | */ |
| 136 | int socket_open(UrlData *pUrlData){ |
| 137 | static struct sockaddr_in addr; /* The server address */ |
| 138 | static int addrIsInit = 0; /* True once addr is initialized */ |
| 139 | |
| 140 | socket_global_init(); |
| 141 | if( !addrIsInit ){ |
| 142 | addr.sin_family = AF_INET; |
| 143 | addr.sin_port = htons(pUrlData->port); |
| 144 | *(int*)&addr.sin_addr = inet_addr(pUrlData->name); |
| 145 | if( -1 == *(int*)&addr.sin_addr ){ |
| 146 | #ifndef FOSSIL_STATIC_LINK |
| 147 |
| --- src/http_socket.c | |
| +++ src/http_socket.c | |
| @@ -45,10 +45,11 @@ | |
| 45 | ** There can only be a single socket connection open at a time. |
| 46 | ** State information about that socket is stored in the following |
| 47 | ** local variables: |
| 48 | */ |
| 49 | static int socketIsInit = 0; /* True after global initialization */ |
| 50 | static int addrIsInit = 0; /* True once addr is initialized */ |
| 51 | #if defined(_WIN32) |
| 52 | static WSADATA socketInfo; /* Windows socket initialize data */ |
| 53 | #endif |
| 54 | static int iSocket = -1; /* The socket on which we talk to the server */ |
| 55 | static char *socketErrMsg = 0; /* Text of most recent socket error */ |
| @@ -105,10 +106,11 @@ | |
| 106 | WSACleanup(); |
| 107 | #endif |
| 108 | socket_clear_errmsg(); |
| 109 | socketIsInit = 0; |
| 110 | } |
| 111 | addrIsInit = 0; |
| 112 | } |
| 113 | |
| 114 | /* |
| 115 | ** Close the currently open socket. If no socket is open, this routine |
| 116 | ** is a no-op. |
| @@ -133,14 +135,14 @@ | |
| 135 | ** |
| 136 | ** Return the number of errors. |
| 137 | */ |
| 138 | int socket_open(UrlData *pUrlData){ |
| 139 | static struct sockaddr_in addr; /* The server address */ |
| 140 | |
| 141 | socket_global_init(); |
| 142 | if( !addrIsInit ){ |
| 143 | memset(&addr, 0, sizeof(addr)); |
| 144 | addr.sin_family = AF_INET; |
| 145 | addr.sin_port = htons(pUrlData->port); |
| 146 | *(int*)&addr.sin_addr = inet_addr(pUrlData->name); |
| 147 | if( -1 == *(int*)&addr.sin_addr ){ |
| 148 | #ifndef FOSSIL_STATIC_LINK |
| 149 |
+4
-3
| --- src/http_ssl.c | ||
| +++ src/http_ssl.c | ||
| @@ -41,11 +41,11 @@ | ||
| 41 | 41 | ** There can only be a single OpenSSL IO connection open at a time. |
| 42 | 42 | ** State information about that IO is stored in the following |
| 43 | 43 | ** local variables: |
| 44 | 44 | */ |
| 45 | 45 | static int sslIsInit = 0; /* True after global initialization */ |
| 46 | -static BIO *iBio; /* OpenSSL I/O abstraction */ | |
| 46 | +static BIO *iBio = 0; /* OpenSSL I/O abstraction */ | |
| 47 | 47 | static char *sslErrMsg = 0; /* Text of most recent OpenSSL error */ |
| 48 | 48 | static SSL_CTX *sslCtx; /* SSL context */ |
| 49 | 49 | static SSL *ssl; |
| 50 | 50 | |
| 51 | 51 | |
| @@ -99,12 +99,12 @@ | ||
| 99 | 99 | SSL_library_init(); |
| 100 | 100 | SSL_load_error_strings(); |
| 101 | 101 | ERR_load_BIO_strings(); |
| 102 | 102 | OpenSSL_add_all_algorithms(); |
| 103 | 103 | sslCtx = SSL_CTX_new(SSLv23_client_method()); |
| 104 | - /* Disable SSLv2 */ | |
| 105 | - SSL_CTX_set_options(sslCtx, SSL_OP_NO_SSLv2); | |
| 104 | + /* Disable SSLv2 and SSLv3 */ | |
| 105 | + SSL_CTX_set_options(sslCtx, SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3); | |
| 106 | 106 | |
| 107 | 107 | /* Set up acceptable CA root certificates */ |
| 108 | 108 | zCaSetting = db_get("ssl-ca-location", 0); |
| 109 | 109 | if( zCaSetting==0 || zCaSetting[0]=='\0' ){ |
| 110 | 110 | /* CA location not specified, use platform's default certificate store */ |
| @@ -171,10 +171,11 @@ | ||
| 171 | 171 | */ |
| 172 | 172 | void ssl_close(void){ |
| 173 | 173 | if( iBio!=NULL ){ |
| 174 | 174 | (void)BIO_reset(iBio); |
| 175 | 175 | BIO_free_all(iBio); |
| 176 | + iBio = NULL; | |
| 176 | 177 | } |
| 177 | 178 | } |
| 178 | 179 | |
| 179 | 180 | /* See RFC2817 for details */ |
| 180 | 181 | static int establish_proxy_tunnel(UrlData *pUrlData, BIO *bio){ |
| 181 | 182 |
| --- src/http_ssl.c | |
| +++ src/http_ssl.c | |
| @@ -41,11 +41,11 @@ | |
| 41 | ** There can only be a single OpenSSL IO connection open at a time. |
| 42 | ** State information about that IO is stored in the following |
| 43 | ** local variables: |
| 44 | */ |
| 45 | static int sslIsInit = 0; /* True after global initialization */ |
| 46 | static BIO *iBio; /* OpenSSL I/O abstraction */ |
| 47 | static char *sslErrMsg = 0; /* Text of most recent OpenSSL error */ |
| 48 | static SSL_CTX *sslCtx; /* SSL context */ |
| 49 | static SSL *ssl; |
| 50 | |
| 51 | |
| @@ -99,12 +99,12 @@ | |
| 99 | SSL_library_init(); |
| 100 | SSL_load_error_strings(); |
| 101 | ERR_load_BIO_strings(); |
| 102 | OpenSSL_add_all_algorithms(); |
| 103 | sslCtx = SSL_CTX_new(SSLv23_client_method()); |
| 104 | /* Disable SSLv2 */ |
| 105 | SSL_CTX_set_options(sslCtx, SSL_OP_NO_SSLv2); |
| 106 | |
| 107 | /* Set up acceptable CA root certificates */ |
| 108 | zCaSetting = db_get("ssl-ca-location", 0); |
| 109 | if( zCaSetting==0 || zCaSetting[0]=='\0' ){ |
| 110 | /* CA location not specified, use platform's default certificate store */ |
| @@ -171,10 +171,11 @@ | |
| 171 | */ |
| 172 | void ssl_close(void){ |
| 173 | if( iBio!=NULL ){ |
| 174 | (void)BIO_reset(iBio); |
| 175 | BIO_free_all(iBio); |
| 176 | } |
| 177 | } |
| 178 | |
| 179 | /* See RFC2817 for details */ |
| 180 | static int establish_proxy_tunnel(UrlData *pUrlData, BIO *bio){ |
| 181 |
| --- src/http_ssl.c | |
| +++ src/http_ssl.c | |
| @@ -41,11 +41,11 @@ | |
| 41 | ** There can only be a single OpenSSL IO connection open at a time. |
| 42 | ** State information about that IO is stored in the following |
| 43 | ** local variables: |
| 44 | */ |
| 45 | static int sslIsInit = 0; /* True after global initialization */ |
| 46 | static BIO *iBio = 0; /* OpenSSL I/O abstraction */ |
| 47 | static char *sslErrMsg = 0; /* Text of most recent OpenSSL error */ |
| 48 | static SSL_CTX *sslCtx; /* SSL context */ |
| 49 | static SSL *ssl; |
| 50 | |
| 51 | |
| @@ -99,12 +99,12 @@ | |
| 99 | SSL_library_init(); |
| 100 | SSL_load_error_strings(); |
| 101 | ERR_load_BIO_strings(); |
| 102 | OpenSSL_add_all_algorithms(); |
| 103 | sslCtx = SSL_CTX_new(SSLv23_client_method()); |
| 104 | /* Disable SSLv2 and SSLv3 */ |
| 105 | SSL_CTX_set_options(sslCtx, SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3); |
| 106 | |
| 107 | /* Set up acceptable CA root certificates */ |
| 108 | zCaSetting = db_get("ssl-ca-location", 0); |
| 109 | if( zCaSetting==0 || zCaSetting[0]=='\0' ){ |
| 110 | /* CA location not specified, use platform's default certificate store */ |
| @@ -171,10 +171,11 @@ | |
| 171 | */ |
| 172 | void ssl_close(void){ |
| 173 | if( iBio!=NULL ){ |
| 174 | (void)BIO_reset(iBio); |
| 175 | BIO_free_all(iBio); |
| 176 | iBio = NULL; |
| 177 | } |
| 178 | } |
| 179 | |
| 180 | /* See RFC2817 for details */ |
| 181 | static int establish_proxy_tunnel(UrlData *pUrlData, BIO *bio){ |
| 182 |
+1
-1
| --- src/info.c | ||
| +++ src/info.c | ||
| @@ -1919,11 +1919,11 @@ | ||
| 1919 | 1919 | } |
| 1920 | 1920 | if( strcmp(zModAction,"approve")==0 ){ |
| 1921 | 1921 | moderation_approve(rid); |
| 1922 | 1922 | } |
| 1923 | 1923 | } |
| 1924 | - zTktTitle = db_table_has_column( "ticket", "title" ) | |
| 1924 | + zTktTitle = db_table_has_column("repository", "ticket", "title" ) | |
| 1925 | 1925 | ? db_text("(No title)", "SELECT title FROM ticket WHERE tkt_uuid=%Q", zTktName) |
| 1926 | 1926 | : 0; |
| 1927 | 1927 | style_header("Ticket Change Details"); |
| 1928 | 1928 | style_submenu_element("Raw", "Raw", "%R/artifact/%s", zUuid); |
| 1929 | 1929 | style_submenu_element("History", "History", "%R/tkthistory/%s", zTktName); |
| 1930 | 1930 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -1919,11 +1919,11 @@ | |
| 1919 | } |
| 1920 | if( strcmp(zModAction,"approve")==0 ){ |
| 1921 | moderation_approve(rid); |
| 1922 | } |
| 1923 | } |
| 1924 | zTktTitle = db_table_has_column( "ticket", "title" ) |
| 1925 | ? db_text("(No title)", "SELECT title FROM ticket WHERE tkt_uuid=%Q", zTktName) |
| 1926 | : 0; |
| 1927 | style_header("Ticket Change Details"); |
| 1928 | style_submenu_element("Raw", "Raw", "%R/artifact/%s", zUuid); |
| 1929 | style_submenu_element("History", "History", "%R/tkthistory/%s", zTktName); |
| 1930 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -1919,11 +1919,11 @@ | |
| 1919 | } |
| 1920 | if( strcmp(zModAction,"approve")==0 ){ |
| 1921 | moderation_approve(rid); |
| 1922 | } |
| 1923 | } |
| 1924 | zTktTitle = db_table_has_column("repository", "ticket", "title" ) |
| 1925 | ? db_text("(No title)", "SELECT title FROM ticket WHERE tkt_uuid=%Q", zTktName) |
| 1926 | : 0; |
| 1927 | style_header("Ticket Change Details"); |
| 1928 | style_submenu_element("Raw", "Raw", "%R/artifact/%s", zUuid); |
| 1929 | style_submenu_element("History", "History", "%R/tkthistory/%s", zTktName); |
| 1930 |
+5
-5
| --- src/json_branch.c | ||
| +++ src/json_branch.c | ||
| @@ -66,11 +66,11 @@ | ||
| 66 | 66 | cson_value * payV; |
| 67 | 67 | cson_object * pay; |
| 68 | 68 | cson_value * listV; |
| 69 | 69 | cson_array * list; |
| 70 | 70 | char const * range = NULL; |
| 71 | - int which = 0; | |
| 71 | + int branchListFlags = BRL_OPEN_ONLY; | |
| 72 | 72 | char * sawConversionError = NULL; |
| 73 | 73 | Stmt q; |
| 74 | 74 | if( !g.perm.Read ){ |
| 75 | 75 | json_set_err(FSL_JSON_E_DENIED, |
| 76 | 76 | "Requires 'o' permissions."); |
| @@ -102,19 +102,19 @@ | ||
| 102 | 102 | } |
| 103 | 103 | /* Normalize range values... */ |
| 104 | 104 | switch(*range){ |
| 105 | 105 | case 'c': |
| 106 | 106 | range = "closed"; |
| 107 | - which = -1; | |
| 107 | + branchListFlags = BRL_CLOSED_ONLY; | |
| 108 | 108 | break; |
| 109 | 109 | case 'a': |
| 110 | 110 | range = "all"; |
| 111 | - which = 1; | |
| 111 | + branchListFlags = BRL_BOTH; | |
| 112 | 112 | break; |
| 113 | 113 | default: |
| 114 | 114 | range = "open"; |
| 115 | - which = 0; | |
| 115 | + branchListFlags = BRL_OPEN_ONLY; | |
| 116 | 116 | break; |
| 117 | 117 | }; |
| 118 | 118 | cson_object_set(pay,"range",json_new_string(range)); |
| 119 | 119 | |
| 120 | 120 | if( g.localOpen ){ /* add "current" property (branch name). */ |
| @@ -128,11 +128,11 @@ | ||
| 128 | 128 | cson_object_set(pay,"current",json_new_string(zCurrent)); |
| 129 | 129 | } |
| 130 | 130 | } |
| 131 | 131 | |
| 132 | 132 | |
| 133 | - branch_prepare_list_query(&q, which); | |
| 133 | + branch_prepare_list_query(&q, branchListFlags); | |
| 134 | 134 | cson_object_set(pay,"branches",listV); |
| 135 | 135 | while((SQLITE_ROW==db_step(&q))){ |
| 136 | 136 | cson_value * v = cson_sqlite3_column_to_value(q.pStmt,0); |
| 137 | 137 | if(v){ |
| 138 | 138 | cson_array_append(list,v); |
| 139 | 139 |
| --- src/json_branch.c | |
| +++ src/json_branch.c | |
| @@ -66,11 +66,11 @@ | |
| 66 | cson_value * payV; |
| 67 | cson_object * pay; |
| 68 | cson_value * listV; |
| 69 | cson_array * list; |
| 70 | char const * range = NULL; |
| 71 | int which = 0; |
| 72 | char * sawConversionError = NULL; |
| 73 | Stmt q; |
| 74 | if( !g.perm.Read ){ |
| 75 | json_set_err(FSL_JSON_E_DENIED, |
| 76 | "Requires 'o' permissions."); |
| @@ -102,19 +102,19 @@ | |
| 102 | } |
| 103 | /* Normalize range values... */ |
| 104 | switch(*range){ |
| 105 | case 'c': |
| 106 | range = "closed"; |
| 107 | which = -1; |
| 108 | break; |
| 109 | case 'a': |
| 110 | range = "all"; |
| 111 | which = 1; |
| 112 | break; |
| 113 | default: |
| 114 | range = "open"; |
| 115 | which = 0; |
| 116 | break; |
| 117 | }; |
| 118 | cson_object_set(pay,"range",json_new_string(range)); |
| 119 | |
| 120 | if( g.localOpen ){ /* add "current" property (branch name). */ |
| @@ -128,11 +128,11 @@ | |
| 128 | cson_object_set(pay,"current",json_new_string(zCurrent)); |
| 129 | } |
| 130 | } |
| 131 | |
| 132 | |
| 133 | branch_prepare_list_query(&q, which); |
| 134 | cson_object_set(pay,"branches",listV); |
| 135 | while((SQLITE_ROW==db_step(&q))){ |
| 136 | cson_value * v = cson_sqlite3_column_to_value(q.pStmt,0); |
| 137 | if(v){ |
| 138 | cson_array_append(list,v); |
| 139 |
| --- src/json_branch.c | |
| +++ src/json_branch.c | |
| @@ -66,11 +66,11 @@ | |
| 66 | cson_value * payV; |
| 67 | cson_object * pay; |
| 68 | cson_value * listV; |
| 69 | cson_array * list; |
| 70 | char const * range = NULL; |
| 71 | int branchListFlags = BRL_OPEN_ONLY; |
| 72 | char * sawConversionError = NULL; |
| 73 | Stmt q; |
| 74 | if( !g.perm.Read ){ |
| 75 | json_set_err(FSL_JSON_E_DENIED, |
| 76 | "Requires 'o' permissions."); |
| @@ -102,19 +102,19 @@ | |
| 102 | } |
| 103 | /* Normalize range values... */ |
| 104 | switch(*range){ |
| 105 | case 'c': |
| 106 | range = "closed"; |
| 107 | branchListFlags = BRL_CLOSED_ONLY; |
| 108 | break; |
| 109 | case 'a': |
| 110 | range = "all"; |
| 111 | branchListFlags = BRL_BOTH; |
| 112 | break; |
| 113 | default: |
| 114 | range = "open"; |
| 115 | branchListFlags = BRL_OPEN_ONLY; |
| 116 | break; |
| 117 | }; |
| 118 | cson_object_set(pay,"range",json_new_string(range)); |
| 119 | |
| 120 | if( g.localOpen ){ /* add "current" property (branch name). */ |
| @@ -128,11 +128,11 @@ | |
| 128 | cson_object_set(pay,"current",json_new_string(zCurrent)); |
| 129 | } |
| 130 | } |
| 131 | |
| 132 | |
| 133 | branch_prepare_list_query(&q, branchListFlags); |
| 134 | cson_object_set(pay,"branches",listV); |
| 135 | while((SQLITE_ROW==db_step(&q))){ |
| 136 | cson_value * v = cson_sqlite3_column_to_value(q.pStmt,0); |
| 137 | if(v){ |
| 138 | cson_array_append(list,v); |
| 139 |
+4
-4
| --- src/json_timeline.c | ||
| +++ src/json_timeline.c | ||
| @@ -88,20 +88,21 @@ | ||
| 88 | 88 | db_multi_exec("%s", zSql /*safe-for-%s*/); |
| 89 | 89 | } |
| 90 | 90 | |
| 91 | 91 | /* |
| 92 | 92 | ** Return a pointer to a constant string that forms the basis |
| 93 | -** for a timeline query for the JSON interface. | |
| 93 | +** for a timeline query for the JSON interface. It MUST NOT | |
| 94 | +** be used in a formatted string argument. | |
| 94 | 95 | */ |
| 95 | 96 | char const * json_timeline_query(void){ |
| 96 | 97 | /* Field order MUST match that from json_timeline_temp_table()!!! */ |
| 97 | 98 | static const char zBaseSql[] = |
| 98 | 99 | @ SELECT |
| 99 | 100 | @ NULL, |
| 100 | 101 | @ blob.rid, |
| 101 | 102 | @ uuid, |
| 102 | - @ CAST(strftime('%%s',event.mtime) AS INTEGER), | |
| 103 | + @ CAST(strftime('%s',event.mtime) AS INTEGER), | |
| 103 | 104 | @ datetime(event.mtime), |
| 104 | 105 | @ coalesce(ecomment, comment), |
| 105 | 106 | @ coalesce(euser, user), |
| 106 | 107 | @ blob.rid IN leaf, |
| 107 | 108 | @ bgcolor, |
| @@ -544,12 +545,11 @@ | ||
| 544 | 545 | goto error; |
| 545 | 546 | } |
| 546 | 547 | |
| 547 | 548 | #if 0 |
| 548 | 549 | /* only for testing! */ |
| 549 | - tmp = cson_value_new_string(blob_buffer(&sql),strlen(blob_buffer(&sql))); | |
| 550 | - SET("timelineSql"); | |
| 550 | + cson_object_set(pay, "timelineSql", cson_value_new_string(blob_buffer(&sql),strlen(blob_buffer(&sql)))); | |
| 551 | 551 | #endif |
| 552 | 552 | db_multi_exec("%s", blob_buffer(&sql) /*safe-for-%s*/); |
| 553 | 553 | blob_reset(&sql); |
| 554 | 554 | db_prepare(&q, "SELECT" |
| 555 | 555 | " uuid AS uuid," |
| 556 | 556 |
| --- src/json_timeline.c | |
| +++ src/json_timeline.c | |
| @@ -88,20 +88,21 @@ | |
| 88 | db_multi_exec("%s", zSql /*safe-for-%s*/); |
| 89 | } |
| 90 | |
| 91 | /* |
| 92 | ** Return a pointer to a constant string that forms the basis |
| 93 | ** for a timeline query for the JSON interface. |
| 94 | */ |
| 95 | char const * json_timeline_query(void){ |
| 96 | /* Field order MUST match that from json_timeline_temp_table()!!! */ |
| 97 | static const char zBaseSql[] = |
| 98 | @ SELECT |
| 99 | @ NULL, |
| 100 | @ blob.rid, |
| 101 | @ uuid, |
| 102 | @ CAST(strftime('%%s',event.mtime) AS INTEGER), |
| 103 | @ datetime(event.mtime), |
| 104 | @ coalesce(ecomment, comment), |
| 105 | @ coalesce(euser, user), |
| 106 | @ blob.rid IN leaf, |
| 107 | @ bgcolor, |
| @@ -544,12 +545,11 @@ | |
| 544 | goto error; |
| 545 | } |
| 546 | |
| 547 | #if 0 |
| 548 | /* only for testing! */ |
| 549 | tmp = cson_value_new_string(blob_buffer(&sql),strlen(blob_buffer(&sql))); |
| 550 | SET("timelineSql"); |
| 551 | #endif |
| 552 | db_multi_exec("%s", blob_buffer(&sql) /*safe-for-%s*/); |
| 553 | blob_reset(&sql); |
| 554 | db_prepare(&q, "SELECT" |
| 555 | " uuid AS uuid," |
| 556 |
| --- src/json_timeline.c | |
| +++ src/json_timeline.c | |
| @@ -88,20 +88,21 @@ | |
| 88 | db_multi_exec("%s", zSql /*safe-for-%s*/); |
| 89 | } |
| 90 | |
| 91 | /* |
| 92 | ** Return a pointer to a constant string that forms the basis |
| 93 | ** for a timeline query for the JSON interface. It MUST NOT |
| 94 | ** be used in a formatted string argument. |
| 95 | */ |
| 96 | char const * json_timeline_query(void){ |
| 97 | /* Field order MUST match that from json_timeline_temp_table()!!! */ |
| 98 | static const char zBaseSql[] = |
| 99 | @ SELECT |
| 100 | @ NULL, |
| 101 | @ blob.rid, |
| 102 | @ uuid, |
| 103 | @ CAST(strftime('%s',event.mtime) AS INTEGER), |
| 104 | @ datetime(event.mtime), |
| 105 | @ coalesce(ecomment, comment), |
| 106 | @ coalesce(euser, user), |
| 107 | @ blob.rid IN leaf, |
| 108 | @ bgcolor, |
| @@ -544,12 +545,11 @@ | |
| 545 | goto error; |
| 546 | } |
| 547 | |
| 548 | #if 0 |
| 549 | /* only for testing! */ |
| 550 | cson_object_set(pay, "timelineSql", cson_value_new_string(blob_buffer(&sql),strlen(blob_buffer(&sql)))); |
| 551 | #endif |
| 552 | db_multi_exec("%s", blob_buffer(&sql) /*safe-for-%s*/); |
| 553 | blob_reset(&sql); |
| 554 | db_prepare(&q, "SELECT" |
| 555 | " uuid AS uuid," |
| 556 |
+12
| --- src/main.mk | ||
| +++ src/main.mk | ||
| @@ -99,10 +99,11 @@ | ||
| 99 | 99 | $(SRCDIR)/schema.c \ |
| 100 | 100 | $(SRCDIR)/search.c \ |
| 101 | 101 | $(SRCDIR)/setup.c \ |
| 102 | 102 | $(SRCDIR)/sha1.c \ |
| 103 | 103 | $(SRCDIR)/shun.c \ |
| 104 | + $(SRCDIR)/sitemap.c \ | |
| 104 | 105 | $(SRCDIR)/skins.c \ |
| 105 | 106 | $(SRCDIR)/sqlcmd.c \ |
| 106 | 107 | $(SRCDIR)/stash.c \ |
| 107 | 108 | $(SRCDIR)/stat.c \ |
| 108 | 109 | $(SRCDIR)/style.c \ |
| @@ -220,10 +221,11 @@ | ||
| 220 | 221 | $(OBJDIR)/schema_.c \ |
| 221 | 222 | $(OBJDIR)/search_.c \ |
| 222 | 223 | $(OBJDIR)/setup_.c \ |
| 223 | 224 | $(OBJDIR)/sha1_.c \ |
| 224 | 225 | $(OBJDIR)/shun_.c \ |
| 226 | + $(OBJDIR)/sitemap_.c \ | |
| 225 | 227 | $(OBJDIR)/skins_.c \ |
| 226 | 228 | $(OBJDIR)/sqlcmd_.c \ |
| 227 | 229 | $(OBJDIR)/stash_.c \ |
| 228 | 230 | $(OBJDIR)/stat_.c \ |
| 229 | 231 | $(OBJDIR)/style_.c \ |
| @@ -338,10 +340,11 @@ | ||
| 338 | 340 | $(OBJDIR)/schema.o \ |
| 339 | 341 | $(OBJDIR)/search.o \ |
| 340 | 342 | $(OBJDIR)/setup.o \ |
| 341 | 343 | $(OBJDIR)/sha1.o \ |
| 342 | 344 | $(OBJDIR)/shun.o \ |
| 345 | + $(OBJDIR)/sitemap.o \ | |
| 343 | 346 | $(OBJDIR)/skins.o \ |
| 344 | 347 | $(OBJDIR)/sqlcmd.o \ |
| 345 | 348 | $(OBJDIR)/stash.o \ |
| 346 | 349 | $(OBJDIR)/stat.o \ |
| 347 | 350 | $(OBJDIR)/style.o \ |
| @@ -565,10 +568,11 @@ | ||
| 565 | 568 | $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \ |
| 566 | 569 | $(OBJDIR)/search_.c:$(OBJDIR)/search.h \ |
| 567 | 570 | $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \ |
| 568 | 571 | $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h \ |
| 569 | 572 | $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h \ |
| 573 | + $(OBJDIR)/sitemap_.c:$(OBJDIR)/sitemap.h \ | |
| 570 | 574 | $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \ |
| 571 | 575 | $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \ |
| 572 | 576 | $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h \ |
| 573 | 577 | $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h \ |
| 574 | 578 | $(OBJDIR)/style_.c:$(OBJDIR)/style.h \ |
| @@ -1296,10 +1300,18 @@ | ||
| 1296 | 1300 | |
| 1297 | 1301 | $(OBJDIR)/shun.o: $(OBJDIR)/shun_.c $(OBJDIR)/shun.h $(SRCDIR)/config.h |
| 1298 | 1302 | $(XTCC) -o $(OBJDIR)/shun.o -c $(OBJDIR)/shun_.c |
| 1299 | 1303 | |
| 1300 | 1304 | $(OBJDIR)/shun.h: $(OBJDIR)/headers |
| 1305 | + | |
| 1306 | +$(OBJDIR)/sitemap_.c: $(SRCDIR)/sitemap.c $(OBJDIR)/translate | |
| 1307 | + $(OBJDIR)/translate $(SRCDIR)/sitemap.c >$@ | |
| 1308 | + | |
| 1309 | +$(OBJDIR)/sitemap.o: $(OBJDIR)/sitemap_.c $(OBJDIR)/sitemap.h $(SRCDIR)/config.h | |
| 1310 | + $(XTCC) -o $(OBJDIR)/sitemap.o -c $(OBJDIR)/sitemap_.c | |
| 1311 | + | |
| 1312 | +$(OBJDIR)/sitemap.h: $(OBJDIR)/headers | |
| 1301 | 1313 | |
| 1302 | 1314 | $(OBJDIR)/skins_.c: $(SRCDIR)/skins.c $(OBJDIR)/translate |
| 1303 | 1315 | $(OBJDIR)/translate $(SRCDIR)/skins.c >$@ |
| 1304 | 1316 | |
| 1305 | 1317 | $(OBJDIR)/skins.o: $(OBJDIR)/skins_.c $(OBJDIR)/skins.h $(SRCDIR)/config.h |
| 1306 | 1318 |
| --- src/main.mk | |
| +++ src/main.mk | |
| @@ -99,10 +99,11 @@ | |
| 99 | $(SRCDIR)/schema.c \ |
| 100 | $(SRCDIR)/search.c \ |
| 101 | $(SRCDIR)/setup.c \ |
| 102 | $(SRCDIR)/sha1.c \ |
| 103 | $(SRCDIR)/shun.c \ |
| 104 | $(SRCDIR)/skins.c \ |
| 105 | $(SRCDIR)/sqlcmd.c \ |
| 106 | $(SRCDIR)/stash.c \ |
| 107 | $(SRCDIR)/stat.c \ |
| 108 | $(SRCDIR)/style.c \ |
| @@ -220,10 +221,11 @@ | |
| 220 | $(OBJDIR)/schema_.c \ |
| 221 | $(OBJDIR)/search_.c \ |
| 222 | $(OBJDIR)/setup_.c \ |
| 223 | $(OBJDIR)/sha1_.c \ |
| 224 | $(OBJDIR)/shun_.c \ |
| 225 | $(OBJDIR)/skins_.c \ |
| 226 | $(OBJDIR)/sqlcmd_.c \ |
| 227 | $(OBJDIR)/stash_.c \ |
| 228 | $(OBJDIR)/stat_.c \ |
| 229 | $(OBJDIR)/style_.c \ |
| @@ -338,10 +340,11 @@ | |
| 338 | $(OBJDIR)/schema.o \ |
| 339 | $(OBJDIR)/search.o \ |
| 340 | $(OBJDIR)/setup.o \ |
| 341 | $(OBJDIR)/sha1.o \ |
| 342 | $(OBJDIR)/shun.o \ |
| 343 | $(OBJDIR)/skins.o \ |
| 344 | $(OBJDIR)/sqlcmd.o \ |
| 345 | $(OBJDIR)/stash.o \ |
| 346 | $(OBJDIR)/stat.o \ |
| 347 | $(OBJDIR)/style.o \ |
| @@ -565,10 +568,11 @@ | |
| 565 | $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \ |
| 566 | $(OBJDIR)/search_.c:$(OBJDIR)/search.h \ |
| 567 | $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \ |
| 568 | $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h \ |
| 569 | $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h \ |
| 570 | $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \ |
| 571 | $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \ |
| 572 | $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h \ |
| 573 | $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h \ |
| 574 | $(OBJDIR)/style_.c:$(OBJDIR)/style.h \ |
| @@ -1296,10 +1300,18 @@ | |
| 1296 | |
| 1297 | $(OBJDIR)/shun.o: $(OBJDIR)/shun_.c $(OBJDIR)/shun.h $(SRCDIR)/config.h |
| 1298 | $(XTCC) -o $(OBJDIR)/shun.o -c $(OBJDIR)/shun_.c |
| 1299 | |
| 1300 | $(OBJDIR)/shun.h: $(OBJDIR)/headers |
| 1301 | |
| 1302 | $(OBJDIR)/skins_.c: $(SRCDIR)/skins.c $(OBJDIR)/translate |
| 1303 | $(OBJDIR)/translate $(SRCDIR)/skins.c >$@ |
| 1304 | |
| 1305 | $(OBJDIR)/skins.o: $(OBJDIR)/skins_.c $(OBJDIR)/skins.h $(SRCDIR)/config.h |
| 1306 |
| --- src/main.mk | |
| +++ src/main.mk | |
| @@ -99,10 +99,11 @@ | |
| 99 | $(SRCDIR)/schema.c \ |
| 100 | $(SRCDIR)/search.c \ |
| 101 | $(SRCDIR)/setup.c \ |
| 102 | $(SRCDIR)/sha1.c \ |
| 103 | $(SRCDIR)/shun.c \ |
| 104 | $(SRCDIR)/sitemap.c \ |
| 105 | $(SRCDIR)/skins.c \ |
| 106 | $(SRCDIR)/sqlcmd.c \ |
| 107 | $(SRCDIR)/stash.c \ |
| 108 | $(SRCDIR)/stat.c \ |
| 109 | $(SRCDIR)/style.c \ |
| @@ -220,10 +221,11 @@ | |
| 221 | $(OBJDIR)/schema_.c \ |
| 222 | $(OBJDIR)/search_.c \ |
| 223 | $(OBJDIR)/setup_.c \ |
| 224 | $(OBJDIR)/sha1_.c \ |
| 225 | $(OBJDIR)/shun_.c \ |
| 226 | $(OBJDIR)/sitemap_.c \ |
| 227 | $(OBJDIR)/skins_.c \ |
| 228 | $(OBJDIR)/sqlcmd_.c \ |
| 229 | $(OBJDIR)/stash_.c \ |
| 230 | $(OBJDIR)/stat_.c \ |
| 231 | $(OBJDIR)/style_.c \ |
| @@ -338,10 +340,11 @@ | |
| 340 | $(OBJDIR)/schema.o \ |
| 341 | $(OBJDIR)/search.o \ |
| 342 | $(OBJDIR)/setup.o \ |
| 343 | $(OBJDIR)/sha1.o \ |
| 344 | $(OBJDIR)/shun.o \ |
| 345 | $(OBJDIR)/sitemap.o \ |
| 346 | $(OBJDIR)/skins.o \ |
| 347 | $(OBJDIR)/sqlcmd.o \ |
| 348 | $(OBJDIR)/stash.o \ |
| 349 | $(OBJDIR)/stat.o \ |
| 350 | $(OBJDIR)/style.o \ |
| @@ -565,10 +568,11 @@ | |
| 568 | $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \ |
| 569 | $(OBJDIR)/search_.c:$(OBJDIR)/search.h \ |
| 570 | $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \ |
| 571 | $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h \ |
| 572 | $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h \ |
| 573 | $(OBJDIR)/sitemap_.c:$(OBJDIR)/sitemap.h \ |
| 574 | $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \ |
| 575 | $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \ |
| 576 | $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h \ |
| 577 | $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h \ |
| 578 | $(OBJDIR)/style_.c:$(OBJDIR)/style.h \ |
| @@ -1296,10 +1300,18 @@ | |
| 1300 | |
| 1301 | $(OBJDIR)/shun.o: $(OBJDIR)/shun_.c $(OBJDIR)/shun.h $(SRCDIR)/config.h |
| 1302 | $(XTCC) -o $(OBJDIR)/shun.o -c $(OBJDIR)/shun_.c |
| 1303 | |
| 1304 | $(OBJDIR)/shun.h: $(OBJDIR)/headers |
| 1305 | |
| 1306 | $(OBJDIR)/sitemap_.c: $(SRCDIR)/sitemap.c $(OBJDIR)/translate |
| 1307 | $(OBJDIR)/translate $(SRCDIR)/sitemap.c >$@ |
| 1308 | |
| 1309 | $(OBJDIR)/sitemap.o: $(OBJDIR)/sitemap_.c $(OBJDIR)/sitemap.h $(SRCDIR)/config.h |
| 1310 | $(XTCC) -o $(OBJDIR)/sitemap.o -c $(OBJDIR)/sitemap_.c |
| 1311 | |
| 1312 | $(OBJDIR)/sitemap.h: $(OBJDIR)/headers |
| 1313 | |
| 1314 | $(OBJDIR)/skins_.c: $(SRCDIR)/skins.c $(OBJDIR)/translate |
| 1315 | $(OBJDIR)/translate $(SRCDIR)/skins.c >$@ |
| 1316 | |
| 1317 | $(OBJDIR)/skins.o: $(OBJDIR)/skins_.c $(OBJDIR)/skins.h $(SRCDIR)/config.h |
| 1318 |
+38
-7
| --- src/makemake.tcl | ||
| +++ src/makemake.tcl | ||
| @@ -105,10 +105,11 @@ | ||
| 105 | 105 | schema |
| 106 | 106 | search |
| 107 | 107 | setup |
| 108 | 108 | sha1 |
| 109 | 109 | shun |
| 110 | + sitemap | |
| 110 | 111 | skins |
| 111 | 112 | sqlcmd |
| 112 | 113 | stash |
| 113 | 114 | stat |
| 114 | 115 | style |
| @@ -513,11 +514,12 @@ | ||
| 513 | 514 | # This is useful when Tcl has been compiled statically with MinGW. |
| 514 | 515 | # |
| 515 | 516 | FOSSIL_TCL_SOURCE = 1 |
| 516 | 517 | |
| 517 | 518 | #### Check if the workaround for the MinGW command line handling needs to |
| 518 | -# be enabled by default. | |
| 519 | +# be enabled by default. This check may be somewhat fragile due to the | |
| 520 | +# use of "findstring". | |
| 519 | 521 | # |
| 520 | 522 | ifndef MINGW_IS_32BIT_ONLY |
| 521 | 523 | ifeq (,$(findstring w64-mingw32,$(PREFIX))) |
| 522 | 524 | MINGW_IS_32BIT_ONLY = 1 |
| 523 | 525 | endif |
| @@ -526,26 +528,46 @@ | ||
| 526 | 528 | #### The directories where the zlib include and library files are located. |
| 527 | 529 | # |
| 528 | 530 | ZINCDIR = $(SRCDIR)/../compat/zlib |
| 529 | 531 | ZLIBDIR = $(SRCDIR)/../compat/zlib |
| 530 | 532 | |
| 533 | +#### Make an attempt to detect if Fossil is being built for the x64 processor | |
| 534 | +# architecture. This check may be somewhat fragile due to "findstring". | |
| 535 | +# | |
| 531 | 536 | ifndef X64 |
| 532 | 537 | ifneq (,$(findstring x86_64-w64-mingw32,$(PREFIX))) |
| 533 | 538 | X64 = 1 |
| 534 | 539 | endif |
| 535 | 540 | endif |
| 536 | 541 | |
| 542 | +#### Determine if the optimized assembly routines provided with zlib should be | |
| 543 | +# used, taking into account whether zlib is actually enabled and the target | |
| 544 | +# processor architecture. | |
| 545 | +# | |
| 537 | 546 | ifndef X64 |
| 538 | 547 | SSLCONFIG = mingw |
| 548 | +ifndef FOSSIL_ENABLE_MINIZ | |
| 539 | 549 | ZLIBCONFIG = LOC="-DASMV -DASMINF" OBJA="inffas86.o match.o" |
| 540 | 550 | LIBTARGETS = $(ZLIBDIR)/inffas86.o $(ZLIBDIR)/match.o |
| 551 | +else | |
| 552 | +ZLIBCONFIG = | |
| 553 | +LIBTARGETS = | |
| 554 | +endif | |
| 541 | 555 | else |
| 542 | 556 | SSLCONFIG = mingw64 |
| 543 | -ZLIBCONFIG = | |
| 557 | +ZLIBCONFIG = | |
| 544 | 558 | LIBTARGETS = |
| 545 | 559 | endif |
| 546 | 560 | |
| 561 | +#### Disable creation of the OpenSSL shared libraries. Also, disable support | |
| 562 | +# for both SSLv2 and SSLv3 (i.e. thereby forcing the use of TLS). | |
| 563 | +# | |
| 564 | +SSLCONFIG += no-ssl2 no-ssl3 no-shared | |
| 565 | + | |
| 566 | +#### When using zlib, make sure that OpenSSL is configured to use the zlib | |
| 567 | +# that Fossil knows about (i.e. the one within the source tree). | |
| 568 | +# | |
| 547 | 569 | ifndef FOSSIL_ENABLE_MINIZ |
| 548 | 570 | SSLCONFIG += --with-zlib-lib=$(PWD)/$(ZLIBDIR) --with-zlib-include=$(PWD)/$(ZLIBDIR) zlib |
| 549 | 571 | endif |
| 550 | 572 | |
| 551 | 573 | #### The directories where the OpenSSL include and library files are located. |
| @@ -1290,23 +1312,32 @@ | ||
| 1290 | 1312 | SSLLIBDIR = $(SSLDIR)\out32 |
| 1291 | 1313 | SSLLFLAGS = /nologo /opt:ref /debug |
| 1292 | 1314 | SSLLIB = ssleay32.lib libeay32.lib user32.lib gdi32.lib |
| 1293 | 1315 | !if "$(PLATFORM)"=="amd64" || "$(PLATFORM)"=="x64" |
| 1294 | 1316 | !message Using 'x64' platform for OpenSSL... |
| 1295 | -SSLCONFIG = VC-WIN64A no-asm | |
| 1317 | +# BUGBUG (OpenSSL): Apparently, using "no-ssl*" here breaks the build. | |
| 1318 | +# SSLCONFIG = VC-WIN64A no-asm no-ssl2 no-ssl3 no-shared | |
| 1319 | +SSLCONFIG = VC-WIN64A no-asm no-shared | |
| 1296 | 1320 | SSLSETUP = ms\do_win64a.bat |
| 1297 | 1321 | SSLNMAKE = ms\nt.mak all |
| 1322 | +SSLCFLAGS = -DOPENSSL_NO_SSL2 -DOPENSSL_NO_SSL3 | |
| 1298 | 1323 | !elseif "$(PLATFORM)"=="ia64" |
| 1299 | 1324 | !message Using 'ia64' platform for OpenSSL... |
| 1300 | -SSLCONFIG = VC-WIN64I no-asm | |
| 1325 | +# BUGBUG (OpenSSL): Apparently, using "no-ssl*" here breaks the build. | |
| 1326 | +# SSLCONFIG = VC-WIN64I no-asm no-ssl2 no-ssl3 no-shared | |
| 1327 | +SSLCONFIG = VC-WIN64I no-asm no-shared | |
| 1301 | 1328 | SSLSETUP = ms\do_win64i.bat |
| 1302 | 1329 | SSLNMAKE = ms\nt.mak all |
| 1330 | +SSLCFLAGS = -DOPENSSL_NO_SSL2 -DOPENSSL_NO_SSL3 | |
| 1303 | 1331 | !else |
| 1304 | 1332 | !message Assuming 'x86' platform for OpenSSL... |
| 1305 | -SSLCONFIG = VC-WIN32 no-asm | |
| 1333 | +# BUGBUG (OpenSSL): Apparently, using "no-ssl*" here breaks the build. | |
| 1334 | +# SSLCONFIG = VC-WIN32 no-asm no-ssl2 no-ssl3 no-shared | |
| 1335 | +SSLCONFIG = VC-WIN32 no-asm no-shared | |
| 1306 | 1336 | SSLSETUP = ms\do_ms.bat |
| 1307 | 1337 | SSLNMAKE = ms\nt.mak all |
| 1338 | +SSLCFLAGS = -DOPENSSL_NO_SSL2 -DOPENSSL_NO_SSL3 | |
| 1308 | 1339 | !endif |
| 1309 | 1340 | !endif |
| 1310 | 1341 | |
| 1311 | 1342 | !ifdef FOSSIL_ENABLE_TCL |
| 1312 | 1343 | TCLDIR = $(B)\compat\tcl-8.6 |
| @@ -1475,13 +1506,13 @@ | ||
| 1475 | 1506 | @set PATH=$(PERLDIR);$(PATH) |
| 1476 | 1507 | !endif |
| 1477 | 1508 | @pushd "$(SSLDIR)" && $(PERL) Configure $(SSLCONFIG) && popd |
| 1478 | 1509 | @pushd "$(SSLDIR)" && call $(SSLSETUP) && popd |
| 1479 | 1510 | !ifdef FOSSIL_ENABLE_WINXP |
| 1480 | - @pushd "$(SSLDIR)" && $(MAKE) /f $(SSLNMAKE) "CC=cl $(XPCFLAGS)" "LFLAGS=$(SSLLFLAGS) $(XPLDFLAGS)" && popd | |
| 1511 | + @pushd "$(SSLDIR)" && $(MAKE) /f $(SSLNMAKE) "CC=cl $(SSLCFLAGS) $(XPCFLAGS)" "LFLAGS=$(SSLLFLAGS) $(XPLDFLAGS)" && popd | |
| 1481 | 1512 | !else |
| 1482 | - @pushd "$(SSLDIR)" && $(MAKE) /f $(SSLNMAKE) && popd | |
| 1513 | + @pushd "$(SSLDIR)" && $(MAKE) /f $(SSLNMAKE) "CC=cl $(SSLCFLAGS)" && popd | |
| 1483 | 1514 | !endif |
| 1484 | 1515 | !endif |
| 1485 | 1516 | |
| 1486 | 1517 | !ifndef FOSSIL_ENABLE_MINIZ |
| 1487 | 1518 | APPTARGETS = $(APPTARGETS) zlib |
| 1488 | 1519 |
| --- src/makemake.tcl | |
| +++ src/makemake.tcl | |
| @@ -105,10 +105,11 @@ | |
| 105 | schema |
| 106 | search |
| 107 | setup |
| 108 | sha1 |
| 109 | shun |
| 110 | skins |
| 111 | sqlcmd |
| 112 | stash |
| 113 | stat |
| 114 | style |
| @@ -513,11 +514,12 @@ | |
| 513 | # This is useful when Tcl has been compiled statically with MinGW. |
| 514 | # |
| 515 | FOSSIL_TCL_SOURCE = 1 |
| 516 | |
| 517 | #### Check if the workaround for the MinGW command line handling needs to |
| 518 | # be enabled by default. |
| 519 | # |
| 520 | ifndef MINGW_IS_32BIT_ONLY |
| 521 | ifeq (,$(findstring w64-mingw32,$(PREFIX))) |
| 522 | MINGW_IS_32BIT_ONLY = 1 |
| 523 | endif |
| @@ -526,26 +528,46 @@ | |
| 526 | #### The directories where the zlib include and library files are located. |
| 527 | # |
| 528 | ZINCDIR = $(SRCDIR)/../compat/zlib |
| 529 | ZLIBDIR = $(SRCDIR)/../compat/zlib |
| 530 | |
| 531 | ifndef X64 |
| 532 | ifneq (,$(findstring x86_64-w64-mingw32,$(PREFIX))) |
| 533 | X64 = 1 |
| 534 | endif |
| 535 | endif |
| 536 | |
| 537 | ifndef X64 |
| 538 | SSLCONFIG = mingw |
| 539 | ZLIBCONFIG = LOC="-DASMV -DASMINF" OBJA="inffas86.o match.o" |
| 540 | LIBTARGETS = $(ZLIBDIR)/inffas86.o $(ZLIBDIR)/match.o |
| 541 | else |
| 542 | SSLCONFIG = mingw64 |
| 543 | ZLIBCONFIG = |
| 544 | LIBTARGETS = |
| 545 | endif |
| 546 | |
| 547 | ifndef FOSSIL_ENABLE_MINIZ |
| 548 | SSLCONFIG += --with-zlib-lib=$(PWD)/$(ZLIBDIR) --with-zlib-include=$(PWD)/$(ZLIBDIR) zlib |
| 549 | endif |
| 550 | |
| 551 | #### The directories where the OpenSSL include and library files are located. |
| @@ -1290,23 +1312,32 @@ | |
| 1290 | SSLLIBDIR = $(SSLDIR)\out32 |
| 1291 | SSLLFLAGS = /nologo /opt:ref /debug |
| 1292 | SSLLIB = ssleay32.lib libeay32.lib user32.lib gdi32.lib |
| 1293 | !if "$(PLATFORM)"=="amd64" || "$(PLATFORM)"=="x64" |
| 1294 | !message Using 'x64' platform for OpenSSL... |
| 1295 | SSLCONFIG = VC-WIN64A no-asm |
| 1296 | SSLSETUP = ms\do_win64a.bat |
| 1297 | SSLNMAKE = ms\nt.mak all |
| 1298 | !elseif "$(PLATFORM)"=="ia64" |
| 1299 | !message Using 'ia64' platform for OpenSSL... |
| 1300 | SSLCONFIG = VC-WIN64I no-asm |
| 1301 | SSLSETUP = ms\do_win64i.bat |
| 1302 | SSLNMAKE = ms\nt.mak all |
| 1303 | !else |
| 1304 | !message Assuming 'x86' platform for OpenSSL... |
| 1305 | SSLCONFIG = VC-WIN32 no-asm |
| 1306 | SSLSETUP = ms\do_ms.bat |
| 1307 | SSLNMAKE = ms\nt.mak all |
| 1308 | !endif |
| 1309 | !endif |
| 1310 | |
| 1311 | !ifdef FOSSIL_ENABLE_TCL |
| 1312 | TCLDIR = $(B)\compat\tcl-8.6 |
| @@ -1475,13 +1506,13 @@ | |
| 1475 | @set PATH=$(PERLDIR);$(PATH) |
| 1476 | !endif |
| 1477 | @pushd "$(SSLDIR)" && $(PERL) Configure $(SSLCONFIG) && popd |
| 1478 | @pushd "$(SSLDIR)" && call $(SSLSETUP) && popd |
| 1479 | !ifdef FOSSIL_ENABLE_WINXP |
| 1480 | @pushd "$(SSLDIR)" && $(MAKE) /f $(SSLNMAKE) "CC=cl $(XPCFLAGS)" "LFLAGS=$(SSLLFLAGS) $(XPLDFLAGS)" && popd |
| 1481 | !else |
| 1482 | @pushd "$(SSLDIR)" && $(MAKE) /f $(SSLNMAKE) && popd |
| 1483 | !endif |
| 1484 | !endif |
| 1485 | |
| 1486 | !ifndef FOSSIL_ENABLE_MINIZ |
| 1487 | APPTARGETS = $(APPTARGETS) zlib |
| 1488 |
| --- src/makemake.tcl | |
| +++ src/makemake.tcl | |
| @@ -105,10 +105,11 @@ | |
| 105 | schema |
| 106 | search |
| 107 | setup |
| 108 | sha1 |
| 109 | shun |
| 110 | sitemap |
| 111 | skins |
| 112 | sqlcmd |
| 113 | stash |
| 114 | stat |
| 115 | style |
| @@ -513,11 +514,12 @@ | |
| 514 | # This is useful when Tcl has been compiled statically with MinGW. |
| 515 | # |
| 516 | FOSSIL_TCL_SOURCE = 1 |
| 517 | |
| 518 | #### Check if the workaround for the MinGW command line handling needs to |
| 519 | # be enabled by default. This check may be somewhat fragile due to the |
| 520 | # use of "findstring". |
| 521 | # |
| 522 | ifndef MINGW_IS_32BIT_ONLY |
| 523 | ifeq (,$(findstring w64-mingw32,$(PREFIX))) |
| 524 | MINGW_IS_32BIT_ONLY = 1 |
| 525 | endif |
| @@ -526,26 +528,46 @@ | |
| 528 | #### The directories where the zlib include and library files are located. |
| 529 | # |
| 530 | ZINCDIR = $(SRCDIR)/../compat/zlib |
| 531 | ZLIBDIR = $(SRCDIR)/../compat/zlib |
| 532 | |
| 533 | #### Make an attempt to detect if Fossil is being built for the x64 processor |
| 534 | # architecture. This check may be somewhat fragile due to "findstring". |
| 535 | # |
| 536 | ifndef X64 |
| 537 | ifneq (,$(findstring x86_64-w64-mingw32,$(PREFIX))) |
| 538 | X64 = 1 |
| 539 | endif |
| 540 | endif |
| 541 | |
| 542 | #### Determine if the optimized assembly routines provided with zlib should be |
| 543 | # used, taking into account whether zlib is actually enabled and the target |
| 544 | # processor architecture. |
| 545 | # |
| 546 | ifndef X64 |
| 547 | SSLCONFIG = mingw |
| 548 | ifndef FOSSIL_ENABLE_MINIZ |
| 549 | ZLIBCONFIG = LOC="-DASMV -DASMINF" OBJA="inffas86.o match.o" |
| 550 | LIBTARGETS = $(ZLIBDIR)/inffas86.o $(ZLIBDIR)/match.o |
| 551 | else |
| 552 | ZLIBCONFIG = |
| 553 | LIBTARGETS = |
| 554 | endif |
| 555 | else |
| 556 | SSLCONFIG = mingw64 |
| 557 | ZLIBCONFIG = |
| 558 | LIBTARGETS = |
| 559 | endif |
| 560 | |
| 561 | #### Disable creation of the OpenSSL shared libraries. Also, disable support |
| 562 | # for both SSLv2 and SSLv3 (i.e. thereby forcing the use of TLS). |
| 563 | # |
| 564 | SSLCONFIG += no-ssl2 no-ssl3 no-shared |
| 565 | |
| 566 | #### When using zlib, make sure that OpenSSL is configured to use the zlib |
| 567 | # that Fossil knows about (i.e. the one within the source tree). |
| 568 | # |
| 569 | ifndef FOSSIL_ENABLE_MINIZ |
| 570 | SSLCONFIG += --with-zlib-lib=$(PWD)/$(ZLIBDIR) --with-zlib-include=$(PWD)/$(ZLIBDIR) zlib |
| 571 | endif |
| 572 | |
| 573 | #### The directories where the OpenSSL include and library files are located. |
| @@ -1290,23 +1312,32 @@ | |
| 1312 | SSLLIBDIR = $(SSLDIR)\out32 |
| 1313 | SSLLFLAGS = /nologo /opt:ref /debug |
| 1314 | SSLLIB = ssleay32.lib libeay32.lib user32.lib gdi32.lib |
| 1315 | !if "$(PLATFORM)"=="amd64" || "$(PLATFORM)"=="x64" |
| 1316 | !message Using 'x64' platform for OpenSSL... |
| 1317 | # BUGBUG (OpenSSL): Apparently, using "no-ssl*" here breaks the build. |
| 1318 | # SSLCONFIG = VC-WIN64A no-asm no-ssl2 no-ssl3 no-shared |
| 1319 | SSLCONFIG = VC-WIN64A no-asm no-shared |
| 1320 | SSLSETUP = ms\do_win64a.bat |
| 1321 | SSLNMAKE = ms\nt.mak all |
| 1322 | SSLCFLAGS = -DOPENSSL_NO_SSL2 -DOPENSSL_NO_SSL3 |
| 1323 | !elseif "$(PLATFORM)"=="ia64" |
| 1324 | !message Using 'ia64' platform for OpenSSL... |
| 1325 | # BUGBUG (OpenSSL): Apparently, using "no-ssl*" here breaks the build. |
| 1326 | # SSLCONFIG = VC-WIN64I no-asm no-ssl2 no-ssl3 no-shared |
| 1327 | SSLCONFIG = VC-WIN64I no-asm no-shared |
| 1328 | SSLSETUP = ms\do_win64i.bat |
| 1329 | SSLNMAKE = ms\nt.mak all |
| 1330 | SSLCFLAGS = -DOPENSSL_NO_SSL2 -DOPENSSL_NO_SSL3 |
| 1331 | !else |
| 1332 | !message Assuming 'x86' platform for OpenSSL... |
| 1333 | # BUGBUG (OpenSSL): Apparently, using "no-ssl*" here breaks the build. |
| 1334 | # SSLCONFIG = VC-WIN32 no-asm no-ssl2 no-ssl3 no-shared |
| 1335 | SSLCONFIG = VC-WIN32 no-asm no-shared |
| 1336 | SSLSETUP = ms\do_ms.bat |
| 1337 | SSLNMAKE = ms\nt.mak all |
| 1338 | SSLCFLAGS = -DOPENSSL_NO_SSL2 -DOPENSSL_NO_SSL3 |
| 1339 | !endif |
| 1340 | !endif |
| 1341 | |
| 1342 | !ifdef FOSSIL_ENABLE_TCL |
| 1343 | TCLDIR = $(B)\compat\tcl-8.6 |
| @@ -1475,13 +1506,13 @@ | |
| 1506 | @set PATH=$(PERLDIR);$(PATH) |
| 1507 | !endif |
| 1508 | @pushd "$(SSLDIR)" && $(PERL) Configure $(SSLCONFIG) && popd |
| 1509 | @pushd "$(SSLDIR)" && call $(SSLSETUP) && popd |
| 1510 | !ifdef FOSSIL_ENABLE_WINXP |
| 1511 | @pushd "$(SSLDIR)" && $(MAKE) /f $(SSLNMAKE) "CC=cl $(SSLCFLAGS) $(XPCFLAGS)" "LFLAGS=$(SSLLFLAGS) $(XPLDFLAGS)" && popd |
| 1512 | !else |
| 1513 | @pushd "$(SSLDIR)" && $(MAKE) /f $(SSLNMAKE) "CC=cl $(SSLCFLAGS)" && popd |
| 1514 | !endif |
| 1515 | !endif |
| 1516 | |
| 1517 | !ifndef FOSSIL_ENABLE_MINIZ |
| 1518 | APPTARGETS = $(APPTARGETS) zlib |
| 1519 |
+1
-1
| --- src/markdown.c | ||
| +++ src/markdown.c | ||
| @@ -2155,11 +2155,11 @@ | ||
| 2155 | 2155 | struct Blob *ib, /* input blob in markdown */ |
| 2156 | 2156 | const struct mkd_renderer *rndrer /* renderer descriptor (callbacks) */ |
| 2157 | 2157 | ){ |
| 2158 | 2158 | struct link_ref *lr; |
| 2159 | 2159 | struct Blob text = BLOB_INITIALIZER; |
| 2160 | - size_t i, beg, end; | |
| 2160 | + size_t i, beg, end = 0; | |
| 2161 | 2161 | struct render rndr; |
| 2162 | 2162 | char *ib_data; |
| 2163 | 2163 | |
| 2164 | 2164 | /* filling the render structure */ |
| 2165 | 2165 | if( !rndrer ) return; |
| 2166 | 2166 |
| --- src/markdown.c | |
| +++ src/markdown.c | |
| @@ -2155,11 +2155,11 @@ | |
| 2155 | struct Blob *ib, /* input blob in markdown */ |
| 2156 | const struct mkd_renderer *rndrer /* renderer descriptor (callbacks) */ |
| 2157 | ){ |
| 2158 | struct link_ref *lr; |
| 2159 | struct Blob text = BLOB_INITIALIZER; |
| 2160 | size_t i, beg, end; |
| 2161 | struct render rndr; |
| 2162 | char *ib_data; |
| 2163 | |
| 2164 | /* filling the render structure */ |
| 2165 | if( !rndrer ) return; |
| 2166 |
| --- src/markdown.c | |
| +++ src/markdown.c | |
| @@ -2155,11 +2155,11 @@ | |
| 2155 | struct Blob *ib, /* input blob in markdown */ |
| 2156 | const struct mkd_renderer *rndrer /* renderer descriptor (callbacks) */ |
| 2157 | ){ |
| 2158 | struct link_ref *lr; |
| 2159 | struct Blob text = BLOB_INITIALIZER; |
| 2160 | size_t i, beg, end = 0; |
| 2161 | struct render rndr; |
| 2162 | char *ib_data; |
| 2163 | |
| 2164 | /* filling the render structure */ |
| 2165 | if( !rndrer ) return; |
| 2166 |
+1
-6
| --- src/moderate.c | ||
| +++ src/moderate.c | ||
| @@ -38,16 +38,11 @@ | ||
| 38 | 38 | |
| 39 | 39 | /* |
| 40 | 40 | ** Return TRUE if the modreq table exists |
| 41 | 41 | */ |
| 42 | 42 | int moderation_table_exists(void){ |
| 43 | - static int modreqExists = -1; | |
| 44 | - if( modreqExists<0 ){ | |
| 45 | - modreqExists = db_exists("SELECT 1 FROM %s.sqlite_master" | |
| 46 | - " WHERE name='modreq'", db_name("repository")); | |
| 47 | - } | |
| 48 | - return modreqExists; | |
| 43 | + return db_table_exists("repository", "modreq"); | |
| 49 | 44 | } |
| 50 | 45 | |
| 51 | 46 | /* |
| 52 | 47 | ** Return TRUE if the object specified is being held for moderation. |
| 53 | 48 | */ |
| 54 | 49 |
| --- src/moderate.c | |
| +++ src/moderate.c | |
| @@ -38,16 +38,11 @@ | |
| 38 | |
| 39 | /* |
| 40 | ** Return TRUE if the modreq table exists |
| 41 | */ |
| 42 | int moderation_table_exists(void){ |
| 43 | static int modreqExists = -1; |
| 44 | if( modreqExists<0 ){ |
| 45 | modreqExists = db_exists("SELECT 1 FROM %s.sqlite_master" |
| 46 | " WHERE name='modreq'", db_name("repository")); |
| 47 | } |
| 48 | return modreqExists; |
| 49 | } |
| 50 | |
| 51 | /* |
| 52 | ** Return TRUE if the object specified is being held for moderation. |
| 53 | */ |
| 54 |
| --- src/moderate.c | |
| +++ src/moderate.c | |
| @@ -38,16 +38,11 @@ | |
| 38 | |
| 39 | /* |
| 40 | ** Return TRUE if the modreq table exists |
| 41 | */ |
| 42 | int moderation_table_exists(void){ |
| 43 | return db_table_exists("repository", "modreq"); |
| 44 | } |
| 45 | |
| 46 | /* |
| 47 | ** Return TRUE if the object specified is being held for moderation. |
| 48 | */ |
| 49 |
+100
-29
| --- src/name.c | ||
| +++ src/name.c | ||
| @@ -346,30 +346,25 @@ | ||
| 346 | 346 | ** name_collisions searches through events, blobs, and tickets for |
| 347 | 347 | ** collisions of a given UUID based on its length on UUIDs no shorter |
| 348 | 348 | ** than 4 characters in length. |
| 349 | 349 | */ |
| 350 | 350 | int name_collisions(const char *zName){ |
| 351 | - Stmt q; | |
| 352 | 351 | int c = 0; /* count of collisions for zName */ |
| 353 | 352 | int nLen; /* length of zName */ |
| 354 | 353 | nLen = strlen(zName); |
| 355 | 354 | if( nLen>=4 && nLen<=UUID_SIZE && validate16(zName, nLen) ){ |
| 356 | - db_prepare(&q, | |
| 357 | - "SELECT count(uuid) FROM" | |
| 358 | - " (SELECT substr(tkt_uuid, 1, %d) AS uuid FROM ticket" | |
| 359 | - " UNION ALL SELECT * FROM" | |
| 360 | - " (SELECT substr(tagname, 7, %d) FROM" | |
| 361 | - " tag WHERE tagname GLOB 'event-*')" | |
| 362 | - " UNION ALL SELECT * FROM" | |
| 363 | - " (SELECT substr(uuid, 1, %d) FROM blob))" | |
| 364 | - " WHERE uuid GLOB '%q*'" | |
| 365 | - " GROUP BY uuid HAVING count(uuid) > 1;", | |
| 366 | - nLen, nLen, nLen, zName); | |
| 367 | - if( db_step(&q)==SQLITE_ROW ){ | |
| 368 | - c = db_column_int(&q, 0); | |
| 369 | - } | |
| 370 | - db_finalize(&q); | |
| 355 | + c = db_int(0, | |
| 356 | + "SELECT" | |
| 357 | + " (SELECT count(*) FROM ticket" | |
| 358 | + " WHERE tkt_uuid GLOB '%q*') +" | |
| 359 | + " (SELECT count(*) FROM tag" | |
| 360 | + " WHERE tagname GLOB 'event-%q*') +" | |
| 361 | + " (SELECT count(*) FROM blob" | |
| 362 | + " WHERE uuid GLOB '%q*');", | |
| 363 | + zName, zName, zName | |
| 364 | + ); | |
| 365 | + if( c<2 ) c = 0; | |
| 371 | 366 | } |
| 372 | 367 | return c; |
| 373 | 368 | } |
| 374 | 369 | |
| 375 | 370 | /* |
| @@ -808,21 +803,21 @@ | ||
| 808 | 803 | db_multi_exec( |
| 809 | 804 | "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n" |
| 810 | 805 | "SELECT blob.rid, blob.uuid, event.mtime, 'checkin',\n" |
| 811 | 806 | " 'checkin on ' || strftime('%%Y-%%m-%%d %%H:%%M',event.mtime)\n" |
| 812 | 807 | " FROM event, blob\n" |
| 813 | - " WHERE event.objid %s AND event.type='ci'\n" | |
| 808 | + " WHERE (event.objid %s) AND event.type='ci'\n" | |
| 814 | 809 | " AND event.objid=blob.rid;", |
| 815 | 810 | zWhere /*safe-for-%s*/ |
| 816 | 811 | ); |
| 817 | 812 | |
| 818 | 813 | /* Describe files */ |
| 819 | 814 | db_multi_exec( |
| 820 | 815 | "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n" |
| 821 | 816 | "SELECT blob.rid, blob.uuid, event.mtime, 'file', 'file '||filename.name\n" |
| 822 | 817 | " FROM mlink, blob, event, filename\n" |
| 823 | - " WHERE mlink.fid %s\n" | |
| 818 | + " WHERE (mlink.fid %s)\n" | |
| 824 | 819 | " AND mlink.mid=event.objid\n" |
| 825 | 820 | " AND filename.fnid=mlink.fnid\n" |
| 826 | 821 | " AND mlink.fid=blob.rid;", |
| 827 | 822 | zWhere /*safe-for-%s*/ |
| 828 | 823 | ); |
| @@ -831,21 +826,21 @@ | ||
| 831 | 826 | db_multi_exec( |
| 832 | 827 | "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n" |
| 833 | 828 | "SELECT blob.rid, blob.uuid, tagxref.mtime, 'tag',\n" |
| 834 | 829 | " 'tag '||substr((SELECT uuid FROM blob WHERE rid=tagxref.rid),1,16)\n" |
| 835 | 830 | " FROM tagxref, blob\n" |
| 836 | - " WHERE tagxref.srcid %s AND tagxref.srcid!=tagxref.rid\n" | |
| 831 | + " WHERE (tagxref.srcid %s) AND tagxref.srcid!=tagxref.rid\n" | |
| 837 | 832 | " AND tagxref.srcid=blob.rid;", |
| 838 | 833 | zWhere /*safe-for-%s*/ |
| 839 | 834 | ); |
| 840 | 835 | |
| 841 | 836 | /* Cluster artifacts */ |
| 842 | 837 | db_multi_exec( |
| 843 | 838 | "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n" |
| 844 | 839 | "SELECT blob.rid, blob.uuid, tagxref.mtime, 'cluster', 'cluster'\n" |
| 845 | 840 | " FROM tagxref, blob\n" |
| 846 | - " WHERE tagxref.rid %s\n" | |
| 841 | + " WHERE (tagxref.rid %s)\n" | |
| 847 | 842 | " AND tagxref.tagid=(SELECT tagid FROM tag WHERE tagname='cluster')\n" |
| 848 | 843 | " AND blob.rid=tagxref.rid;", |
| 849 | 844 | zWhere /*safe-for-%s*/ |
| 850 | 845 | ); |
| 851 | 846 | |
| @@ -853,11 +848,11 @@ | ||
| 853 | 848 | db_multi_exec( |
| 854 | 849 | "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n" |
| 855 | 850 | "SELECT blob.rid, blob.uuid, tagxref.mtime, 'ticket',\n" |
| 856 | 851 | " 'ticket '||substr(tag.tagname,5,21)\n" |
| 857 | 852 | " FROM tagxref, tag, blob\n" |
| 858 | - " WHERE tagxref.rid %s\n" | |
| 853 | + " WHERE (tagxref.rid %s)\n" | |
| 859 | 854 | " AND tag.tagid=tagxref.tagid\n" |
| 860 | 855 | " AND tag.tagname GLOB 'tkt-*'" |
| 861 | 856 | " AND blob.rid=tagxref.rid;", |
| 862 | 857 | zWhere /*safe-for-%s*/ |
| 863 | 858 | ); |
| @@ -866,11 +861,11 @@ | ||
| 866 | 861 | db_multi_exec( |
| 867 | 862 | "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n" |
| 868 | 863 | "SELECT blob.rid, blob.uuid, tagxref.mtime, 'wiki',\n" |
| 869 | 864 | " printf('wiki \"%%s\"',substr(tag.tagname,6))\n" |
| 870 | 865 | " FROM tagxref, tag, blob\n" |
| 871 | - " WHERE tagxref.rid %s\n" | |
| 866 | + " WHERE (tagxref.rid %s)\n" | |
| 872 | 867 | " AND tag.tagid=tagxref.tagid\n" |
| 873 | 868 | " AND tag.tagname GLOB 'wiki-*'" |
| 874 | 869 | " AND blob.rid=tagxref.rid;", |
| 875 | 870 | zWhere /*safe-for-%s*/ |
| 876 | 871 | ); |
| @@ -879,35 +874,45 @@ | ||
| 879 | 874 | db_multi_exec( |
| 880 | 875 | "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n" |
| 881 | 876 | "SELECT blob.rid, blob.uuid, tagxref.mtime, 'event',\n" |
| 882 | 877 | " 'event '||substr(tag.tagname,7)\n" |
| 883 | 878 | " FROM tagxref, tag, blob\n" |
| 884 | - " WHERE tagxref.rid %s\n" | |
| 879 | + " WHERE (tagxref.rid %s)\n" | |
| 885 | 880 | " AND tag.tagid=tagxref.tagid\n" |
| 886 | 881 | " AND tag.tagname GLOB 'event-*'" |
| 887 | 882 | " AND blob.rid=tagxref.rid;", |
| 888 | 883 | zWhere /*safe-for-%s*/ |
| 889 | 884 | ); |
| 890 | 885 | |
| 891 | 886 | /* Attachments */ |
| 892 | 887 | db_multi_exec( |
| 893 | - "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,detail)\n" | |
| 888 | + "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n" | |
| 889 | + "SELECT blob.rid, blob.uuid, attachment.mtime, 'attach-control',\n" | |
| 890 | + " 'attachment-control for '||attachment.filename\n" | |
| 891 | + " FROM attachment, blob\n" | |
| 892 | + " WHERE (attachment.attachid %s)\n" | |
| 893 | + " AND blob.rid=attachment.attachid", | |
| 894 | + zWhere /*safe-for-%s*/ | |
| 895 | + ); | |
| 896 | + db_multi_exec( | |
| 897 | + "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n" | |
| 894 | 898 | "SELECT blob.rid, blob.uuid, attachment.mtime, 'attachment',\n" |
| 895 | 899 | " 'attachment '||attachment.filename\n" |
| 896 | 900 | " FROM attachment, blob\n" |
| 897 | - " WHERE attachment.src %s\n" | |
| 898 | - " AND blob.rid=attachment.src;", | |
| 901 | + " WHERE (blob.rid %s)\n" | |
| 902 | + " AND blob.rid NOT IN (SELECT rid FROM description)\n" | |
| 903 | + " AND blob.uuid=attachment.src", | |
| 899 | 904 | zWhere /*safe-for-%s*/ |
| 900 | 905 | ); |
| 901 | 906 | |
| 902 | 907 | /* Everything else */ |
| 903 | 908 | db_multi_exec( |
| 904 | 909 | "INSERT OR IGNORE INTO description(rid,uuid,type,summary)\n" |
| 905 | 910 | "SELECT blob.rid, blob.uuid," |
| 906 | 911 | " CASE WHEN blob.size<0 THEN 'phantom' ELSE '' END,\n" |
| 907 | 912 | " 'unknown'\n" |
| 908 | - " FROM blob WHERE blob.rid %s;", | |
| 913 | + " FROM blob WHERE (blob.rid %s);", | |
| 909 | 914 | zWhere /*safe-for-%s*/ |
| 910 | 915 | ); |
| 911 | 916 | |
| 912 | 917 | /* Mark private elements */ |
| 913 | 918 | db_multi_exec( |
| @@ -943,17 +948,83 @@ | ||
| 943 | 948 | } |
| 944 | 949 | |
| 945 | 950 | /* |
| 946 | 951 | ** COMMAND: test-describe-artifacts |
| 947 | 952 | ** |
| 948 | -** Usage: %fossil test-describe-artifacts | |
| 953 | +** Usage: %fossil test-describe-artifacts [--from S] [--count N] | |
| 949 | 954 | ** |
| 950 | 955 | ** Display a one-line description of every artifact. |
| 951 | 956 | */ |
| 952 | 957 | void test_describe_artifacts_cmd(void){ |
| 958 | + int iFrom = 0; | |
| 959 | + int iCnt = 1000000; | |
| 960 | + const char *z; | |
| 961 | + char *zRange; | |
| 953 | 962 | db_find_and_open_repository(0,0); |
| 954 | - describe_artifacts_to_stdout("IN (SELECT rid FROM blob)", 0); | |
| 963 | + z = find_option("from",0,1); | |
| 964 | + if( z ) iFrom = atoi(z); | |
| 965 | + z = find_option("count",0,1); | |
| 966 | + if( z ) iCnt = atoi(z); | |
| 967 | + zRange = mprintf("BETWEEN %d AND %d", iFrom, iFrom+iCnt-1); | |
| 968 | + describe_artifacts_to_stdout(zRange, 0); | |
| 969 | +} | |
| 970 | + | |
| 971 | +/* | |
| 972 | +** WEBPAGE: bloblist | |
| 973 | +** | |
| 974 | +** Return a page showing all artifacts in the repository. Query parameters: | |
| 975 | +** | |
| 976 | +** n=N Show N artifacts | |
| 977 | +** s=S Start with artifact number S | |
| 978 | +*/ | |
| 979 | +void bloblist_page(void){ | |
| 980 | + Stmt q; | |
| 981 | + int s = atoi(PD("s","0")); | |
| 982 | + int n = atoi(PD("n","5000")); | |
| 983 | + int mx = db_int(0, "SELECT max(rid) FROM blob"); | |
| 984 | + char *zRange; | |
| 985 | + | |
| 986 | + login_check_credentials(); | |
| 987 | + if( !g.perm.Read ){ login_needed(); return; } | |
| 988 | + style_header("List Of Artifacts"); | |
| 989 | + if( mx>n && P("s")==0 ){ | |
| 990 | + int i; | |
| 991 | + @ <p>Select a range of artifacts to view:</p> | |
| 992 | + @ <ul> | |
| 993 | + for(i=1; i<=mx; i+=n){ | |
| 994 | + @ <li> %z(href("%R/bloblist?s=%d&n=%d",i,n)) | |
| 995 | + @ %d(i)..%d(i+n-1<mx?i+n-1:mx)</a> | |
| 996 | + } | |
| 997 | + @ </ul> | |
| 998 | + style_footer(); | |
| 999 | + return; | |
| 1000 | + } | |
| 1001 | + if( mx>n ){ | |
| 1002 | + style_submenu_element("Index", "Index", "bloblist"); | |
| 1003 | + } | |
| 1004 | + zRange = mprintf("BETWEEN %d AND %d", s, s+n-1); | |
| 1005 | + describe_artifacts(zRange); | |
| 1006 | + db_prepare(&q, | |
| 1007 | + "SELECT rid, uuid, summary, isPrivate FROM description ORDER BY rid" | |
| 1008 | + ); | |
| 1009 | + @ <table cellpadding="0" cellspacing="0"> | |
| 1010 | + while( db_step(&q)==SQLITE_ROW ){ | |
| 1011 | + int rid = db_column_int(&q,0); | |
| 1012 | + const char *zUuid = db_column_text(&q, 1); | |
| 1013 | + const char *zDesc = db_column_text(&q, 2); | |
| 1014 | + int isPriv = db_column_int(&q,2); | |
| 1015 | + @ <tr><td align="right">%d(rid)</td> | |
| 1016 | + @ <td> %z(href("%R/info/%s",zUuid))%s(zUuid)</a> </td> | |
| 1017 | + @ <td align="left">%h(zDesc)</td> | |
| 1018 | + if( isPriv ){ | |
| 1019 | + @ <td>(unpublished)</td> | |
| 1020 | + } | |
| 1021 | + @ </tr> | |
| 1022 | + } | |
| 1023 | + @ </table> | |
| 1024 | + db_finalize(&q); | |
| 1025 | + style_footer(); | |
| 955 | 1026 | } |
| 956 | 1027 | |
| 957 | 1028 | /* |
| 958 | 1029 | ** COMMAND: test-unsent |
| 959 | 1030 | ** |
| 960 | 1031 |
| --- src/name.c | |
| +++ src/name.c | |
| @@ -346,30 +346,25 @@ | |
| 346 | ** name_collisions searches through events, blobs, and tickets for |
| 347 | ** collisions of a given UUID based on its length on UUIDs no shorter |
| 348 | ** than 4 characters in length. |
| 349 | */ |
| 350 | int name_collisions(const char *zName){ |
| 351 | Stmt q; |
| 352 | int c = 0; /* count of collisions for zName */ |
| 353 | int nLen; /* length of zName */ |
| 354 | nLen = strlen(zName); |
| 355 | if( nLen>=4 && nLen<=UUID_SIZE && validate16(zName, nLen) ){ |
| 356 | db_prepare(&q, |
| 357 | "SELECT count(uuid) FROM" |
| 358 | " (SELECT substr(tkt_uuid, 1, %d) AS uuid FROM ticket" |
| 359 | " UNION ALL SELECT * FROM" |
| 360 | " (SELECT substr(tagname, 7, %d) FROM" |
| 361 | " tag WHERE tagname GLOB 'event-*')" |
| 362 | " UNION ALL SELECT * FROM" |
| 363 | " (SELECT substr(uuid, 1, %d) FROM blob))" |
| 364 | " WHERE uuid GLOB '%q*'" |
| 365 | " GROUP BY uuid HAVING count(uuid) > 1;", |
| 366 | nLen, nLen, nLen, zName); |
| 367 | if( db_step(&q)==SQLITE_ROW ){ |
| 368 | c = db_column_int(&q, 0); |
| 369 | } |
| 370 | db_finalize(&q); |
| 371 | } |
| 372 | return c; |
| 373 | } |
| 374 | |
| 375 | /* |
| @@ -808,21 +803,21 @@ | |
| 808 | db_multi_exec( |
| 809 | "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n" |
| 810 | "SELECT blob.rid, blob.uuid, event.mtime, 'checkin',\n" |
| 811 | " 'checkin on ' || strftime('%%Y-%%m-%%d %%H:%%M',event.mtime)\n" |
| 812 | " FROM event, blob\n" |
| 813 | " WHERE event.objid %s AND event.type='ci'\n" |
| 814 | " AND event.objid=blob.rid;", |
| 815 | zWhere /*safe-for-%s*/ |
| 816 | ); |
| 817 | |
| 818 | /* Describe files */ |
| 819 | db_multi_exec( |
| 820 | "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n" |
| 821 | "SELECT blob.rid, blob.uuid, event.mtime, 'file', 'file '||filename.name\n" |
| 822 | " FROM mlink, blob, event, filename\n" |
| 823 | " WHERE mlink.fid %s\n" |
| 824 | " AND mlink.mid=event.objid\n" |
| 825 | " AND filename.fnid=mlink.fnid\n" |
| 826 | " AND mlink.fid=blob.rid;", |
| 827 | zWhere /*safe-for-%s*/ |
| 828 | ); |
| @@ -831,21 +826,21 @@ | |
| 831 | db_multi_exec( |
| 832 | "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n" |
| 833 | "SELECT blob.rid, blob.uuid, tagxref.mtime, 'tag',\n" |
| 834 | " 'tag '||substr((SELECT uuid FROM blob WHERE rid=tagxref.rid),1,16)\n" |
| 835 | " FROM tagxref, blob\n" |
| 836 | " WHERE tagxref.srcid %s AND tagxref.srcid!=tagxref.rid\n" |
| 837 | " AND tagxref.srcid=blob.rid;", |
| 838 | zWhere /*safe-for-%s*/ |
| 839 | ); |
| 840 | |
| 841 | /* Cluster artifacts */ |
| 842 | db_multi_exec( |
| 843 | "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n" |
| 844 | "SELECT blob.rid, blob.uuid, tagxref.mtime, 'cluster', 'cluster'\n" |
| 845 | " FROM tagxref, blob\n" |
| 846 | " WHERE tagxref.rid %s\n" |
| 847 | " AND tagxref.tagid=(SELECT tagid FROM tag WHERE tagname='cluster')\n" |
| 848 | " AND blob.rid=tagxref.rid;", |
| 849 | zWhere /*safe-for-%s*/ |
| 850 | ); |
| 851 | |
| @@ -853,11 +848,11 @@ | |
| 853 | db_multi_exec( |
| 854 | "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n" |
| 855 | "SELECT blob.rid, blob.uuid, tagxref.mtime, 'ticket',\n" |
| 856 | " 'ticket '||substr(tag.tagname,5,21)\n" |
| 857 | " FROM tagxref, tag, blob\n" |
| 858 | " WHERE tagxref.rid %s\n" |
| 859 | " AND tag.tagid=tagxref.tagid\n" |
| 860 | " AND tag.tagname GLOB 'tkt-*'" |
| 861 | " AND blob.rid=tagxref.rid;", |
| 862 | zWhere /*safe-for-%s*/ |
| 863 | ); |
| @@ -866,11 +861,11 @@ | |
| 866 | db_multi_exec( |
| 867 | "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n" |
| 868 | "SELECT blob.rid, blob.uuid, tagxref.mtime, 'wiki',\n" |
| 869 | " printf('wiki \"%%s\"',substr(tag.tagname,6))\n" |
| 870 | " FROM tagxref, tag, blob\n" |
| 871 | " WHERE tagxref.rid %s\n" |
| 872 | " AND tag.tagid=tagxref.tagid\n" |
| 873 | " AND tag.tagname GLOB 'wiki-*'" |
| 874 | " AND blob.rid=tagxref.rid;", |
| 875 | zWhere /*safe-for-%s*/ |
| 876 | ); |
| @@ -879,35 +874,45 @@ | |
| 879 | db_multi_exec( |
| 880 | "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n" |
| 881 | "SELECT blob.rid, blob.uuid, tagxref.mtime, 'event',\n" |
| 882 | " 'event '||substr(tag.tagname,7)\n" |
| 883 | " FROM tagxref, tag, blob\n" |
| 884 | " WHERE tagxref.rid %s\n" |
| 885 | " AND tag.tagid=tagxref.tagid\n" |
| 886 | " AND tag.tagname GLOB 'event-*'" |
| 887 | " AND blob.rid=tagxref.rid;", |
| 888 | zWhere /*safe-for-%s*/ |
| 889 | ); |
| 890 | |
| 891 | /* Attachments */ |
| 892 | db_multi_exec( |
| 893 | "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,detail)\n" |
| 894 | "SELECT blob.rid, blob.uuid, attachment.mtime, 'attachment',\n" |
| 895 | " 'attachment '||attachment.filename\n" |
| 896 | " FROM attachment, blob\n" |
| 897 | " WHERE attachment.src %s\n" |
| 898 | " AND blob.rid=attachment.src;", |
| 899 | zWhere /*safe-for-%s*/ |
| 900 | ); |
| 901 | |
| 902 | /* Everything else */ |
| 903 | db_multi_exec( |
| 904 | "INSERT OR IGNORE INTO description(rid,uuid,type,summary)\n" |
| 905 | "SELECT blob.rid, blob.uuid," |
| 906 | " CASE WHEN blob.size<0 THEN 'phantom' ELSE '' END,\n" |
| 907 | " 'unknown'\n" |
| 908 | " FROM blob WHERE blob.rid %s;", |
| 909 | zWhere /*safe-for-%s*/ |
| 910 | ); |
| 911 | |
| 912 | /* Mark private elements */ |
| 913 | db_multi_exec( |
| @@ -943,17 +948,83 @@ | |
| 943 | } |
| 944 | |
| 945 | /* |
| 946 | ** COMMAND: test-describe-artifacts |
| 947 | ** |
| 948 | ** Usage: %fossil test-describe-artifacts |
| 949 | ** |
| 950 | ** Display a one-line description of every artifact. |
| 951 | */ |
| 952 | void test_describe_artifacts_cmd(void){ |
| 953 | db_find_and_open_repository(0,0); |
| 954 | describe_artifacts_to_stdout("IN (SELECT rid FROM blob)", 0); |
| 955 | } |
| 956 | |
| 957 | /* |
| 958 | ** COMMAND: test-unsent |
| 959 | ** |
| 960 |
| --- src/name.c | |
| +++ src/name.c | |
| @@ -346,30 +346,25 @@ | |
| 346 | ** name_collisions searches through events, blobs, and tickets for |
| 347 | ** collisions of a given UUID based on its length on UUIDs no shorter |
| 348 | ** than 4 characters in length. |
| 349 | */ |
| 350 | int name_collisions(const char *zName){ |
| 351 | int c = 0; /* count of collisions for zName */ |
| 352 | int nLen; /* length of zName */ |
| 353 | nLen = strlen(zName); |
| 354 | if( nLen>=4 && nLen<=UUID_SIZE && validate16(zName, nLen) ){ |
| 355 | c = db_int(0, |
| 356 | "SELECT" |
| 357 | " (SELECT count(*) FROM ticket" |
| 358 | " WHERE tkt_uuid GLOB '%q*') +" |
| 359 | " (SELECT count(*) FROM tag" |
| 360 | " WHERE tagname GLOB 'event-%q*') +" |
| 361 | " (SELECT count(*) FROM blob" |
| 362 | " WHERE uuid GLOB '%q*');", |
| 363 | zName, zName, zName |
| 364 | ); |
| 365 | if( c<2 ) c = 0; |
| 366 | } |
| 367 | return c; |
| 368 | } |
| 369 | |
| 370 | /* |
| @@ -808,21 +803,21 @@ | |
| 803 | db_multi_exec( |
| 804 | "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n" |
| 805 | "SELECT blob.rid, blob.uuid, event.mtime, 'checkin',\n" |
| 806 | " 'checkin on ' || strftime('%%Y-%%m-%%d %%H:%%M',event.mtime)\n" |
| 807 | " FROM event, blob\n" |
| 808 | " WHERE (event.objid %s) AND event.type='ci'\n" |
| 809 | " AND event.objid=blob.rid;", |
| 810 | zWhere /*safe-for-%s*/ |
| 811 | ); |
| 812 | |
| 813 | /* Describe files */ |
| 814 | db_multi_exec( |
| 815 | "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n" |
| 816 | "SELECT blob.rid, blob.uuid, event.mtime, 'file', 'file '||filename.name\n" |
| 817 | " FROM mlink, blob, event, filename\n" |
| 818 | " WHERE (mlink.fid %s)\n" |
| 819 | " AND mlink.mid=event.objid\n" |
| 820 | " AND filename.fnid=mlink.fnid\n" |
| 821 | " AND mlink.fid=blob.rid;", |
| 822 | zWhere /*safe-for-%s*/ |
| 823 | ); |
| @@ -831,21 +826,21 @@ | |
| 826 | db_multi_exec( |
| 827 | "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n" |
| 828 | "SELECT blob.rid, blob.uuid, tagxref.mtime, 'tag',\n" |
| 829 | " 'tag '||substr((SELECT uuid FROM blob WHERE rid=tagxref.rid),1,16)\n" |
| 830 | " FROM tagxref, blob\n" |
| 831 | " WHERE (tagxref.srcid %s) AND tagxref.srcid!=tagxref.rid\n" |
| 832 | " AND tagxref.srcid=blob.rid;", |
| 833 | zWhere /*safe-for-%s*/ |
| 834 | ); |
| 835 | |
| 836 | /* Cluster artifacts */ |
| 837 | db_multi_exec( |
| 838 | "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n" |
| 839 | "SELECT blob.rid, blob.uuid, tagxref.mtime, 'cluster', 'cluster'\n" |
| 840 | " FROM tagxref, blob\n" |
| 841 | " WHERE (tagxref.rid %s)\n" |
| 842 | " AND tagxref.tagid=(SELECT tagid FROM tag WHERE tagname='cluster')\n" |
| 843 | " AND blob.rid=tagxref.rid;", |
| 844 | zWhere /*safe-for-%s*/ |
| 845 | ); |
| 846 | |
| @@ -853,11 +848,11 @@ | |
| 848 | db_multi_exec( |
| 849 | "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n" |
| 850 | "SELECT blob.rid, blob.uuid, tagxref.mtime, 'ticket',\n" |
| 851 | " 'ticket '||substr(tag.tagname,5,21)\n" |
| 852 | " FROM tagxref, tag, blob\n" |
| 853 | " WHERE (tagxref.rid %s)\n" |
| 854 | " AND tag.tagid=tagxref.tagid\n" |
| 855 | " AND tag.tagname GLOB 'tkt-*'" |
| 856 | " AND blob.rid=tagxref.rid;", |
| 857 | zWhere /*safe-for-%s*/ |
| 858 | ); |
| @@ -866,11 +861,11 @@ | |
| 861 | db_multi_exec( |
| 862 | "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n" |
| 863 | "SELECT blob.rid, blob.uuid, tagxref.mtime, 'wiki',\n" |
| 864 | " printf('wiki \"%%s\"',substr(tag.tagname,6))\n" |
| 865 | " FROM tagxref, tag, blob\n" |
| 866 | " WHERE (tagxref.rid %s)\n" |
| 867 | " AND tag.tagid=tagxref.tagid\n" |
| 868 | " AND tag.tagname GLOB 'wiki-*'" |
| 869 | " AND blob.rid=tagxref.rid;", |
| 870 | zWhere /*safe-for-%s*/ |
| 871 | ); |
| @@ -879,35 +874,45 @@ | |
| 874 | db_multi_exec( |
| 875 | "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n" |
| 876 | "SELECT blob.rid, blob.uuid, tagxref.mtime, 'event',\n" |
| 877 | " 'event '||substr(tag.tagname,7)\n" |
| 878 | " FROM tagxref, tag, blob\n" |
| 879 | " WHERE (tagxref.rid %s)\n" |
| 880 | " AND tag.tagid=tagxref.tagid\n" |
| 881 | " AND tag.tagname GLOB 'event-*'" |
| 882 | " AND blob.rid=tagxref.rid;", |
| 883 | zWhere /*safe-for-%s*/ |
| 884 | ); |
| 885 | |
| 886 | /* Attachments */ |
| 887 | db_multi_exec( |
| 888 | "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n" |
| 889 | "SELECT blob.rid, blob.uuid, attachment.mtime, 'attach-control',\n" |
| 890 | " 'attachment-control for '||attachment.filename\n" |
| 891 | " FROM attachment, blob\n" |
| 892 | " WHERE (attachment.attachid %s)\n" |
| 893 | " AND blob.rid=attachment.attachid", |
| 894 | zWhere /*safe-for-%s*/ |
| 895 | ); |
| 896 | db_multi_exec( |
| 897 | "INSERT OR IGNORE INTO description(rid,uuid,ctime,type,summary)\n" |
| 898 | "SELECT blob.rid, blob.uuid, attachment.mtime, 'attachment',\n" |
| 899 | " 'attachment '||attachment.filename\n" |
| 900 | " FROM attachment, blob\n" |
| 901 | " WHERE (blob.rid %s)\n" |
| 902 | " AND blob.rid NOT IN (SELECT rid FROM description)\n" |
| 903 | " AND blob.uuid=attachment.src", |
| 904 | zWhere /*safe-for-%s*/ |
| 905 | ); |
| 906 | |
| 907 | /* Everything else */ |
| 908 | db_multi_exec( |
| 909 | "INSERT OR IGNORE INTO description(rid,uuid,type,summary)\n" |
| 910 | "SELECT blob.rid, blob.uuid," |
| 911 | " CASE WHEN blob.size<0 THEN 'phantom' ELSE '' END,\n" |
| 912 | " 'unknown'\n" |
| 913 | " FROM blob WHERE (blob.rid %s);", |
| 914 | zWhere /*safe-for-%s*/ |
| 915 | ); |
| 916 | |
| 917 | /* Mark private elements */ |
| 918 | db_multi_exec( |
| @@ -943,17 +948,83 @@ | |
| 948 | } |
| 949 | |
| 950 | /* |
| 951 | ** COMMAND: test-describe-artifacts |
| 952 | ** |
| 953 | ** Usage: %fossil test-describe-artifacts [--from S] [--count N] |
| 954 | ** |
| 955 | ** Display a one-line description of every artifact. |
| 956 | */ |
| 957 | void test_describe_artifacts_cmd(void){ |
| 958 | int iFrom = 0; |
| 959 | int iCnt = 1000000; |
| 960 | const char *z; |
| 961 | char *zRange; |
| 962 | db_find_and_open_repository(0,0); |
| 963 | z = find_option("from",0,1); |
| 964 | if( z ) iFrom = atoi(z); |
| 965 | z = find_option("count",0,1); |
| 966 | if( z ) iCnt = atoi(z); |
| 967 | zRange = mprintf("BETWEEN %d AND %d", iFrom, iFrom+iCnt-1); |
| 968 | describe_artifacts_to_stdout(zRange, 0); |
| 969 | } |
| 970 | |
| 971 | /* |
| 972 | ** WEBPAGE: bloblist |
| 973 | ** |
| 974 | ** Return a page showing all artifacts in the repository. Query parameters: |
| 975 | ** |
| 976 | ** n=N Show N artifacts |
| 977 | ** s=S Start with artifact number S |
| 978 | */ |
| 979 | void bloblist_page(void){ |
| 980 | Stmt q; |
| 981 | int s = atoi(PD("s","0")); |
| 982 | int n = atoi(PD("n","5000")); |
| 983 | int mx = db_int(0, "SELECT max(rid) FROM blob"); |
| 984 | char *zRange; |
| 985 | |
| 986 | login_check_credentials(); |
| 987 | if( !g.perm.Read ){ login_needed(); return; } |
| 988 | style_header("List Of Artifacts"); |
| 989 | if( mx>n && P("s")==0 ){ |
| 990 | int i; |
| 991 | @ <p>Select a range of artifacts to view:</p> |
| 992 | @ <ul> |
| 993 | for(i=1; i<=mx; i+=n){ |
| 994 | @ <li> %z(href("%R/bloblist?s=%d&n=%d",i,n)) |
| 995 | @ %d(i)..%d(i+n-1<mx?i+n-1:mx)</a> |
| 996 | } |
| 997 | @ </ul> |
| 998 | style_footer(); |
| 999 | return; |
| 1000 | } |
| 1001 | if( mx>n ){ |
| 1002 | style_submenu_element("Index", "Index", "bloblist"); |
| 1003 | } |
| 1004 | zRange = mprintf("BETWEEN %d AND %d", s, s+n-1); |
| 1005 | describe_artifacts(zRange); |
| 1006 | db_prepare(&q, |
| 1007 | "SELECT rid, uuid, summary, isPrivate FROM description ORDER BY rid" |
| 1008 | ); |
| 1009 | @ <table cellpadding="0" cellspacing="0"> |
| 1010 | while( db_step(&q)==SQLITE_ROW ){ |
| 1011 | int rid = db_column_int(&q,0); |
| 1012 | const char *zUuid = db_column_text(&q, 1); |
| 1013 | const char *zDesc = db_column_text(&q, 2); |
| 1014 | int isPriv = db_column_int(&q,2); |
| 1015 | @ <tr><td align="right">%d(rid)</td> |
| 1016 | @ <td> %z(href("%R/info/%s",zUuid))%s(zUuid)</a> </td> |
| 1017 | @ <td align="left">%h(zDesc)</td> |
| 1018 | if( isPriv ){ |
| 1019 | @ <td>(unpublished)</td> |
| 1020 | } |
| 1021 | @ </tr> |
| 1022 | } |
| 1023 | @ </table> |
| 1024 | db_finalize(&q); |
| 1025 | style_footer(); |
| 1026 | } |
| 1027 | |
| 1028 | /* |
| 1029 | ** COMMAND: test-unsent |
| 1030 | ** |
| 1031 |
+2
-3
| --- src/purge.c | ||
| +++ src/purge.c | ||
| @@ -205,12 +205,11 @@ | ||
| 205 | 205 | ** are about to be deleted or otherwise made inaccessible. This routine |
| 206 | 206 | ** is checking to ensure that purging the checkins in zTab will not delete |
| 207 | 207 | ** a baseline manifest out from under a delta. |
| 208 | 208 | */ |
| 209 | 209 | int purge_baseline_out_from_under_delta(const char *zTab){ |
| 210 | - if( !db_exists("SELECT 1 FROM %s.sqlite_master WHERE name='plink'" | |
| 211 | - " AND sql GLOB '* baseid *'", db_name("repository")) ){ | |
| 210 | + if( !db_table_has_column("repository","plink","baseid") ){ | |
| 212 | 211 | /* Skip this check if the current database is an older schema that |
| 213 | 212 | ** does not contain the PLINK.BASEID field. */ |
| 214 | 213 | return 0; |
| 215 | 214 | }else{ |
| 216 | 215 | return db_int(0, |
| @@ -492,11 +491,11 @@ | ||
| 492 | 491 | } |
| 493 | 492 | /* The "checkins" subcommand goes here in alphabetical order, but it must |
| 494 | 493 | ** be moved to the end since it is the default case */ |
| 495 | 494 | }else if( strncmp(zSubcmd, "list", n)==0 || strcmp(zSubcmd,"ls")==0 ){ |
| 496 | 495 | int showDetail = find_option("l","l",0)!=0; |
| 497 | - if( db_int(-1,"PRAGMA table_info('purgeevent')")<0 ) return; | |
| 496 | + if( !db_table_exists("repository","purgeevent") ) return; | |
| 498 | 497 | db_prepare(&q, "SELECT peid, datetime(ctime,'unixepoch','localtime')" |
| 499 | 498 | " FROM purgeevent"); |
| 500 | 499 | while( db_step(&q)==SQLITE_ROW ){ |
| 501 | 500 | fossil_print("%4d on %s\n", db_column_int(&q,0), db_column_text(&q,1)); |
| 502 | 501 | if( showDetail ){ |
| 503 | 502 |
| --- src/purge.c | |
| +++ src/purge.c | |
| @@ -205,12 +205,11 @@ | |
| 205 | ** are about to be deleted or otherwise made inaccessible. This routine |
| 206 | ** is checking to ensure that purging the checkins in zTab will not delete |
| 207 | ** a baseline manifest out from under a delta. |
| 208 | */ |
| 209 | int purge_baseline_out_from_under_delta(const char *zTab){ |
| 210 | if( !db_exists("SELECT 1 FROM %s.sqlite_master WHERE name='plink'" |
| 211 | " AND sql GLOB '* baseid *'", db_name("repository")) ){ |
| 212 | /* Skip this check if the current database is an older schema that |
| 213 | ** does not contain the PLINK.BASEID field. */ |
| 214 | return 0; |
| 215 | }else{ |
| 216 | return db_int(0, |
| @@ -492,11 +491,11 @@ | |
| 492 | } |
| 493 | /* The "checkins" subcommand goes here in alphabetical order, but it must |
| 494 | ** be moved to the end since it is the default case */ |
| 495 | }else if( strncmp(zSubcmd, "list", n)==0 || strcmp(zSubcmd,"ls")==0 ){ |
| 496 | int showDetail = find_option("l","l",0)!=0; |
| 497 | if( db_int(-1,"PRAGMA table_info('purgeevent')")<0 ) return; |
| 498 | db_prepare(&q, "SELECT peid, datetime(ctime,'unixepoch','localtime')" |
| 499 | " FROM purgeevent"); |
| 500 | while( db_step(&q)==SQLITE_ROW ){ |
| 501 | fossil_print("%4d on %s\n", db_column_int(&q,0), db_column_text(&q,1)); |
| 502 | if( showDetail ){ |
| 503 |
| --- src/purge.c | |
| +++ src/purge.c | |
| @@ -205,12 +205,11 @@ | |
| 205 | ** are about to be deleted or otherwise made inaccessible. This routine |
| 206 | ** is checking to ensure that purging the checkins in zTab will not delete |
| 207 | ** a baseline manifest out from under a delta. |
| 208 | */ |
| 209 | int purge_baseline_out_from_under_delta(const char *zTab){ |
| 210 | if( !db_table_has_column("repository","plink","baseid") ){ |
| 211 | /* Skip this check if the current database is an older schema that |
| 212 | ** does not contain the PLINK.BASEID field. */ |
| 213 | return 0; |
| 214 | }else{ |
| 215 | return db_int(0, |
| @@ -492,11 +491,11 @@ | |
| 491 | } |
| 492 | /* The "checkins" subcommand goes here in alphabetical order, but it must |
| 493 | ** be moved to the end since it is the default case */ |
| 494 | }else if( strncmp(zSubcmd, "list", n)==0 || strcmp(zSubcmd,"ls")==0 ){ |
| 495 | int showDetail = find_option("l","l",0)!=0; |
| 496 | if( !db_table_exists("repository","purgeevent") ) return; |
| 497 | db_prepare(&q, "SELECT peid, datetime(ctime,'unixepoch','localtime')" |
| 498 | " FROM purgeevent"); |
| 499 | while( db_step(&q)==SQLITE_ROW ){ |
| 500 | fossil_print("%4d on %s\n", db_column_int(&q,0), db_column_text(&q,1)); |
| 501 | if( showDetail ){ |
| 502 |
+77
-21
| --- src/report.c | ||
| +++ src/report.c | ||
| @@ -922,42 +922,85 @@ | ||
| 922 | 922 | |
| 923 | 923 | /* |
| 924 | 924 | ** Output Javascript code that will enables sorting of the table with |
| 925 | 925 | ** the id zTableId by clicking. |
| 926 | 926 | ** |
| 927 | -** The javascript is derived from: | |
| 927 | +** The javascript was originally derived from: | |
| 928 | 928 | ** |
| 929 | 929 | ** http://www.webtoolkit.info/sortable-html-table.html |
| 930 | +** | |
| 931 | +** But there have been extensive modifications. | |
| 930 | 932 | ** |
| 931 | 933 | ** This variation allows column types to be expressed using the second |
| 932 | 934 | ** argument. Each character of the second argument represent a column. |
| 933 | -** "t" means sort as text. "n" means sort numerically. "x" means do not | |
| 934 | -** sort on this column. If there are fewer characters in zColumnTypes[] than | |
| 935 | -** their are columns, the all extra columns assume type "t" (text). | |
| 935 | +** | |
| 936 | +** t Sort by text | |
| 937 | +** n Sort numerically | |
| 938 | +** k Sort by the data-sortkey property | |
| 939 | +** x This column is not sortable | |
| 940 | +** | |
| 941 | +** If there are fewer characters in zColumnTypes[] than their are columns, | |
| 942 | +** the all extra columns assume type "t" (text). | |
| 943 | +** | |
| 944 | +** The third parameter is the column that was initially sorted (using 1-based | |
| 945 | +** column numbers, like SQL). Make this value 0 if none of the columns are | |
| 946 | +** initially sorted. Make the value negative if the column is initially sorted | |
| 947 | +** in reverse order. | |
| 948 | +** | |
| 949 | +** Clicking on the same column header twice in a row inverts the sort. | |
| 936 | 950 | */ |
| 937 | -void output_table_sorting_javascript(const char *zTableId, const char *zColumnTypes){ | |
| 951 | +void output_table_sorting_javascript( | |
| 952 | + const char *zTableId, /* ID of table to sort */ | |
| 953 | + const char *zColumnTypes, /* String for column types */ | |
| 954 | + int iInitSort /* Initially sorted column. Leftmost is 1. 0 for NONE */ | |
| 955 | +){ | |
| 938 | 956 | @ <script> |
| 939 | - @ function SortableTable(tableEl,columnTypes){ | |
| 957 | + @ function SortableTable(tableEl,columnTypes,initSort){ | |
| 940 | 958 | @ this.tbody = tableEl.getElementsByTagName('tbody'); |
| 959 | + @ this.columnTypes = columnTypes; | |
| 941 | 960 | @ this.sort = function (cell) { |
| 942 | 961 | @ var column = cell.cellIndex; |
| 943 | - @ var sortFn = cell.sortType=="n" ? this.sortNumeric : this.sortText; | |
| 962 | + @ var sortFn; | |
| 963 | + @ switch( cell.sortType ){ | |
| 964 | + @ case "n": sortFn = this.sortNumeric; break; | |
| 965 | + @ case "t": sortFn = this.sortText; break; | |
| 966 | + @ case "k": sortFn = this.sortKey; break; | |
| 967 | + @ case "x": return; | |
| 968 | + @ } | |
| 944 | 969 | @ this.sortIndex = column; |
| 945 | 970 | @ var newRows = new Array(); |
| 946 | 971 | @ for (j = 0; j < this.tbody[0].rows.length; j++) { |
| 947 | 972 | @ newRows[j] = this.tbody[0].rows[j]; |
| 948 | 973 | @ } |
| 949 | - @ newRows.sort(sortFn); | |
| 950 | - @ if (cell.getAttribute("sortdir") == 'down') { | |
| 951 | - @ newRows.reverse(); | |
| 952 | - @ cell.setAttribute('sortdir','up'); | |
| 953 | - @ } else { | |
| 954 | - @ cell.setAttribute('sortdir','down'); | |
| 974 | + @ if( this.sortIndex==Math.abs(this.prevColumn)-1 ){ | |
| 975 | + @ newRows.reverse(); | |
| 976 | + @ this.prevColumn = -this.prevColumn; | |
| 977 | + @ }else{ | |
| 978 | + @ newRows.sort(sortFn); | |
| 979 | + @ this.prevColumn = this.sortIndex+1; | |
| 955 | 980 | @ } |
| 956 | 981 | @ for (i=0;i<newRows.length;i++) { |
| 957 | 982 | @ this.tbody[0].appendChild(newRows[i]); |
| 958 | 983 | @ } |
| 984 | + @ this.setHdrIcons(); | |
| 985 | + @ } | |
| 986 | + @ this.setHdrIcons = function() { | |
| 987 | + @ for (var i=0; i<this.hdrRow.cells.length; i++) { | |
| 988 | + @ if( this.columnTypes[i]=='x' ) continue; | |
| 989 | + @ var sortType; | |
| 990 | + @ if( this.prevColumn==i+1 ){ | |
| 991 | + @ sortType = 'asc'; | |
| 992 | + @ }else if( this.prevColumn==(-1-i) ){ | |
| 993 | + @ sortType = 'desc' | |
| 994 | + @ }else{ | |
| 995 | + @ sortType = 'none'; | |
| 996 | + @ } | |
| 997 | + @ var hdrCell = this.hdrRow.cells[i]; | |
| 998 | + @ var clsName = hdrCell.className.replace(/\s*\bsort\s*\w+/, ''); | |
| 999 | + @ clsName += ' sort ' + sortType; | |
| 1000 | + @ hdrCell.className = clsName; | |
| 1001 | + @ } | |
| 959 | 1002 | @ } |
| 960 | 1003 | @ this.sortText = function(a,b) { |
| 961 | 1004 | @ var i = thisObject.sortIndex; |
| 962 | 1005 | @ aa = a.cells[i].textContent.replace(/^\W+/,'').toLowerCase(); |
| 963 | 1006 | @ bb = b.cells[i].textContent.replace(/^\W+/,'').toLowerCase(); |
| @@ -971,30 +1014,43 @@ | ||
| 971 | 1014 | @ if (isNaN(aa)) aa = 0; |
| 972 | 1015 | @ bb = parseFloat(b.cells[i].textContent); |
| 973 | 1016 | @ if (isNaN(bb)) bb = 0; |
| 974 | 1017 | @ return aa-bb; |
| 975 | 1018 | @ } |
| 976 | - @ var thisObject = this; | |
| 1019 | + @ this.sortKey = function(a,b) { | |
| 1020 | + @ var i = thisObject.sortIndex; | |
| 1021 | + @ aa = a.cells[i].getAttribute("data-sortkey"); | |
| 1022 | + @ bb = b.cells[i].getAttribute("data-sortkey"); | |
| 1023 | + @ if(aa==bb) return 0; | |
| 1024 | + @ if(aa<bb) return -1; | |
| 1025 | + @ return 1; | |
| 1026 | + @ } | |
| 977 | 1027 | @ var x = tableEl.getElementsByTagName('thead'); |
| 978 | 1028 | @ if(!(this.tbody && this.tbody[0].rows && this.tbody[0].rows.length>0)){ |
| 979 | 1029 | @ return; |
| 980 | 1030 | @ } |
| 981 | 1031 | @ if(x && x[0].rows && x[0].rows.length > 0) { |
| 982 | - @ var sortRow = x[0].rows[0]; | |
| 1032 | + @ this.hdrRow = x[0].rows[0]; | |
| 983 | 1033 | @ } else { |
| 984 | 1034 | @ return; |
| 985 | 1035 | @ } |
| 986 | - @ for (var i=0; i<sortRow.cells.length; i++) { | |
| 987 | - @ sortRow.cells[i].sTable = this; | |
| 988 | - @ sortRow.cells[i].sortType = columnTypes[i] || 't'; | |
| 989 | - @ sortRow.cells[i].onclick = function () { | |
| 1036 | + @ var thisObject = this; | |
| 1037 | + @ this.prevColumn = initSort; | |
| 1038 | + @ for (var i=0; i<this.hdrRow.cells.length; i++) { | |
| 1039 | + @ if( columnTypes[i]=='x' ) continue; | |
| 1040 | + @ var hdrcell = this.hdrRow.cells[i]; | |
| 1041 | + @ hdrcell.sTable = this; | |
| 1042 | + @ hdrcell.style.cursor = "pointer"; | |
| 1043 | + @ hdrcell.sortType = columnTypes[i] || 't'; | |
| 1044 | + @ hdrcell.onclick = function () { | |
| 990 | 1045 | @ this.sTable.sort(this); |
| 991 | 1046 | @ return false; |
| 992 | 1047 | @ } |
| 993 | 1048 | @ } |
| 1049 | + @ this.setHdrIcons() | |
| 994 | 1050 | @ } |
| 995 | - @ var t = new SortableTable(gebi("%s(zTableId)"),"%s(zColumnTypes)"); | |
| 1051 | + @ var t = new SortableTable(gebi("%s(zTableId)"),"%s(zColumnTypes)",%d(iInitSort)); | |
| 996 | 1052 | @ </script> |
| 997 | 1053 | } |
| 998 | 1054 | |
| 999 | 1055 | |
| 1000 | 1056 | /* |
| @@ -1086,11 +1142,11 @@ | ||
| 1086 | 1142 | if( zErr1 ){ |
| 1087 | 1143 | @ <p class="reportError">Error: %h(zErr1)</p> |
| 1088 | 1144 | }else if( zErr2 ){ |
| 1089 | 1145 | @ <p class="reportError">Error: %h(zErr2)</p> |
| 1090 | 1146 | } |
| 1091 | - output_table_sorting_javascript("reportTable",""); | |
| 1147 | + output_table_sorting_javascript("reportTable","",0); | |
| 1092 | 1148 | style_footer(); |
| 1093 | 1149 | }else{ |
| 1094 | 1150 | report_restrict_sql(&zErr1); |
| 1095 | 1151 | db_exec_readonly(g.db, zSql, output_tab_separated, &count, &zErr2); |
| 1096 | 1152 | report_unrestrict_sql(); |
| 1097 | 1153 |
| --- src/report.c | |
| +++ src/report.c | |
| @@ -922,42 +922,85 @@ | |
| 922 | |
| 923 | /* |
| 924 | ** Output Javascript code that will enables sorting of the table with |
| 925 | ** the id zTableId by clicking. |
| 926 | ** |
| 927 | ** The javascript is derived from: |
| 928 | ** |
| 929 | ** http://www.webtoolkit.info/sortable-html-table.html |
| 930 | ** |
| 931 | ** This variation allows column types to be expressed using the second |
| 932 | ** argument. Each character of the second argument represent a column. |
| 933 | ** "t" means sort as text. "n" means sort numerically. "x" means do not |
| 934 | ** sort on this column. If there are fewer characters in zColumnTypes[] than |
| 935 | ** their are columns, the all extra columns assume type "t" (text). |
| 936 | */ |
| 937 | void output_table_sorting_javascript(const char *zTableId, const char *zColumnTypes){ |
| 938 | @ <script> |
| 939 | @ function SortableTable(tableEl,columnTypes){ |
| 940 | @ this.tbody = tableEl.getElementsByTagName('tbody'); |
| 941 | @ this.sort = function (cell) { |
| 942 | @ var column = cell.cellIndex; |
| 943 | @ var sortFn = cell.sortType=="n" ? this.sortNumeric : this.sortText; |
| 944 | @ this.sortIndex = column; |
| 945 | @ var newRows = new Array(); |
| 946 | @ for (j = 0; j < this.tbody[0].rows.length; j++) { |
| 947 | @ newRows[j] = this.tbody[0].rows[j]; |
| 948 | @ } |
| 949 | @ newRows.sort(sortFn); |
| 950 | @ if (cell.getAttribute("sortdir") == 'down') { |
| 951 | @ newRows.reverse(); |
| 952 | @ cell.setAttribute('sortdir','up'); |
| 953 | @ } else { |
| 954 | @ cell.setAttribute('sortdir','down'); |
| 955 | @ } |
| 956 | @ for (i=0;i<newRows.length;i++) { |
| 957 | @ this.tbody[0].appendChild(newRows[i]); |
| 958 | @ } |
| 959 | @ } |
| 960 | @ this.sortText = function(a,b) { |
| 961 | @ var i = thisObject.sortIndex; |
| 962 | @ aa = a.cells[i].textContent.replace(/^\W+/,'').toLowerCase(); |
| 963 | @ bb = b.cells[i].textContent.replace(/^\W+/,'').toLowerCase(); |
| @@ -971,30 +1014,43 @@ | |
| 971 | @ if (isNaN(aa)) aa = 0; |
| 972 | @ bb = parseFloat(b.cells[i].textContent); |
| 973 | @ if (isNaN(bb)) bb = 0; |
| 974 | @ return aa-bb; |
| 975 | @ } |
| 976 | @ var thisObject = this; |
| 977 | @ var x = tableEl.getElementsByTagName('thead'); |
| 978 | @ if(!(this.tbody && this.tbody[0].rows && this.tbody[0].rows.length>0)){ |
| 979 | @ return; |
| 980 | @ } |
| 981 | @ if(x && x[0].rows && x[0].rows.length > 0) { |
| 982 | @ var sortRow = x[0].rows[0]; |
| 983 | @ } else { |
| 984 | @ return; |
| 985 | @ } |
| 986 | @ for (var i=0; i<sortRow.cells.length; i++) { |
| 987 | @ sortRow.cells[i].sTable = this; |
| 988 | @ sortRow.cells[i].sortType = columnTypes[i] || 't'; |
| 989 | @ sortRow.cells[i].onclick = function () { |
| 990 | @ this.sTable.sort(this); |
| 991 | @ return false; |
| 992 | @ } |
| 993 | @ } |
| 994 | @ } |
| 995 | @ var t = new SortableTable(gebi("%s(zTableId)"),"%s(zColumnTypes)"); |
| 996 | @ </script> |
| 997 | } |
| 998 | |
| 999 | |
| 1000 | /* |
| @@ -1086,11 +1142,11 @@ | |
| 1086 | if( zErr1 ){ |
| 1087 | @ <p class="reportError">Error: %h(zErr1)</p> |
| 1088 | }else if( zErr2 ){ |
| 1089 | @ <p class="reportError">Error: %h(zErr2)</p> |
| 1090 | } |
| 1091 | output_table_sorting_javascript("reportTable",""); |
| 1092 | style_footer(); |
| 1093 | }else{ |
| 1094 | report_restrict_sql(&zErr1); |
| 1095 | db_exec_readonly(g.db, zSql, output_tab_separated, &count, &zErr2); |
| 1096 | report_unrestrict_sql(); |
| 1097 |
| --- src/report.c | |
| +++ src/report.c | |
| @@ -922,42 +922,85 @@ | |
| 922 | |
| 923 | /* |
| 924 | ** Output Javascript code that will enables sorting of the table with |
| 925 | ** the id zTableId by clicking. |
| 926 | ** |
| 927 | ** The javascript was originally derived from: |
| 928 | ** |
| 929 | ** http://www.webtoolkit.info/sortable-html-table.html |
| 930 | ** |
| 931 | ** But there have been extensive modifications. |
| 932 | ** |
| 933 | ** This variation allows column types to be expressed using the second |
| 934 | ** argument. Each character of the second argument represent a column. |
| 935 | ** |
| 936 | ** t Sort by text |
| 937 | ** n Sort numerically |
| 938 | ** k Sort by the data-sortkey property |
| 939 | ** x This column is not sortable |
| 940 | ** |
| 941 | ** If there are fewer characters in zColumnTypes[] than their are columns, |
| 942 | ** the all extra columns assume type "t" (text). |
| 943 | ** |
| 944 | ** The third parameter is the column that was initially sorted (using 1-based |
| 945 | ** column numbers, like SQL). Make this value 0 if none of the columns are |
| 946 | ** initially sorted. Make the value negative if the column is initially sorted |
| 947 | ** in reverse order. |
| 948 | ** |
| 949 | ** Clicking on the same column header twice in a row inverts the sort. |
| 950 | */ |
| 951 | void output_table_sorting_javascript( |
| 952 | const char *zTableId, /* ID of table to sort */ |
| 953 | const char *zColumnTypes, /* String for column types */ |
| 954 | int iInitSort /* Initially sorted column. Leftmost is 1. 0 for NONE */ |
| 955 | ){ |
| 956 | @ <script> |
| 957 | @ function SortableTable(tableEl,columnTypes,initSort){ |
| 958 | @ this.tbody = tableEl.getElementsByTagName('tbody'); |
| 959 | @ this.columnTypes = columnTypes; |
| 960 | @ this.sort = function (cell) { |
| 961 | @ var column = cell.cellIndex; |
| 962 | @ var sortFn; |
| 963 | @ switch( cell.sortType ){ |
| 964 | @ case "n": sortFn = this.sortNumeric; break; |
| 965 | @ case "t": sortFn = this.sortText; break; |
| 966 | @ case "k": sortFn = this.sortKey; break; |
| 967 | @ case "x": return; |
| 968 | @ } |
| 969 | @ this.sortIndex = column; |
| 970 | @ var newRows = new Array(); |
| 971 | @ for (j = 0; j < this.tbody[0].rows.length; j++) { |
| 972 | @ newRows[j] = this.tbody[0].rows[j]; |
| 973 | @ } |
| 974 | @ if( this.sortIndex==Math.abs(this.prevColumn)-1 ){ |
| 975 | @ newRows.reverse(); |
| 976 | @ this.prevColumn = -this.prevColumn; |
| 977 | @ }else{ |
| 978 | @ newRows.sort(sortFn); |
| 979 | @ this.prevColumn = this.sortIndex+1; |
| 980 | @ } |
| 981 | @ for (i=0;i<newRows.length;i++) { |
| 982 | @ this.tbody[0].appendChild(newRows[i]); |
| 983 | @ } |
| 984 | @ this.setHdrIcons(); |
| 985 | @ } |
| 986 | @ this.setHdrIcons = function() { |
| 987 | @ for (var i=0; i<this.hdrRow.cells.length; i++) { |
| 988 | @ if( this.columnTypes[i]=='x' ) continue; |
| 989 | @ var sortType; |
| 990 | @ if( this.prevColumn==i+1 ){ |
| 991 | @ sortType = 'asc'; |
| 992 | @ }else if( this.prevColumn==(-1-i) ){ |
| 993 | @ sortType = 'desc' |
| 994 | @ }else{ |
| 995 | @ sortType = 'none'; |
| 996 | @ } |
| 997 | @ var hdrCell = this.hdrRow.cells[i]; |
| 998 | @ var clsName = hdrCell.className.replace(/\s*\bsort\s*\w+/, ''); |
| 999 | @ clsName += ' sort ' + sortType; |
| 1000 | @ hdrCell.className = clsName; |
| 1001 | @ } |
| 1002 | @ } |
| 1003 | @ this.sortText = function(a,b) { |
| 1004 | @ var i = thisObject.sortIndex; |
| 1005 | @ aa = a.cells[i].textContent.replace(/^\W+/,'').toLowerCase(); |
| 1006 | @ bb = b.cells[i].textContent.replace(/^\W+/,'').toLowerCase(); |
| @@ -971,30 +1014,43 @@ | |
| 1014 | @ if (isNaN(aa)) aa = 0; |
| 1015 | @ bb = parseFloat(b.cells[i].textContent); |
| 1016 | @ if (isNaN(bb)) bb = 0; |
| 1017 | @ return aa-bb; |
| 1018 | @ } |
| 1019 | @ this.sortKey = function(a,b) { |
| 1020 | @ var i = thisObject.sortIndex; |
| 1021 | @ aa = a.cells[i].getAttribute("data-sortkey"); |
| 1022 | @ bb = b.cells[i].getAttribute("data-sortkey"); |
| 1023 | @ if(aa==bb) return 0; |
| 1024 | @ if(aa<bb) return -1; |
| 1025 | @ return 1; |
| 1026 | @ } |
| 1027 | @ var x = tableEl.getElementsByTagName('thead'); |
| 1028 | @ if(!(this.tbody && this.tbody[0].rows && this.tbody[0].rows.length>0)){ |
| 1029 | @ return; |
| 1030 | @ } |
| 1031 | @ if(x && x[0].rows && x[0].rows.length > 0) { |
| 1032 | @ this.hdrRow = x[0].rows[0]; |
| 1033 | @ } else { |
| 1034 | @ return; |
| 1035 | @ } |
| 1036 | @ var thisObject = this; |
| 1037 | @ this.prevColumn = initSort; |
| 1038 | @ for (var i=0; i<this.hdrRow.cells.length; i++) { |
| 1039 | @ if( columnTypes[i]=='x' ) continue; |
| 1040 | @ var hdrcell = this.hdrRow.cells[i]; |
| 1041 | @ hdrcell.sTable = this; |
| 1042 | @ hdrcell.style.cursor = "pointer"; |
| 1043 | @ hdrcell.sortType = columnTypes[i] || 't'; |
| 1044 | @ hdrcell.onclick = function () { |
| 1045 | @ this.sTable.sort(this); |
| 1046 | @ return false; |
| 1047 | @ } |
| 1048 | @ } |
| 1049 | @ this.setHdrIcons() |
| 1050 | @ } |
| 1051 | @ var t = new SortableTable(gebi("%s(zTableId)"),"%s(zColumnTypes)",%d(iInitSort)); |
| 1052 | @ </script> |
| 1053 | } |
| 1054 | |
| 1055 | |
| 1056 | /* |
| @@ -1086,11 +1142,11 @@ | |
| 1142 | if( zErr1 ){ |
| 1143 | @ <p class="reportError">Error: %h(zErr1)</p> |
| 1144 | }else if( zErr2 ){ |
| 1145 | @ <p class="reportError">Error: %h(zErr2)</p> |
| 1146 | } |
| 1147 | output_table_sorting_javascript("reportTable","",0); |
| 1148 | style_footer(); |
| 1149 | }else{ |
| 1150 | report_restrict_sql(&zErr1); |
| 1151 | db_exec_readonly(g.db, zSql, output_tab_separated, &count, &zErr2); |
| 1152 | report_unrestrict_sql(); |
| 1153 |
+53
-37
| --- src/search.c | ||
| +++ src/search.c | ||
| @@ -13,27 +13,32 @@ | ||
| 13 | 13 | ** [email protected] |
| 14 | 14 | ** http://www.hwaci.com/drh/ |
| 15 | 15 | ** |
| 16 | 16 | ******************************************************************************* |
| 17 | 17 | ** |
| 18 | -** This file contains code to implement the "/doc" web page and related | |
| 19 | -** pages. | |
| 18 | +** This file contains code to implement a very simple search function | |
| 19 | +** against timeline comments, checkin content, wiki pages, and/or tickets. | |
| 20 | +** | |
| 21 | +** The search is full-text like in that it is looking for words and ignores | |
| 22 | +** punctuation and capitalization. But it is more akin to "grep" in that | |
| 23 | +** it scans the entire corpus for the search, and it does not support the | |
| 24 | +** full functionality of FTS4. | |
| 20 | 25 | */ |
| 21 | 26 | #include "config.h" |
| 22 | 27 | #include "search.h" |
| 23 | 28 | #include <assert.h> |
| 24 | 29 | |
| 25 | 30 | #if INTERFACE |
| 26 | 31 | /* |
| 27 | -** A compiled search patter | |
| 32 | +** A compiled search pattern | |
| 28 | 33 | */ |
| 29 | 34 | struct Search { |
| 30 | - int nTerm; | |
| 31 | - struct srchTerm { | |
| 32 | - char *z; | |
| 33 | - int n; | |
| 34 | - } a[8]; | |
| 35 | + int nTerm; /* Number of search terms */ | |
| 36 | + struct srchTerm { /* For each search term */ | |
| 37 | + char *z; /* Text */ | |
| 38 | + int n; /* length */ | |
| 39 | + } a[8]; | |
| 35 | 40 | }; |
| 36 | 41 | #endif |
| 37 | 42 | |
| 38 | 43 | /* |
| 39 | 44 | ** Compile a search pattern |
| @@ -98,43 +103,47 @@ | ||
| 98 | 103 | ** * 10 bonus points if the first occurrence is an exact match |
| 99 | 104 | ** * 1 additional point for each subsequent match of the same word |
| 100 | 105 | ** * Extra points of two consecutive words of the pattern are consecutive |
| 101 | 106 | ** in the document |
| 102 | 107 | */ |
| 103 | -int search_score(Search *p, const char *zDoc){ | |
| 108 | +int search_score(Search *p, int nDoc, const char **azDoc){ | |
| 104 | 109 | int iPrev = 999; |
| 105 | 110 | int score = 10; |
| 106 | 111 | int iBonus = 0; |
| 107 | - int i, j; | |
| 112 | + int i, j, k; | |
| 113 | + const char *zDoc; | |
| 108 | 114 | unsigned char seen[8]; |
| 109 | 115 | |
| 110 | 116 | memset(seen, 0, sizeof(seen)); |
| 111 | - if( zDoc==0 ) return score; | |
| 112 | - for(i=0; zDoc[i]; i++){ | |
| 113 | - char c = zDoc[i]; | |
| 114 | - if( isBoundary[c&0xff] ) continue; | |
| 115 | - for(j=0; j<p->nTerm; j++){ | |
| 116 | - int n = p->a[j].n; | |
| 117 | - if( sqlite3_strnicmp(p->a[j].z, &zDoc[i], n)==0 ){ | |
| 118 | - score += 1; | |
| 119 | - if( !seen[j] ){ | |
| 120 | - if( isBoundary[zDoc[i+n]&0xff] ) score += 10; | |
| 121 | - seen[j] = 1; | |
| 122 | - } | |
| 123 | - if( j==iPrev+1 ){ | |
| 124 | - score += iBonus; | |
| 125 | - } | |
| 126 | - i += n-1; | |
| 127 | - iPrev = j; | |
| 128 | - iBonus = 50; | |
| 129 | - break; | |
| 130 | - } | |
| 131 | - } | |
| 132 | - iBonus /= 2; | |
| 133 | - while( !isBoundary[zDoc[i]&0xff] ){ i++; } | |
| 134 | - } | |
| 135 | - | |
| 117 | + for(k=0; k<nDoc; k++){ | |
| 118 | + zDoc = azDoc[k]; | |
| 119 | + if( zDoc==0 ) continue; | |
| 120 | + for(i=0; zDoc[i]; i++){ | |
| 121 | + char c = zDoc[i]; | |
| 122 | + if( isBoundary[c&0xff] ) continue; | |
| 123 | + for(j=0; j<p->nTerm; j++){ | |
| 124 | + int n = p->a[j].n; | |
| 125 | + if( sqlite3_strnicmp(p->a[j].z, &zDoc[i], n)==0 ){ | |
| 126 | + score += 1; | |
| 127 | + if( !seen[j] ){ | |
| 128 | + if( isBoundary[zDoc[i+n]&0xff] ) score += 10; | |
| 129 | + seen[j] = 1; | |
| 130 | + } | |
| 131 | + if( j==iPrev+1 ){ | |
| 132 | + score += iBonus; | |
| 133 | + } | |
| 134 | + i += n-1; | |
| 135 | + iPrev = j; | |
| 136 | + iBonus = 50; | |
| 137 | + break; | |
| 138 | + } | |
| 139 | + } | |
| 140 | + iBonus /= 2; | |
| 141 | + while( !isBoundary[zDoc[i]&0xff] ){ i++; } | |
| 142 | + } | |
| 143 | + } | |
| 144 | + | |
| 136 | 145 | /* Every term must be seen or else the score is zero */ |
| 137 | 146 | for(j=0; j<p->nTerm; j++){ |
| 138 | 147 | if( !seen[j] ) return 0; |
| 139 | 148 | } |
| 140 | 149 | |
| @@ -149,21 +158,28 @@ | ||
| 149 | 158 | sqlite3_context *context, |
| 150 | 159 | int argc, |
| 151 | 160 | sqlite3_value **argv |
| 152 | 161 | ){ |
| 153 | 162 | Search *p = (Search*)sqlite3_user_data(context); |
| 154 | - int score = search_score(p, (const char*)sqlite3_value_text(argv[0])); | |
| 163 | + const char **azDoc; | |
| 164 | + int score; | |
| 165 | + int i; | |
| 166 | + | |
| 167 | + azDoc = fossil_malloc( sizeof(const char*)*(argc+1) ); | |
| 168 | + for(i=0; i<argc; i++) azDoc[i] = (const char*)sqlite3_value_text(argv[i]); | |
| 169 | + score = search_score(p, argc, azDoc); | |
| 170 | + fossil_free(azDoc); | |
| 155 | 171 | sqlite3_result_int(context, score); |
| 156 | 172 | } |
| 157 | 173 | |
| 158 | 174 | /* |
| 159 | 175 | ** Register the "score()" SQL function to score its input text |
| 160 | 176 | ** using the given Search object. Once this function is registered, |
| 161 | 177 | ** do not delete the Search object. |
| 162 | 178 | */ |
| 163 | 179 | void search_sql_setup(Search *p){ |
| 164 | - sqlite3_create_function(g.db, "score", 1, SQLITE_UTF8, p, | |
| 180 | + sqlite3_create_function(g.db, "score", -1, SQLITE_UTF8, p, | |
| 165 | 181 | search_score_sqlfunc, 0, 0); |
| 166 | 182 | } |
| 167 | 183 | |
| 168 | 184 | /* |
| 169 | 185 | ** Testing the search function. |
| 170 | 186 | |
| 171 | 187 | ADDED src/sitemap.c |
| --- src/search.c | |
| +++ src/search.c | |
| @@ -13,27 +13,32 @@ | |
| 13 | ** [email protected] |
| 14 | ** http://www.hwaci.com/drh/ |
| 15 | ** |
| 16 | ******************************************************************************* |
| 17 | ** |
| 18 | ** This file contains code to implement the "/doc" web page and related |
| 19 | ** pages. |
| 20 | */ |
| 21 | #include "config.h" |
| 22 | #include "search.h" |
| 23 | #include <assert.h> |
| 24 | |
| 25 | #if INTERFACE |
| 26 | /* |
| 27 | ** A compiled search patter |
| 28 | */ |
| 29 | struct Search { |
| 30 | int nTerm; |
| 31 | struct srchTerm { |
| 32 | char *z; |
| 33 | int n; |
| 34 | } a[8]; |
| 35 | }; |
| 36 | #endif |
| 37 | |
| 38 | /* |
| 39 | ** Compile a search pattern |
| @@ -98,43 +103,47 @@ | |
| 98 | ** * 10 bonus points if the first occurrence is an exact match |
| 99 | ** * 1 additional point for each subsequent match of the same word |
| 100 | ** * Extra points of two consecutive words of the pattern are consecutive |
| 101 | ** in the document |
| 102 | */ |
| 103 | int search_score(Search *p, const char *zDoc){ |
| 104 | int iPrev = 999; |
| 105 | int score = 10; |
| 106 | int iBonus = 0; |
| 107 | int i, j; |
| 108 | unsigned char seen[8]; |
| 109 | |
| 110 | memset(seen, 0, sizeof(seen)); |
| 111 | if( zDoc==0 ) return score; |
| 112 | for(i=0; zDoc[i]; i++){ |
| 113 | char c = zDoc[i]; |
| 114 | if( isBoundary[c&0xff] ) continue; |
| 115 | for(j=0; j<p->nTerm; j++){ |
| 116 | int n = p->a[j].n; |
| 117 | if( sqlite3_strnicmp(p->a[j].z, &zDoc[i], n)==0 ){ |
| 118 | score += 1; |
| 119 | if( !seen[j] ){ |
| 120 | if( isBoundary[zDoc[i+n]&0xff] ) score += 10; |
| 121 | seen[j] = 1; |
| 122 | } |
| 123 | if( j==iPrev+1 ){ |
| 124 | score += iBonus; |
| 125 | } |
| 126 | i += n-1; |
| 127 | iPrev = j; |
| 128 | iBonus = 50; |
| 129 | break; |
| 130 | } |
| 131 | } |
| 132 | iBonus /= 2; |
| 133 | while( !isBoundary[zDoc[i]&0xff] ){ i++; } |
| 134 | } |
| 135 | |
| 136 | /* Every term must be seen or else the score is zero */ |
| 137 | for(j=0; j<p->nTerm; j++){ |
| 138 | if( !seen[j] ) return 0; |
| 139 | } |
| 140 | |
| @@ -149,21 +158,28 @@ | |
| 149 | sqlite3_context *context, |
| 150 | int argc, |
| 151 | sqlite3_value **argv |
| 152 | ){ |
| 153 | Search *p = (Search*)sqlite3_user_data(context); |
| 154 | int score = search_score(p, (const char*)sqlite3_value_text(argv[0])); |
| 155 | sqlite3_result_int(context, score); |
| 156 | } |
| 157 | |
| 158 | /* |
| 159 | ** Register the "score()" SQL function to score its input text |
| 160 | ** using the given Search object. Once this function is registered, |
| 161 | ** do not delete the Search object. |
| 162 | */ |
| 163 | void search_sql_setup(Search *p){ |
| 164 | sqlite3_create_function(g.db, "score", 1, SQLITE_UTF8, p, |
| 165 | search_score_sqlfunc, 0, 0); |
| 166 | } |
| 167 | |
| 168 | /* |
| 169 | ** Testing the search function. |
| 170 | |
| 171 | DDED src/sitemap.c |
| --- src/search.c | |
| +++ src/search.c | |
| @@ -13,27 +13,32 @@ | |
| 13 | ** [email protected] |
| 14 | ** http://www.hwaci.com/drh/ |
| 15 | ** |
| 16 | ******************************************************************************* |
| 17 | ** |
| 18 | ** This file contains code to implement a very simple search function |
| 19 | ** against timeline comments, checkin content, wiki pages, and/or tickets. |
| 20 | ** |
| 21 | ** The search is full-text like in that it is looking for words and ignores |
| 22 | ** punctuation and capitalization. But it is more akin to "grep" in that |
| 23 | ** it scans the entire corpus for the search, and it does not support the |
| 24 | ** full functionality of FTS4. |
| 25 | */ |
| 26 | #include "config.h" |
| 27 | #include "search.h" |
| 28 | #include <assert.h> |
| 29 | |
| 30 | #if INTERFACE |
| 31 | /* |
| 32 | ** A compiled search pattern |
| 33 | */ |
| 34 | struct Search { |
| 35 | int nTerm; /* Number of search terms */ |
| 36 | struct srchTerm { /* For each search term */ |
| 37 | char *z; /* Text */ |
| 38 | int n; /* length */ |
| 39 | } a[8]; |
| 40 | }; |
| 41 | #endif |
| 42 | |
| 43 | /* |
| 44 | ** Compile a search pattern |
| @@ -98,43 +103,47 @@ | |
| 103 | ** * 10 bonus points if the first occurrence is an exact match |
| 104 | ** * 1 additional point for each subsequent match of the same word |
| 105 | ** * Extra points of two consecutive words of the pattern are consecutive |
| 106 | ** in the document |
| 107 | */ |
| 108 | int search_score(Search *p, int nDoc, const char **azDoc){ |
| 109 | int iPrev = 999; |
| 110 | int score = 10; |
| 111 | int iBonus = 0; |
| 112 | int i, j, k; |
| 113 | const char *zDoc; |
| 114 | unsigned char seen[8]; |
| 115 | |
| 116 | memset(seen, 0, sizeof(seen)); |
| 117 | for(k=0; k<nDoc; k++){ |
| 118 | zDoc = azDoc[k]; |
| 119 | if( zDoc==0 ) continue; |
| 120 | for(i=0; zDoc[i]; i++){ |
| 121 | char c = zDoc[i]; |
| 122 | if( isBoundary[c&0xff] ) continue; |
| 123 | for(j=0; j<p->nTerm; j++){ |
| 124 | int n = p->a[j].n; |
| 125 | if( sqlite3_strnicmp(p->a[j].z, &zDoc[i], n)==0 ){ |
| 126 | score += 1; |
| 127 | if( !seen[j] ){ |
| 128 | if( isBoundary[zDoc[i+n]&0xff] ) score += 10; |
| 129 | seen[j] = 1; |
| 130 | } |
| 131 | if( j==iPrev+1 ){ |
| 132 | score += iBonus; |
| 133 | } |
| 134 | i += n-1; |
| 135 | iPrev = j; |
| 136 | iBonus = 50; |
| 137 | break; |
| 138 | } |
| 139 | } |
| 140 | iBonus /= 2; |
| 141 | while( !isBoundary[zDoc[i]&0xff] ){ i++; } |
| 142 | } |
| 143 | } |
| 144 | |
| 145 | /* Every term must be seen or else the score is zero */ |
| 146 | for(j=0; j<p->nTerm; j++){ |
| 147 | if( !seen[j] ) return 0; |
| 148 | } |
| 149 | |
| @@ -149,21 +158,28 @@ | |
| 158 | sqlite3_context *context, |
| 159 | int argc, |
| 160 | sqlite3_value **argv |
| 161 | ){ |
| 162 | Search *p = (Search*)sqlite3_user_data(context); |
| 163 | const char **azDoc; |
| 164 | int score; |
| 165 | int i; |
| 166 | |
| 167 | azDoc = fossil_malloc( sizeof(const char*)*(argc+1) ); |
| 168 | for(i=0; i<argc; i++) azDoc[i] = (const char*)sqlite3_value_text(argv[i]); |
| 169 | score = search_score(p, argc, azDoc); |
| 170 | fossil_free(azDoc); |
| 171 | sqlite3_result_int(context, score); |
| 172 | } |
| 173 | |
| 174 | /* |
| 175 | ** Register the "score()" SQL function to score its input text |
| 176 | ** using the given Search object. Once this function is registered, |
| 177 | ** do not delete the Search object. |
| 178 | */ |
| 179 | void search_sql_setup(Search *p){ |
| 180 | sqlite3_create_function(g.db, "score", -1, SQLITE_UTF8, p, |
| 181 | search_score_sqlfunc, 0, 0); |
| 182 | } |
| 183 | |
| 184 | /* |
| 185 | ** Testing the search function. |
| 186 | |
| 187 | DDED src/sitemap.c |
+43
| --- a/src/sitemap.c | ||
| +++ b/src/sitemap.c | ||
| @@ -0,0 +1,43 @@ | ||
| 1 | +avtimeline?n=all&imeline?n=all& @ warps"))List of "Timewarp" Check-inTest Pages </ul></li>body_and_footer("sitemap"); | |
| 2 | + } | |
| 3 | +} | |
| 4 | +footer(); | |
| 5 | + } | |
| 6 | +} | |
| 7 | +?name=Sandbox"))SandboxHelphelp"))List of All Commands and Web@mimetype map1style_header("Site Map"); | |
| 8 | +style_footer(); | |
| 9 | +} | |
| 10 | +divul id="sitemap"> | |
| 11 | +</div> | |
| 12 | + style_footer(); | |
| 13 | +} | |
| 14 | +</librlist"))Branchesaglist"))TagsdTktli> | |
| 15 | + style_footer(); | |
| 16 | +} | |
| 17 | +?n=200} | |
| 18 | +line?n=all& @ warps"))List of "Timewarp" Check-inTest Pages </ul></li>body_and_footer("sitemap"); | |
| 19 | + } | |
| 20 | +} | |
| 21 | +footer(); | |
| 22 | + } | |
| 23 | +} | |
| 24 | +?name=Sandboxavtimeline?n=all&imeline?n=all& @ warps"))List of "Timewarp" Check-inTest Pages </ul></li>body_and_footer("sitemap"); | |
| 25 | + } | |
| 26 | +} | |
| 27 | +footer(); | |
| 28 | + @ </p> | |
| 29 | + @ | |
| 30 | +#endifq@N6,W@Rh,X@1B~,b:docsrch"))Search Project DocumeShow an incomplete list of@Uy,q@gW,7O@aw,c@linkest_li> | |
| 31 | + @ <ul>docsrc@ </@@ @ warps"))List of "Timewaavtimeline?n=all&imeline?n=aln=all&namechng"))All check-in@ </@@ </ul> | |
| 32 | + @ </liwi</a> | |
| 33 | + @ <ul> | |
| 34 | +q@N6,W@Rh,X@1B~,b:docsrch"))Se@ omplete list o@ @ warps"))List of "avtimelinew@ @ @ @ @ </ul> | |
| 35 | + @ </li@ </ul> | |
| 36 | + @ </liblobrtifacts</a></li> | |
| 37 | + in<ultree?Branches and Tags</a> | |
| 38 | + @ <uls"))List of "avtimelinew@ @ @ @ @ </ul> | |
| 39 | + @ </li@ </ul> | |
| 40 | + @ </liblobrtifactseline?n=aln=all&namechng"))All cul> | |
| 41 | +q@N6,W@Rh,X@1B~,b:docsrch"))Se@ omplete list o@ @ warps"))List of "avtimelinew@ @ @ @ @ </ul> | |
| 42 | + @ </li@ </ul> | |
| 43 | + @ </liblobrtifactsstat"))Status SummaAdministration0 |
| --- a/src/sitemap.c | |
| +++ b/src/sitemap.c | |
| @@ -0,0 +1,43 @@ | |
| --- a/src/sitemap.c | |
| +++ b/src/sitemap.c | |
| @@ -0,0 +1,43 @@ | |
| 1 | avtimeline?n=all&imeline?n=all& @ warps"))List of "Timewarp" Check-inTest Pages </ul></li>body_and_footer("sitemap"); |
| 2 | } |
| 3 | } |
| 4 | footer(); |
| 5 | } |
| 6 | } |
| 7 | ?name=Sandbox"))SandboxHelphelp"))List of All Commands and Web@mimetype map1style_header("Site Map"); |
| 8 | style_footer(); |
| 9 | } |
| 10 | divul id="sitemap"> |
| 11 | </div> |
| 12 | style_footer(); |
| 13 | } |
| 14 | </librlist"))Branchesaglist"))TagsdTktli> |
| 15 | style_footer(); |
| 16 | } |
| 17 | ?n=200} |
| 18 | line?n=all& @ warps"))List of "Timewarp" Check-inTest Pages </ul></li>body_and_footer("sitemap"); |
| 19 | } |
| 20 | } |
| 21 | footer(); |
| 22 | } |
| 23 | } |
| 24 | ?name=Sandboxavtimeline?n=all&imeline?n=all& @ warps"))List of "Timewarp" Check-inTest Pages </ul></li>body_and_footer("sitemap"); |
| 25 | } |
| 26 | } |
| 27 | footer(); |
| 28 | @ </p> |
| 29 | @ |
| 30 | #endifq@N6,W@Rh,X@1B~,b:docsrch"))Search Project DocumeShow an incomplete list of@Uy,q@gW,7O@aw,c@linkest_li> |
| 31 | @ <ul>docsrc@ </@@ @ warps"))List of "Timewaavtimeline?n=all&imeline?n=aln=all&namechng"))All check-in@ </@@ </ul> |
| 32 | @ </liwi</a> |
| 33 | @ <ul> |
| 34 | q@N6,W@Rh,X@1B~,b:docsrch"))Se@ omplete list o@ @ warps"))List of "avtimelinew@ @ @ @ @ </ul> |
| 35 | @ </li@ </ul> |
| 36 | @ </liblobrtifacts</a></li> |
| 37 | in<ultree?Branches and Tags</a> |
| 38 | @ <uls"))List of "avtimelinew@ @ @ @ @ </ul> |
| 39 | @ </li@ </ul> |
| 40 | @ </liblobrtifactseline?n=aln=all&namechng"))All cul> |
| 41 | q@N6,W@Rh,X@1B~,b:docsrch"))Se@ omplete list o@ @ warps"))List of "avtimelinew@ @ @ @ @ </ul> |
| 42 | @ </li@ </ul> |
| 43 | @ </liblobrtifactsstat"))Status SummaAdministration0 |
+328
-234
| --- src/sqlite3.c | ||
| +++ src/sqlite3.c | ||
| @@ -231,11 +231,11 @@ | ||
| 231 | 231 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 232 | 232 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 233 | 233 | */ |
| 234 | 234 | #define SQLITE_VERSION "3.8.8" |
| 235 | 235 | #define SQLITE_VERSION_NUMBER 3008008 |
| 236 | -#define SQLITE_SOURCE_ID "2014-12-06 14:56:49 6aeece19a235344be2537e66a3fe08b1febfb5a0" | |
| 236 | +#define SQLITE_SOURCE_ID "2015-01-03 18:59:17 23d4c07eb81db5a5c6beb56b5820f0b6501f1fb6" | |
| 237 | 237 | |
| 238 | 238 | /* |
| 239 | 239 | ** CAPI3REF: Run-Time Library Version Numbers |
| 240 | 240 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 241 | 241 | ** |
| @@ -323,11 +323,11 @@ | ||
| 323 | 323 | ** This interface only reports on the compile-time mutex setting |
| 324 | 324 | ** of the [SQLITE_THREADSAFE] flag. If SQLite is compiled with |
| 325 | 325 | ** SQLITE_THREADSAFE=1 or =2 then mutexes are enabled by default but |
| 326 | 326 | ** can be fully or partially disabled using a call to [sqlite3_config()] |
| 327 | 327 | ** with the verbs [SQLITE_CONFIG_SINGLETHREAD], [SQLITE_CONFIG_MULTITHREAD], |
| 328 | -** or [SQLITE_CONFIG_MUTEX]. ^(The return value of the | |
| 328 | +** or [SQLITE_CONFIG_SERIALIZED]. ^(The return value of the | |
| 329 | 329 | ** sqlite3_threadsafe() function shows only the compile-time setting of |
| 330 | 330 | ** thread safety, not any run-time changes to that setting made by |
| 331 | 331 | ** sqlite3_config(). In other words, the return value from sqlite3_threadsafe() |
| 332 | 332 | ** is unchanged by calls to sqlite3_config().)^ |
| 333 | 333 | ** |
| @@ -1692,11 +1692,11 @@ | ||
| 1692 | 1692 | ** configuration option. |
| 1693 | 1693 | ** ^There are three arguments to SQLITE_CONFIG_PAGECACHE: A pointer to |
| 1694 | 1694 | ** 8-byte aligned |
| 1695 | 1695 | ** memory, the size of each page buffer (sz), and the number of pages (N). |
| 1696 | 1696 | ** The sz argument should be the size of the largest database page |
| 1697 | -** (a power of two between 512 and 32768) plus some extra bytes for each | |
| 1697 | +** (a power of two between 512 and 65536) plus some extra bytes for each | |
| 1698 | 1698 | ** page header. ^The number of extra bytes needed by the page header |
| 1699 | 1699 | ** can be determined using the [SQLITE_CONFIG_PCACHE_HDRSZ] option |
| 1700 | 1700 | ** to [sqlite3_config()]. |
| 1701 | 1701 | ** ^It is harmless, apart from the wasted memory, |
| 1702 | 1702 | ** for the sz parameter to be larger than necessary. The first |
| @@ -1872,10 +1872,21 @@ | ||
| 1872 | 1872 | ** <dd>^The SQLITE_CONFIG_PCACHE_HDRSZ option takes a single parameter which |
| 1873 | 1873 | ** is a pointer to an integer and writes into that integer the number of extra |
| 1874 | 1874 | ** bytes per page required for each page in [SQLITE_CONFIG_PAGECACHE]. |
| 1875 | 1875 | ** The amount of extra space required can change depending on the compiler, |
| 1876 | 1876 | ** target platform, and SQLite version. |
| 1877 | +** | |
| 1878 | +** [[SQLITE_CONFIG_PMASZ]] | |
| 1879 | +** <dt>SQLITE_CONFIG_PMASZ | |
| 1880 | +** <dd>^The SQLITE_CONFIG_PMASZ option takes a single parameter which | |
| 1881 | +** is an unsigned integer and sets the "Minimum PMA Size" for the multithreaded | |
| 1882 | +** sorter to that integer. The default minimum PMA Size is set by the | |
| 1883 | +** [SQLITE_SORTER_PMASZ] compile-time option. New threads are launched | |
| 1884 | +** to help with sort operations when multithreaded sorting | |
| 1885 | +** is enabled (using the [PRAGMA threads] command) and the amount of content | |
| 1886 | +** to be sorted exceeds the page size times the minimum of the | |
| 1887 | +** [PRAGMA cache_size] setting and this value. | |
| 1877 | 1888 | ** </dl> |
| 1878 | 1889 | */ |
| 1879 | 1890 | #define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */ |
| 1880 | 1891 | #define SQLITE_CONFIG_MULTITHREAD 2 /* nil */ |
| 1881 | 1892 | #define SQLITE_CONFIG_SERIALIZED 3 /* nil */ |
| @@ -1898,10 +1909,11 @@ | ||
| 1898 | 1909 | #define SQLITE_CONFIG_COVERING_INDEX_SCAN 20 /* int */ |
| 1899 | 1910 | #define SQLITE_CONFIG_SQLLOG 21 /* xSqllog, void* */ |
| 1900 | 1911 | #define SQLITE_CONFIG_MMAP_SIZE 22 /* sqlite3_int64, sqlite3_int64 */ |
| 1901 | 1912 | #define SQLITE_CONFIG_WIN32_HEAPSIZE 23 /* int nByte */ |
| 1902 | 1913 | #define SQLITE_CONFIG_PCACHE_HDRSZ 24 /* int *psz */ |
| 1914 | +#define SQLITE_CONFIG_PMASZ 25 /* unsigned int szPma */ | |
| 1903 | 1915 | |
| 1904 | 1916 | /* |
| 1905 | 1917 | ** CAPI3REF: Database Connection Configuration Options |
| 1906 | 1918 | ** |
| 1907 | 1919 | ** These constants are the available integer configuration options that |
| @@ -5279,24 +5291,31 @@ | ||
| 5279 | 5291 | |
| 5280 | 5292 | |
| 5281 | 5293 | /* |
| 5282 | 5294 | ** CAPI3REF: Extract Metadata About A Column Of A Table |
| 5283 | 5295 | ** |
| 5284 | -** ^This routine returns metadata about a specific column of a specific | |
| 5285 | -** database table accessible using the [database connection] handle | |
| 5286 | -** passed as the first function argument. | |
| 5296 | +** ^(The sqlite3_table_column_metadata(X,D,T,C,....) routine returns | |
| 5297 | +** information about column C of table T in database D | |
| 5298 | +** on [database connection] X.)^ ^The sqlite3_table_column_metadata() | |
| 5299 | +** interface returns SQLITE_OK and fills in the non-NULL pointers in | |
| 5300 | +** the final five arguments with appropriate values if the specified | |
| 5301 | +** column exists. ^The sqlite3_table_column_metadata() interface returns | |
| 5302 | +** SQLITE_ERROR and if the specified column does not exist. | |
| 5303 | +** ^If the column-name parameter to sqlite3_table_column_metadata() is a | |
| 5304 | +** NULL pointer, then this routine simply checks for the existance of the | |
| 5305 | +** table and returns SQLITE_OK if the table exists and SQLITE_ERROR if it | |
| 5306 | +** does not. | |
| 5287 | 5307 | ** |
| 5288 | 5308 | ** ^The column is identified by the second, third and fourth parameters to |
| 5289 | -** this function. ^The second parameter is either the name of the database | |
| 5309 | +** this function. ^(The second parameter is either the name of the database | |
| 5290 | 5310 | ** (i.e. "main", "temp", or an attached database) containing the specified |
| 5291 | -** table or NULL. ^If it is NULL, then all attached databases are searched | |
| 5311 | +** table or NULL.)^ ^If it is NULL, then all attached databases are searched | |
| 5292 | 5312 | ** for the table using the same algorithm used by the database engine to |
| 5293 | 5313 | ** resolve unqualified table references. |
| 5294 | 5314 | ** |
| 5295 | 5315 | ** ^The third and fourth parameters to this function are the table and column |
| 5296 | -** name of the desired column, respectively. Neither of these parameters | |
| 5297 | -** may be NULL. | |
| 5316 | +** name of the desired column, respectively. | |
| 5298 | 5317 | ** |
| 5299 | 5318 | ** ^Metadata is returned by writing to the memory locations passed as the 5th |
| 5300 | 5319 | ** and subsequent parameters to this function. ^Any of these arguments may be |
| 5301 | 5320 | ** NULL, in which case the corresponding element of metadata is omitted. |
| 5302 | 5321 | ** |
| @@ -5311,36 +5330,33 @@ | ||
| 5311 | 5330 | ** <tr><td> 9th <td> int <td> True if column is [AUTOINCREMENT] |
| 5312 | 5331 | ** </table> |
| 5313 | 5332 | ** </blockquote>)^ |
| 5314 | 5333 | ** |
| 5315 | 5334 | ** ^The memory pointed to by the character pointers returned for the |
| 5316 | -** declaration type and collation sequence is valid only until the next | |
| 5335 | +** declaration type and collation sequence is valid until the next | |
| 5317 | 5336 | ** call to any SQLite API function. |
| 5318 | 5337 | ** |
| 5319 | 5338 | ** ^If the specified table is actually a view, an [error code] is returned. |
| 5320 | 5339 | ** |
| 5321 | -** ^If the specified column is "rowid", "oid" or "_rowid_" and an | |
| 5340 | +** ^If the specified column is "rowid", "oid" or "_rowid_" and the table | |
| 5341 | +** is not a [WITHOUT ROWID] table and an | |
| 5322 | 5342 | ** [INTEGER PRIMARY KEY] column has been explicitly declared, then the output |
| 5323 | 5343 | ** parameters are set for the explicitly declared column. ^(If there is no |
| 5324 | -** explicitly declared [INTEGER PRIMARY KEY] column, then the output | |
| 5325 | -** parameters are set as follows: | |
| 5344 | +** [INTEGER PRIMARY KEY] column, then the outputs | |
| 5345 | +** for the [rowid] are set as follows: | |
| 5326 | 5346 | ** |
| 5327 | 5347 | ** <pre> |
| 5328 | 5348 | ** data type: "INTEGER" |
| 5329 | 5349 | ** collation sequence: "BINARY" |
| 5330 | 5350 | ** not null: 0 |
| 5331 | 5351 | ** primary key: 1 |
| 5332 | 5352 | ** auto increment: 0 |
| 5333 | 5353 | ** </pre>)^ |
| 5334 | 5354 | ** |
| 5335 | -** ^(This function may load one or more schemas from database files. If an | |
| 5336 | -** error occurs during this process, or if the requested table or column | |
| 5337 | -** cannot be found, an [error code] is returned and an error message left | |
| 5338 | -** in the [database connection] (to be retrieved using sqlite3_errmsg()).)^ | |
| 5339 | -** | |
| 5340 | -** ^This API is only available if the library was compiled with the | |
| 5341 | -** [SQLITE_ENABLE_COLUMN_METADATA] C-preprocessor symbol defined. | |
| 5355 | +** ^This function causes all database schemas to be read from disk and | |
| 5356 | +** parsed, if that has not already been done, and returns an error if | |
| 5357 | +** any errors are encountered while loading the schema. | |
| 5342 | 5358 | */ |
| 5343 | 5359 | SQLITE_API int sqlite3_table_column_metadata( |
| 5344 | 5360 | sqlite3 *db, /* Connection handle */ |
| 5345 | 5361 | const char *zDbName, /* Database name or NULL */ |
| 5346 | 5362 | const char *zTableName, /* Table name */ |
| @@ -7303,16 +7319,14 @@ | ||
| 7303 | 7319 | |
| 7304 | 7320 | /* |
| 7305 | 7321 | ** CAPI3REF: Write-Ahead Log Commit Hook |
| 7306 | 7322 | ** |
| 7307 | 7323 | ** ^The [sqlite3_wal_hook()] function is used to register a callback that |
| 7308 | -** will be invoked each time a database connection commits data to a | |
| 7309 | -** [write-ahead log] (i.e. whenever a transaction is committed in | |
| 7310 | -** [journal_mode | journal_mode=WAL mode]). | |
| 7324 | +** is invoked each time data is committed to a database in wal mode. | |
| 7311 | 7325 | ** |
| 7312 | -** ^The callback is invoked by SQLite after the commit has taken place and | |
| 7313 | -** the associated write-lock on the database released, so the implementation | |
| 7326 | +** ^(The callback is invoked by SQLite after the commit has taken place and | |
| 7327 | +** the associated write-lock on the database released)^, so the implementation | |
| 7314 | 7328 | ** may read, write or [checkpoint] the database as required. |
| 7315 | 7329 | ** |
| 7316 | 7330 | ** ^The first parameter passed to the callback function when it is invoked |
| 7317 | 7331 | ** is a copy of the third parameter passed to sqlite3_wal_hook() when |
| 7318 | 7332 | ** registering the callback. ^The second is a copy of the database handle. |
| @@ -9096,11 +9110,11 @@ | ||
| 9096 | 9110 | #define _BTREE_H_ |
| 9097 | 9111 | |
| 9098 | 9112 | /* TODO: This definition is just included so other modules compile. It |
| 9099 | 9113 | ** needs to be revisited. |
| 9100 | 9114 | */ |
| 9101 | -#define SQLITE_N_BTREE_META 10 | |
| 9115 | +#define SQLITE_N_BTREE_META 16 | |
| 9102 | 9116 | |
| 9103 | 9117 | /* |
| 9104 | 9118 | ** If defined as non-zero, auto-vacuum is enabled by default. Otherwise |
| 9105 | 9119 | ** it must be turned on for each database using "PRAGMA auto_vacuum = 1". |
| 9106 | 9120 | */ |
| @@ -9211,10 +9225,15 @@ | ||
| 9211 | 9225 | ** offset = 36 + (idx * 4) |
| 9212 | 9226 | ** |
| 9213 | 9227 | ** For example, the free-page-count field is located at byte offset 36 of |
| 9214 | 9228 | ** the database file header. The incr-vacuum-flag field is located at |
| 9215 | 9229 | ** byte offset 64 (== 36+4*7). |
| 9230 | +** | |
| 9231 | +** The BTREE_DATA_VERSION value is not really a value stored in the header. | |
| 9232 | +** It is a read-only number computed by the pager. But we merge it with | |
| 9233 | +** the header value access routines since its access pattern is the same. | |
| 9234 | +** Call it a "virtual meta value". | |
| 9216 | 9235 | */ |
| 9217 | 9236 | #define BTREE_FREE_PAGE_COUNT 0 |
| 9218 | 9237 | #define BTREE_SCHEMA_VERSION 1 |
| 9219 | 9238 | #define BTREE_FILE_FORMAT 2 |
| 9220 | 9239 | #define BTREE_DEFAULT_CACHE_SIZE 3 |
| @@ -9221,10 +9240,11 @@ | ||
| 9221 | 9240 | #define BTREE_LARGEST_ROOT_PAGE 4 |
| 9222 | 9241 | #define BTREE_TEXT_ENCODING 5 |
| 9223 | 9242 | #define BTREE_USER_VERSION 6 |
| 9224 | 9243 | #define BTREE_INCR_VACUUM 7 |
| 9225 | 9244 | #define BTREE_APPLICATION_ID 8 |
| 9245 | +#define BTREE_DATA_VERSION 15 /* A virtual meta-value */ | |
| 9226 | 9246 | |
| 9227 | 9247 | /* |
| 9228 | 9248 | ** Values that may be OR'd together to form the second argument of an |
| 9229 | 9249 | ** sqlite3BtreeCursorHints() call. |
| 9230 | 9250 | */ |
| @@ -10002,10 +10022,11 @@ | ||
| 10002 | 10022 | SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager); |
| 10003 | 10023 | #endif |
| 10004 | 10024 | |
| 10005 | 10025 | /* Functions used to query pager state and configuration. */ |
| 10006 | 10026 | SQLITE_PRIVATE u8 sqlite3PagerIsreadonly(Pager*); |
| 10027 | +SQLITE_PRIVATE u32 sqlite3PagerDataVersion(Pager*); | |
| 10007 | 10028 | SQLITE_PRIVATE int sqlite3PagerRefcount(Pager*); |
| 10008 | 10029 | SQLITE_PRIVATE int sqlite3PagerMemUsed(Pager*); |
| 10009 | 10030 | SQLITE_PRIVATE const char *sqlite3PagerFilename(Pager*, int); |
| 10010 | 10031 | SQLITE_PRIVATE const sqlite3_vfs *sqlite3PagerVfs(Pager*); |
| 10011 | 10032 | SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager*); |
| @@ -10743,10 +10764,11 @@ | ||
| 10743 | 10764 | i64 szMmap; /* Default mmap_size setting */ |
| 10744 | 10765 | unsigned int openFlags; /* Flags passed to sqlite3_vfs.xOpen() */ |
| 10745 | 10766 | int errCode; /* Most recent error code (SQLITE_*) */ |
| 10746 | 10767 | int errMask; /* & result codes with this before returning */ |
| 10747 | 10768 | u16 dbOptFlags; /* Flags to enable/disable optimizations */ |
| 10769 | + u8 enc; /* Text encoding */ | |
| 10748 | 10770 | u8 autoCommit; /* The auto-commit flag. */ |
| 10749 | 10771 | u8 temp_store; /* 1: file 2: memory 0: default */ |
| 10750 | 10772 | u8 mallocFailed; /* True if we have seen a malloc failure */ |
| 10751 | 10773 | u8 dfltLockMode; /* Default locking-mode for attached dbs */ |
| 10752 | 10774 | signed char nextAutovac; /* Autovac setting after VACUUM if >=0 */ |
| @@ -10844,11 +10866,12 @@ | ||
| 10844 | 10866 | }; |
| 10845 | 10867 | |
| 10846 | 10868 | /* |
| 10847 | 10869 | ** A macro to discover the encoding of a database. |
| 10848 | 10870 | */ |
| 10849 | -#define ENC(db) ((db)->aDb[0].pSchema->enc) | |
| 10871 | +#define SCHEMA_ENC(db) ((db)->aDb[0].pSchema->enc) | |
| 10872 | +#define ENC(db) ((db)->enc) | |
| 10850 | 10873 | |
| 10851 | 10874 | /* |
| 10852 | 10875 | ** Possible values for the sqlite3.flags. |
| 10853 | 10876 | */ |
| 10854 | 10877 | #define SQLITE_VdbeTrace 0x00000001 /* True to trace VDBE execution */ |
| @@ -11468,11 +11491,10 @@ | ||
| 11468 | 11491 | Index *pNext; /* The next index associated with the same table */ |
| 11469 | 11492 | Schema *pSchema; /* Schema containing this index */ |
| 11470 | 11493 | u8 *aSortOrder; /* for each column: True==DESC, False==ASC */ |
| 11471 | 11494 | char **azColl; /* Array of collation sequence names for index */ |
| 11472 | 11495 | Expr *pPartIdxWhere; /* WHERE clause for partial indices */ |
| 11473 | - KeyInfo *pKeyInfo; /* A KeyInfo object suitable for this index */ | |
| 11474 | 11496 | int tnum; /* DB Page containing root of this index */ |
| 11475 | 11497 | LogEst szIdxRow; /* Estimated average row size in bytes */ |
| 11476 | 11498 | u16 nKeyCol; /* Number of columns forming the key */ |
| 11477 | 11499 | u16 nColumn; /* Number of columns stored in the index */ |
| 11478 | 11500 | u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */ |
| @@ -12522,10 +12544,11 @@ | ||
| 12522 | 12544 | void *pPage; /* Page cache memory */ |
| 12523 | 12545 | int szPage; /* Size of each page in pPage[] */ |
| 12524 | 12546 | int nPage; /* Number of pages in pPage[] */ |
| 12525 | 12547 | int mxParserStack; /* maximum depth of the parser stack */ |
| 12526 | 12548 | int sharedCacheEnabled; /* true if shared-cache mode enabled */ |
| 12549 | + u32 szPma; /* Maximum Sorter PMA size */ | |
| 12527 | 12550 | /* The above might be initialized to non-zero. The following need to always |
| 12528 | 12551 | ** initially be zero, however. */ |
| 12529 | 12552 | int isInit; /* True after initialization has finished */ |
| 12530 | 12553 | int inProgress; /* True while initialization in progress */ |
| 12531 | 12554 | int isMutexInit; /* True after mutexes are initialized */ |
| @@ -13444,11 +13467,11 @@ | ||
| 13444 | 13467 | ** print I/O tracing messages. |
| 13445 | 13468 | */ |
| 13446 | 13469 | #ifdef SQLITE_ENABLE_IOTRACE |
| 13447 | 13470 | # define IOTRACE(A) if( sqlite3IoTrace ){ sqlite3IoTrace A; } |
| 13448 | 13471 | SQLITE_PRIVATE void sqlite3VdbeIOTraceSql(Vdbe*); |
| 13449 | -SQLITE_PRIVATE void (*sqlite3IoTrace)(const char*,...); | |
| 13472 | +void (*sqlite3IoTrace)(const char*,...); | |
| 13450 | 13473 | #else |
| 13451 | 13474 | # define IOTRACE(A) |
| 13452 | 13475 | # define sqlite3VdbeIOTraceSql(X) |
| 13453 | 13476 | #endif |
| 13454 | 13477 | |
| @@ -13657,10 +13680,17 @@ | ||
| 13657 | 13680 | */ |
| 13658 | 13681 | #ifndef SQLITE_ALLOW_COVERING_INDEX_SCAN |
| 13659 | 13682 | # define SQLITE_ALLOW_COVERING_INDEX_SCAN 1 |
| 13660 | 13683 | #endif |
| 13661 | 13684 | |
| 13685 | +/* The minimum PMA size is set to this value multiplied by the database | |
| 13686 | +** page size in bytes. | |
| 13687 | +*/ | |
| 13688 | +#ifndef SQLITE_SORTER_PMASZ | |
| 13689 | +# define SQLITE_SORTER_PMASZ 250 | |
| 13690 | +#endif | |
| 13691 | + | |
| 13662 | 13692 | /* |
| 13663 | 13693 | ** The following singleton contains the global configuration for |
| 13664 | 13694 | ** the SQLite library. |
| 13665 | 13695 | */ |
| 13666 | 13696 | SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = { |
| @@ -13687,10 +13717,11 @@ | ||
| 13687 | 13717 | (void*)0, /* pPage */ |
| 13688 | 13718 | 0, /* szPage */ |
| 13689 | 13719 | 0, /* nPage */ |
| 13690 | 13720 | 0, /* mxParserStack */ |
| 13691 | 13721 | 0, /* sharedCacheEnabled */ |
| 13722 | + SQLITE_SORTER_PMASZ, /* szPma */ | |
| 13692 | 13723 | /* All the rest should always be initialized to zero */ |
| 13693 | 13724 | 0, /* isInit */ |
| 13694 | 13725 | 0, /* inProgress */ |
| 13695 | 13726 | 0, /* isMutexInit */ |
| 13696 | 13727 | 0, /* isMallocInit */ |
| @@ -19972,10 +20003,16 @@ | ||
| 19972 | 20003 | #endif |
| 19973 | 20004 | } |
| 19974 | 20005 | break; |
| 19975 | 20006 | } |
| 19976 | 20007 | default: { |
| 20008 | +#ifdef SQLITE_ENABLE_API_ARMOR | |
| 20009 | + if( iType-2<0 || iType-2>=ArraySize(winMutex_staticMutexes) ){ | |
| 20010 | + (void)SQLITE_MISUSE_BKPT; | |
| 20011 | + return 0; | |
| 20012 | + } | |
| 20013 | +#endif | |
| 19977 | 20014 | assert( iType-2 >= 0 ); |
| 19978 | 20015 | assert( iType-2 < ArraySize(winMutex_staticMutexes) ); |
| 19979 | 20016 | assert( winMutex_isInit==1 ); |
| 19980 | 20017 | p = &winMutex_staticMutexes[iType-2]; |
| 19981 | 20018 | #ifdef SQLITE_DEBUG |
| @@ -28779,28 +28816,31 @@ | ||
| 28779 | 28816 | do{ |
| 28780 | 28817 | err = osFallocate(pFile->h, buf.st_size, nSize-buf.st_size); |
| 28781 | 28818 | }while( err==EINTR ); |
| 28782 | 28819 | if( err ) return SQLITE_IOERR_WRITE; |
| 28783 | 28820 | #else |
| 28784 | - /* If the OS does not have posix_fallocate(), fake it. First use | |
| 28785 | - ** ftruncate() to set the file size, then write a single byte to | |
| 28786 | - ** the last byte in each block within the extended region. This | |
| 28787 | - ** is the same technique used by glibc to implement posix_fallocate() | |
| 28788 | - ** on systems that do not have a real fallocate() system call. | |
| 28821 | + /* If the OS does not have posix_fallocate(), fake it. Write a | |
| 28822 | + ** single byte to the last byte in each block that falls entirely | |
| 28823 | + ** within the extended region. Then, if required, a single byte | |
| 28824 | + ** at offset (nSize-1), to set the size of the file correctly. | |
| 28825 | + ** This is a similar technique to that used by glibc on systems | |
| 28826 | + ** that do not have a real fallocate() call. | |
| 28789 | 28827 | */ |
| 28790 | 28828 | int nBlk = buf.st_blksize; /* File-system block size */ |
| 28791 | 28829 | i64 iWrite; /* Next offset to write to */ |
| 28792 | 28830 | |
| 28793 | - if( robust_ftruncate(pFile->h, nSize) ){ | |
| 28794 | - pFile->lastErrno = errno; | |
| 28795 | - return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath); | |
| 28796 | - } | |
| 28797 | 28831 | iWrite = ((buf.st_size + 2*nBlk - 1)/nBlk)*nBlk-1; |
| 28798 | - while( iWrite<nSize ){ | |
| 28832 | + assert( iWrite>=buf.st_size ); | |
| 28833 | + assert( (iWrite/nBlk)==((buf.st_size+nBlk-1)/nBlk) ); | |
| 28834 | + assert( ((iWrite+1)%nBlk)==0 ); | |
| 28835 | + for(/*no-op*/; iWrite<nSize; iWrite+=nBlk ){ | |
| 28799 | 28836 | int nWrite = seekAndWrite(pFile, iWrite, "", 1); |
| 28800 | 28837 | if( nWrite!=1 ) return SQLITE_IOERR_WRITE; |
| 28801 | - iWrite += nBlk; | |
| 28838 | + } | |
| 28839 | + if( nSize%nBlk ){ | |
| 28840 | + int nWrite = seekAndWrite(pFile, nSize-1, "", 1); | |
| 28841 | + if( nWrite!=1 ) return SQLITE_IOERR_WRITE; | |
| 28802 | 28842 | } |
| 28803 | 28843 | #endif |
| 28804 | 28844 | } |
| 28805 | 28845 | } |
| 28806 | 28846 | |
| @@ -34014,12 +34054,12 @@ | ||
| 34014 | 34054 | */ |
| 34015 | 34055 | SQLITE_API int sqlite3_win32_reset_heap(){ |
| 34016 | 34056 | int rc; |
| 34017 | 34057 | MUTEX_LOGIC( sqlite3_mutex *pMaster; ) /* The main static mutex */ |
| 34018 | 34058 | MUTEX_LOGIC( sqlite3_mutex *pMem; ) /* The memsys static mutex */ |
| 34019 | - MUTEX_LOGIC( pMaster = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); ) | |
| 34020 | - MUTEX_LOGIC( pMem = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM); ) | |
| 34059 | + MUTEX_LOGIC( pMaster = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER); ) | |
| 34060 | + MUTEX_LOGIC( pMem = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM); ) | |
| 34021 | 34061 | sqlite3_mutex_enter(pMaster); |
| 34022 | 34062 | sqlite3_mutex_enter(pMem); |
| 34023 | 34063 | winMemAssertMagic(); |
| 34024 | 34064 | if( winMemGetHeap()!=NULL && winMemGetOwned() && sqlite3_memory_used()==0 ){ |
| 34025 | 34065 | /* |
| @@ -35290,11 +35330,11 @@ | ||
| 35290 | 35330 | sqlite3_file *id, /* File to read from */ |
| 35291 | 35331 | void *pBuf, /* Write content into this buffer */ |
| 35292 | 35332 | int amt, /* Number of bytes to read */ |
| 35293 | 35333 | sqlite3_int64 offset /* Begin reading at this offset */ |
| 35294 | 35334 | ){ |
| 35295 | -#if !SQLITE_OS_WINCE | |
| 35335 | +#if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_OVERLAPPED) | |
| 35296 | 35336 | OVERLAPPED overlapped; /* The offset for ReadFile. */ |
| 35297 | 35337 | #endif |
| 35298 | 35338 | winFile *pFile = (winFile*)id; /* file handle */ |
| 35299 | 35339 | DWORD nRead; /* Number of bytes actually read from file */ |
| 35300 | 35340 | int nRetry = 0; /* Number of retrys */ |
| @@ -35322,11 +35362,11 @@ | ||
| 35322 | 35362 | offset += nCopy; |
| 35323 | 35363 | } |
| 35324 | 35364 | } |
| 35325 | 35365 | #endif |
| 35326 | 35366 | |
| 35327 | -#if SQLITE_OS_WINCE | |
| 35367 | +#if SQLITE_OS_WINCE || defined(SQLITE_WIN32_NO_OVERLAPPED) | |
| 35328 | 35368 | if( winSeekFile(pFile, offset) ){ |
| 35329 | 35369 | OSTRACE(("READ file=%p, rc=SQLITE_FULL\n", pFile->h)); |
| 35330 | 35370 | return SQLITE_FULL; |
| 35331 | 35371 | } |
| 35332 | 35372 | while( !osReadFile(pFile->h, pBuf, amt, &nRead, 0) ){ |
| @@ -35394,32 +35434,32 @@ | ||
| 35394 | 35434 | offset += nCopy; |
| 35395 | 35435 | } |
| 35396 | 35436 | } |
| 35397 | 35437 | #endif |
| 35398 | 35438 | |
| 35399 | -#if SQLITE_OS_WINCE | |
| 35439 | +#if SQLITE_OS_WINCE || defined(SQLITE_WIN32_NO_OVERLAPPED) | |
| 35400 | 35440 | rc = winSeekFile(pFile, offset); |
| 35401 | 35441 | if( rc==0 ){ |
| 35402 | 35442 | #else |
| 35403 | 35443 | { |
| 35404 | 35444 | #endif |
| 35405 | -#if !SQLITE_OS_WINCE | |
| 35445 | +#if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_OVERLAPPED) | |
| 35406 | 35446 | OVERLAPPED overlapped; /* The offset for WriteFile. */ |
| 35407 | 35447 | #endif |
| 35408 | 35448 | u8 *aRem = (u8 *)pBuf; /* Data yet to be written */ |
| 35409 | 35449 | int nRem = amt; /* Number of bytes yet to be written */ |
| 35410 | 35450 | DWORD nWrite; /* Bytes written by each WriteFile() call */ |
| 35411 | 35451 | DWORD lastErrno = NO_ERROR; /* Value returned by GetLastError() */ |
| 35412 | 35452 | |
| 35413 | -#if !SQLITE_OS_WINCE | |
| 35453 | +#if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_OVERLAPPED) | |
| 35414 | 35454 | memset(&overlapped, 0, sizeof(OVERLAPPED)); |
| 35415 | 35455 | overlapped.Offset = (LONG)(offset & 0xffffffff); |
| 35416 | 35456 | overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff); |
| 35417 | 35457 | #endif |
| 35418 | 35458 | |
| 35419 | 35459 | while( nRem>0 ){ |
| 35420 | -#if SQLITE_OS_WINCE | |
| 35460 | +#if SQLITE_OS_WINCE || defined(SQLITE_WIN32_NO_OVERLAPPED) | |
| 35421 | 35461 | if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, 0) ){ |
| 35422 | 35462 | #else |
| 35423 | 35463 | if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, &overlapped) ){ |
| 35424 | 35464 | #endif |
| 35425 | 35465 | if( winRetryIoerr(&nRetry, &lastErrno) ) continue; |
| @@ -35428,11 +35468,11 @@ | ||
| 35428 | 35468 | assert( nWrite==0 || nWrite<=(DWORD)nRem ); |
| 35429 | 35469 | if( nWrite==0 || nWrite>(DWORD)nRem ){ |
| 35430 | 35470 | lastErrno = osGetLastError(); |
| 35431 | 35471 | break; |
| 35432 | 35472 | } |
| 35433 | -#if !SQLITE_OS_WINCE | |
| 35473 | +#if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_OVERLAPPED) | |
| 35434 | 35474 | offset += nWrite; |
| 35435 | 35475 | overlapped.Offset = (LONG)(offset & 0xffffffff); |
| 35436 | 35476 | overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff); |
| 35437 | 35477 | #endif |
| 35438 | 35478 | aRem += nWrite; |
| @@ -38974,11 +39014,12 @@ | ||
| 38974 | 39014 | SQLITE_PRIVATE int sqlite3PcacheSetPageSize(PCache *pCache, int szPage){ |
| 38975 | 39015 | assert( pCache->nRef==0 && pCache->pDirty==0 ); |
| 38976 | 39016 | if( pCache->szPage ){ |
| 38977 | 39017 | sqlite3_pcache *pNew; |
| 38978 | 39018 | pNew = sqlite3GlobalConfig.pcache2.xCreate( |
| 38979 | - szPage, pCache->szExtra + sizeof(PgHdr), pCache->bPurgeable | |
| 39019 | + szPage, pCache->szExtra + ROUND8(sizeof(PgHdr)), | |
| 39020 | + pCache->bPurgeable | |
| 38980 | 39021 | ); |
| 38981 | 39022 | if( pNew==0 ) return SQLITE_NOMEM; |
| 38982 | 39023 | sqlite3GlobalConfig.pcache2.xCachesize(pNew, numberOfCachePages(pCache)); |
| 38983 | 39024 | if( pCache->pCache ){ |
| 38984 | 39025 | sqlite3GlobalConfig.pcache2.xDestroy(pCache->pCache); |
| @@ -39433,11 +39474,11 @@ | ||
| 39433 | 39474 | |
| 39434 | 39475 | /* |
| 39435 | 39476 | ** Return the size of the header added by this middleware layer |
| 39436 | 39477 | ** in the page-cache hierarchy. |
| 39437 | 39478 | */ |
| 39438 | -SQLITE_PRIVATE int sqlite3HeaderSizePcache(void){ return sizeof(PgHdr); } | |
| 39479 | +SQLITE_PRIVATE int sqlite3HeaderSizePcache(void){ return ROUND8(sizeof(PgHdr)); } | |
| 39439 | 39480 | |
| 39440 | 39481 | |
| 39441 | 39482 | #if defined(SQLITE_CHECK_PAGES) || defined(SQLITE_DEBUG) |
| 39442 | 39483 | /* |
| 39443 | 39484 | ** For all dirty pages currently in the cache, invoke the specified |
| @@ -39749,11 +39790,11 @@ | ||
| 39749 | 39790 | pcache1Free(pPg); |
| 39750 | 39791 | sqlite3_free(p); |
| 39751 | 39792 | pPg = 0; |
| 39752 | 39793 | } |
| 39753 | 39794 | #else |
| 39754 | - pPg = pcache1Alloc(sizeof(PgHdr1) + pCache->szPage + pCache->szExtra); | |
| 39795 | + pPg = pcache1Alloc(ROUND8(sizeof(PgHdr1)) + pCache->szPage + pCache->szExtra); | |
| 39755 | 39796 | p = (PgHdr1 *)&((u8 *)pPg)[pCache->szPage]; |
| 39756 | 39797 | #endif |
| 39757 | 39798 | pcache1EnterMutex(pCache->pGroup); |
| 39758 | 39799 | |
| 39759 | 39800 | if( pPg ){ |
| @@ -40437,11 +40478,11 @@ | ||
| 40437 | 40478 | } |
| 40438 | 40479 | |
| 40439 | 40480 | /* |
| 40440 | 40481 | ** Return the size of the header on each page of this PCACHE implementation. |
| 40441 | 40482 | */ |
| 40442 | -SQLITE_PRIVATE int sqlite3HeaderSizePcache1(void){ return sizeof(PgHdr1); } | |
| 40483 | +SQLITE_PRIVATE int sqlite3HeaderSizePcache1(void){ return ROUND8(sizeof(PgHdr1)); } | |
| 40443 | 40484 | |
| 40444 | 40485 | #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT |
| 40445 | 40486 | /* |
| 40446 | 40487 | ** This function is called to free superfluous dynamically allocated memory |
| 40447 | 40488 | ** held by the pager system. Memory in use by any SQLite pager allocated |
| @@ -41795,10 +41836,12 @@ | ||
| 41795 | 41836 | u8 eLock; /* Current lock held on database file */ |
| 41796 | 41837 | u8 changeCountDone; /* Set after incrementing the change-counter */ |
| 41797 | 41838 | u8 setMaster; /* True if a m-j name has been written to jrnl */ |
| 41798 | 41839 | u8 doNotSpill; /* Do not spill the cache when non-zero */ |
| 41799 | 41840 | u8 subjInMemory; /* True to use in-memory sub-journals */ |
| 41841 | + u8 bUseFetch; /* True to use xFetch() */ | |
| 41842 | + u8 hasBeenUsed; /* True if any content previously read from this pager*/ | |
| 41800 | 41843 | Pgno dbSize; /* Number of pages in the database */ |
| 41801 | 41844 | Pgno dbOrigSize; /* dbSize before the current transaction */ |
| 41802 | 41845 | Pgno dbFileSize; /* Number of pages in the database file */ |
| 41803 | 41846 | Pgno dbHintSize; /* Value passed to FCNTL_SIZE_HINT call */ |
| 41804 | 41847 | int errCode; /* One of several kinds of errors */ |
| @@ -41812,13 +41855,13 @@ | ||
| 41812 | 41855 | i64 journalOff; /* Current write offset in the journal file */ |
| 41813 | 41856 | i64 journalHdr; /* Byte offset to previous journal header */ |
| 41814 | 41857 | sqlite3_backup *pBackup; /* Pointer to list of ongoing backup processes */ |
| 41815 | 41858 | PagerSavepoint *aSavepoint; /* Array of active savepoints */ |
| 41816 | 41859 | int nSavepoint; /* Number of elements in aSavepoint[] */ |
| 41860 | + u32 iDataVersion; /* Changes whenever database content changes */ | |
| 41817 | 41861 | char dbFileVers[16]; /* Changes whenever database file changes */ |
| 41818 | 41862 | |
| 41819 | - u8 bUseFetch; /* True to use xFetch() */ | |
| 41820 | 41863 | int nMmapOut; /* Number of mmap pages currently outstanding */ |
| 41821 | 41864 | sqlite3_int64 szMmap; /* Desired maximum mmap size */ |
| 41822 | 41865 | PgHdr *pMmapFreelist; /* List of free mmap page headers (pDirty) */ |
| 41823 | 41866 | /* |
| 41824 | 41867 | ** End of the routinely-changing class members |
| @@ -42830,13 +42873,22 @@ | ||
| 42830 | 42873 | |
| 42831 | 42874 | /* |
| 42832 | 42875 | ** Discard the entire contents of the in-memory page-cache. |
| 42833 | 42876 | */ |
| 42834 | 42877 | static void pager_reset(Pager *pPager){ |
| 42878 | + pPager->iDataVersion++; | |
| 42835 | 42879 | sqlite3BackupRestart(pPager->pBackup); |
| 42836 | 42880 | sqlite3PcacheClear(pPager->pPCache); |
| 42837 | 42881 | } |
| 42882 | + | |
| 42883 | +/* | |
| 42884 | +** Return the pPager->iDataVersion value | |
| 42885 | +*/ | |
| 42886 | +SQLITE_PRIVATE u32 sqlite3PagerDataVersion(Pager *pPager){ | |
| 42887 | + assert( pPager->eState>PAGER_OPEN ); | |
| 42888 | + return pPager->iDataVersion; | |
| 42889 | +} | |
| 42838 | 42890 | |
| 42839 | 42891 | /* |
| 42840 | 42892 | ** Free all structures in the Pager.aSavepoint[] array and set both |
| 42841 | 42893 | ** Pager.aSavepoint and Pager.nSavepoint to zero. Close the sub-journal |
| 42842 | 42894 | ** if it is open and the pager is not in exclusive mode. |
| @@ -45036,11 +45088,11 @@ | ||
| 45036 | 45088 | Pgno pgno, /* Page number */ |
| 45037 | 45089 | void *pData, /* xFetch()'d data for this page */ |
| 45038 | 45090 | PgHdr **ppPage /* OUT: Acquired page object */ |
| 45039 | 45091 | ){ |
| 45040 | 45092 | PgHdr *p; /* Memory mapped page to return */ |
| 45041 | - | |
| 45093 | + | |
| 45042 | 45094 | if( pPager->pMmapFreelist ){ |
| 45043 | 45095 | *ppPage = p = pPager->pMmapFreelist; |
| 45044 | 45096 | pPager->pMmapFreelist = p->pDirty; |
| 45045 | 45097 | p->pDirty = 0; |
| 45046 | 45098 | memset(p->pExtra, 0, pPager->nExtra); |
| @@ -46267,20 +46319,16 @@ | ||
| 46267 | 46319 | assert( (pPager->eLock==SHARED_LOCK) |
| 46268 | 46320 | || (pPager->exclusiveMode && pPager->eLock>SHARED_LOCK) |
| 46269 | 46321 | ); |
| 46270 | 46322 | } |
| 46271 | 46323 | |
| 46272 | - if( !pPager->tempFile && ( | |
| 46273 | - pPager->pBackup | |
| 46274 | - || sqlite3PcachePagecount(pPager->pPCache)>0 | |
| 46275 | - || USEFETCH(pPager) | |
| 46276 | - )){ | |
| 46277 | - /* The shared-lock has just been acquired on the database file | |
| 46278 | - ** and there are already pages in the cache (from a previous | |
| 46279 | - ** read or write transaction). Check to see if the database | |
| 46280 | - ** has been modified. If the database has changed, flush the | |
| 46281 | - ** cache. | |
| 46324 | + if( !pPager->tempFile && pPager->hasBeenUsed ){ | |
| 46325 | + /* The shared-lock has just been acquired then check to | |
| 46326 | + ** see if the database has been modified. If the database has changed, | |
| 46327 | + ** flush the cache. The pPager->hasBeenUsed flag prevents this from | |
| 46328 | + ** occurring on the very first access to a file, in order to save a | |
| 46329 | + ** single unnecessary sqlite3OsRead() call at the start-up. | |
| 46282 | 46330 | ** |
| 46283 | 46331 | ** Database changes is detected by looking at 15 bytes beginning |
| 46284 | 46332 | ** at offset 24 into the file. The first 4 of these 16 bytes are |
| 46285 | 46333 | ** a 32-bit counter that is incremented with each change. The |
| 46286 | 46334 | ** other bytes change randomly with each file change when |
| @@ -46441,10 +46489,11 @@ | ||
| 46441 | 46489 | assert( noContent==0 || bMmapOk==0 ); |
| 46442 | 46490 | |
| 46443 | 46491 | if( pgno==0 ){ |
| 46444 | 46492 | return SQLITE_CORRUPT_BKPT; |
| 46445 | 46493 | } |
| 46494 | + pPager->hasBeenUsed = 1; | |
| 46446 | 46495 | |
| 46447 | 46496 | /* If the pager is in the error state, return an error immediately. |
| 46448 | 46497 | ** Otherwise, request the page from the PCache layer. */ |
| 46449 | 46498 | if( pPager->errCode!=SQLITE_OK ){ |
| 46450 | 46499 | rc = pPager->errCode; |
| @@ -46590,10 +46639,11 @@ | ||
| 46590 | 46639 | sqlite3_pcache_page *pPage; |
| 46591 | 46640 | assert( pPager!=0 ); |
| 46592 | 46641 | assert( pgno!=0 ); |
| 46593 | 46642 | assert( pPager->pPCache!=0 ); |
| 46594 | 46643 | pPage = sqlite3PcacheFetch(pPager->pPCache, pgno, 0); |
| 46644 | + assert( pPage==0 || pPager->hasBeenUsed ); | |
| 46595 | 46645 | return sqlite3PcacheFetchFinish(pPager->pPCache, pgno, pPage); |
| 46596 | 46646 | } |
| 46597 | 46647 | |
| 46598 | 46648 | /* |
| 46599 | 46649 | ** Release a page reference. |
| @@ -47456,10 +47506,11 @@ | ||
| 47456 | 47506 | pPager->eState = PAGER_READER; |
| 47457 | 47507 | return SQLITE_OK; |
| 47458 | 47508 | } |
| 47459 | 47509 | |
| 47460 | 47510 | PAGERTRACE(("COMMIT %d\n", PAGERID(pPager))); |
| 47511 | + pPager->iDataVersion++; | |
| 47461 | 47512 | rc = pager_end_transaction(pPager, pPager->setMaster, 1); |
| 47462 | 47513 | return pager_error(pPager, rc); |
| 47463 | 47514 | } |
| 47464 | 47515 | |
| 47465 | 47516 | /* |
| @@ -50825,11 +50876,11 @@ | ||
| 50825 | 50876 | } |
| 50826 | 50877 | nCollide = HASHTABLE_NSLOT; |
| 50827 | 50878 | for(iKey=walHash(pgno); aHash[iKey]; iKey=walNextHash(iKey)){ |
| 50828 | 50879 | u32 iFrame = aHash[iKey] + iZero; |
| 50829 | 50880 | if( iFrame<=iLast && aPgno[aHash[iKey]]==pgno ){ |
| 50830 | - /* assert( iFrame>iRead ); -- not true if there is corruption */ | |
| 50881 | + assert( iFrame>iRead || CORRUPT_DB ); | |
| 50831 | 50882 | iRead = iFrame; |
| 50832 | 50883 | } |
| 50833 | 50884 | if( (nCollide--)==0 ){ |
| 50834 | 50885 | return SQLITE_CORRUPT_BKPT; |
| 50835 | 50886 | } |
| @@ -51931,10 +51982,11 @@ | ||
| 51931 | 51982 | u8 inTrans; /* TRANS_NONE, TRANS_READ or TRANS_WRITE */ |
| 51932 | 51983 | u8 sharable; /* True if we can share pBt with another db */ |
| 51933 | 51984 | u8 locked; /* True if db currently has pBt locked */ |
| 51934 | 51985 | int wantToLock; /* Number of nested calls to sqlite3BtreeEnter() */ |
| 51935 | 51986 | int nBackup; /* Number of backup operations reading this btree */ |
| 51987 | + u32 iDataVersion; /* Combines with pBt->pPager->iDataVersion */ | |
| 51936 | 51988 | Btree *pNext; /* List of other sharable Btrees from the same db */ |
| 51937 | 51989 | Btree *pPrev; /* Back pointer of the same list */ |
| 51938 | 51990 | #ifndef SQLITE_OMIT_SHARED_CACHE |
| 51939 | 51991 | BtLock lock; /* Object used to lock page 1 */ |
| 51940 | 51992 | #endif |
| @@ -56094,10 +56146,11 @@ | ||
| 56094 | 56146 | rc = sqlite3PagerCommitPhaseTwo(pBt->pPager); |
| 56095 | 56147 | if( rc!=SQLITE_OK && bCleanup==0 ){ |
| 56096 | 56148 | sqlite3BtreeLeave(p); |
| 56097 | 56149 | return rc; |
| 56098 | 56150 | } |
| 56151 | + p->iDataVersion--; /* Compensate for pPager->iDataVersion++; */ | |
| 56099 | 56152 | pBt->inTransaction = TRANS_READ; |
| 56100 | 56153 | btreeClearHasContent(pBt); |
| 56101 | 56154 | } |
| 56102 | 56155 | |
| 56103 | 56156 | btreeEndTransaction(p); |
| @@ -56457,11 +56510,11 @@ | ||
| 56457 | 56510 | } |
| 56458 | 56511 | for(i=0; i<=pCur->iPage; i++){ |
| 56459 | 56512 | releasePage(pCur->apPage[i]); |
| 56460 | 56513 | } |
| 56461 | 56514 | unlockBtreeIfUnused(pBt); |
| 56462 | - sqlite3DbFree(pBtree->db, pCur->aOverflow); | |
| 56515 | + sqlite3_free(pCur->aOverflow); | |
| 56463 | 56516 | /* sqlite3_free(pCur); */ |
| 56464 | 56517 | sqlite3BtreeLeave(pBtree); |
| 56465 | 56518 | } |
| 56466 | 56519 | return SQLITE_OK; |
| 56467 | 56520 | } |
| @@ -56751,10 +56804,11 @@ | ||
| 56751 | 56804 | pBuf += a; |
| 56752 | 56805 | amt -= a; |
| 56753 | 56806 | }else{ |
| 56754 | 56807 | offset -= pCur->info.nLocal; |
| 56755 | 56808 | } |
| 56809 | + | |
| 56756 | 56810 | |
| 56757 | 56811 | if( rc==SQLITE_OK && amt>0 ){ |
| 56758 | 56812 | const u32 ovflSize = pBt->usableSize - 4; /* Bytes content per ovfl page */ |
| 56759 | 56813 | Pgno nextPage; |
| 56760 | 56814 | |
| @@ -56769,12 +56823,12 @@ | ||
| 56769 | 56823 | ** means "not yet known" (the cache is lazily populated). |
| 56770 | 56824 | */ |
| 56771 | 56825 | if( eOp!=2 && (pCur->curFlags & BTCF_ValidOvfl)==0 ){ |
| 56772 | 56826 | int nOvfl = (pCur->info.nPayload-pCur->info.nLocal+ovflSize-1)/ovflSize; |
| 56773 | 56827 | if( nOvfl>pCur->nOvflAlloc ){ |
| 56774 | - Pgno *aNew = (Pgno*)sqlite3DbRealloc( | |
| 56775 | - pCur->pBtree->db, pCur->aOverflow, nOvfl*2*sizeof(Pgno) | |
| 56828 | + Pgno *aNew = (Pgno*)sqlite3Realloc( | |
| 56829 | + pCur->aOverflow, nOvfl*2*sizeof(Pgno) | |
| 56776 | 56830 | ); |
| 56777 | 56831 | if( aNew==0 ){ |
| 56778 | 56832 | rc = SQLITE_NOMEM; |
| 56779 | 56833 | }else{ |
| 56780 | 56834 | pCur->nOvflAlloc = nOvfl*2; |
| @@ -56817,10 +56871,11 @@ | ||
| 56817 | 56871 | ** Note that the aOverflow[] array must be allocated because eOp!=2 |
| 56818 | 56872 | ** here. If eOp==2, then offset==0 and this branch is never taken. |
| 56819 | 56873 | */ |
| 56820 | 56874 | assert( eOp!=2 ); |
| 56821 | 56875 | assert( pCur->curFlags & BTCF_ValidOvfl ); |
| 56876 | + assert( pCur->pBtree->db==pBt->db ); | |
| 56822 | 56877 | if( pCur->aOverflow[iIdx+1] ){ |
| 56823 | 56878 | nextPage = pCur->aOverflow[iIdx+1]; |
| 56824 | 56879 | }else{ |
| 56825 | 56880 | rc = getOverflowPage(pBt, nextPage, 0, &nextPage); |
| 56826 | 56881 | } |
| @@ -59329,11 +59384,11 @@ | ||
| 59329 | 59384 | + nMaxCells*sizeof(u16) /* szCell */ |
| 59330 | 59385 | + pBt->pageSize; /* aSpace1 */ |
| 59331 | 59386 | |
| 59332 | 59387 | /* EVIDENCE-OF: R-28375-38319 SQLite will never request a scratch buffer |
| 59333 | 59388 | ** that is more than 6 times the database page size. */ |
| 59334 | - assert( szScratch<=6*pBt->pageSize ); | |
| 59389 | + assert( szScratch<=6*(int)pBt->pageSize ); | |
| 59335 | 59390 | apCell = sqlite3ScratchMalloc( szScratch ); |
| 59336 | 59391 | if( apCell==0 ){ |
| 59337 | 59392 | rc = SQLITE_NOMEM; |
| 59338 | 59393 | goto balance_cleanup; |
| 59339 | 59394 | } |
| @@ -59406,12 +59461,12 @@ | ||
| 59406 | 59461 | assert( leafCorrection==4 ); |
| 59407 | 59462 | if( szCell[nCell]<4 ){ |
| 59408 | 59463 | /* Do not allow any cells smaller than 4 bytes. If a smaller cell |
| 59409 | 59464 | ** does exist, pad it with 0x00 bytes. */ |
| 59410 | 59465 | assert( szCell[nCell]==3 ); |
| 59411 | - assert( apCell[nCell]==&pTemp[iSpace1-3] ); | |
| 59412 | - pTemp[iSpace1++] = 0x00; | |
| 59466 | + assert( apCell[nCell]==&aSpace1[iSpace1-3] ); | |
| 59467 | + aSpace1[iSpace1++] = 0x00; | |
| 59413 | 59468 | szCell[nCell] = 4; |
| 59414 | 59469 | } |
| 59415 | 59470 | } |
| 59416 | 59471 | nCell++; |
| 59417 | 59472 | } |
| @@ -60719,10 +60774,17 @@ | ||
| 60719 | 60774 | ** is read-only, the others are read/write. |
| 60720 | 60775 | ** |
| 60721 | 60776 | ** The schema layer numbers meta values differently. At the schema |
| 60722 | 60777 | ** layer (and the SetCookie and ReadCookie opcodes) the number of |
| 60723 | 60778 | ** free pages is not visible. So Cookie[0] is the same as Meta[1]. |
| 60779 | +** | |
| 60780 | +** This routine treats Meta[BTREE_DATA_VERSION] as a special case. Instead | |
| 60781 | +** of reading the value out of the header, it instead loads the "DataVersion" | |
| 60782 | +** from the pager. The BTREE_DATA_VERSION value is not actually stored in the | |
| 60783 | +** database file. It is a number computed by the pager. But its access | |
| 60784 | +** pattern is the same as header meta values, and so it is convenient to | |
| 60785 | +** read it from this routine. | |
| 60724 | 60786 | */ |
| 60725 | 60787 | SQLITE_PRIVATE void sqlite3BtreeGetMeta(Btree *p, int idx, u32 *pMeta){ |
| 60726 | 60788 | BtShared *pBt = p->pBt; |
| 60727 | 60789 | |
| 60728 | 60790 | sqlite3BtreeEnter(p); |
| @@ -60729,11 +60791,15 @@ | ||
| 60729 | 60791 | assert( p->inTrans>TRANS_NONE ); |
| 60730 | 60792 | assert( SQLITE_OK==querySharedCacheTableLock(p, MASTER_ROOT, READ_LOCK) ); |
| 60731 | 60793 | assert( pBt->pPage1 ); |
| 60732 | 60794 | assert( idx>=0 && idx<=15 ); |
| 60733 | 60795 | |
| 60734 | - *pMeta = get4byte(&pBt->pPage1->aData[36 + idx*4]); | |
| 60796 | + if( idx==BTREE_DATA_VERSION ){ | |
| 60797 | + *pMeta = sqlite3PagerDataVersion(pBt->pPager) + p->iDataVersion; | |
| 60798 | + }else{ | |
| 60799 | + *pMeta = get4byte(&pBt->pPage1->aData[36 + idx*4]); | |
| 60800 | + } | |
| 60735 | 60801 | |
| 60736 | 60802 | /* If auto-vacuum is disabled in this build and this is an auto-vacuum |
| 60737 | 60803 | ** database, mark the database as read-only. */ |
| 60738 | 60804 | #ifdef SQLITE_OMIT_AUTOVACUUM |
| 60739 | 60805 | if( idx==BTREE_LARGEST_ROOT_PAGE && *pMeta>0 ){ |
| @@ -60820,11 +60886,11 @@ | ||
| 60820 | 60886 | if( pPage->leaf ){ |
| 60821 | 60887 | do { |
| 60822 | 60888 | if( pCur->iPage==0 ){ |
| 60823 | 60889 | /* All pages of the b-tree have been visited. Return successfully. */ |
| 60824 | 60890 | *pnEntry = nEntry; |
| 60825 | - return SQLITE_OK; | |
| 60891 | + return moveToRoot(pCur); | |
| 60826 | 60892 | } |
| 60827 | 60893 | moveToParent(pCur); |
| 60828 | 60894 | }while ( pCur->aiIdx[pCur->iPage]>=pCur->apPage[pCur->iPage]->nCell ); |
| 60829 | 60895 | |
| 60830 | 60896 | pCur->aiIdx[pCur->iPage]++; |
| @@ -61676,11 +61742,11 @@ | ||
| 61676 | 61742 | } |
| 61677 | 61743 | |
| 61678 | 61744 | /* |
| 61679 | 61745 | ** Return the size of the header added to each page by this module. |
| 61680 | 61746 | */ |
| 61681 | -SQLITE_PRIVATE int sqlite3HeaderSizeBtree(void){ return sizeof(MemPage); } | |
| 61747 | +SQLITE_PRIVATE int sqlite3HeaderSizeBtree(void){ return ROUND8(sizeof(MemPage)); } | |
| 61682 | 61748 | |
| 61683 | 61749 | /************** End of btree.c ***********************************************/ |
| 61684 | 61750 | /************** Begin file backup.c ******************************************/ |
| 61685 | 61751 | /* |
| 61686 | 61752 | ** 2009 January 28 |
| @@ -64440,36 +64506,39 @@ | ||
| 64440 | 64506 | ** |
| 64441 | 64507 | ** assert( sqlite3VdbeAssertMayAbort(pParse->pVdbe, pParse->mayAbort) ); |
| 64442 | 64508 | */ |
| 64443 | 64509 | SQLITE_PRIVATE int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){ |
| 64444 | 64510 | int hasAbort = 0; |
| 64511 | + int hasFkCounter = 0; | |
| 64445 | 64512 | Op *pOp; |
| 64446 | 64513 | VdbeOpIter sIter; |
| 64447 | 64514 | memset(&sIter, 0, sizeof(sIter)); |
| 64448 | 64515 | sIter.v = v; |
| 64449 | 64516 | |
| 64450 | 64517 | while( (pOp = opIterNext(&sIter))!=0 ){ |
| 64451 | 64518 | int opcode = pOp->opcode; |
| 64452 | 64519 | if( opcode==OP_Destroy || opcode==OP_VUpdate || opcode==OP_VRename |
| 64453 | -#ifndef SQLITE_OMIT_FOREIGN_KEY | |
| 64454 | - || (opcode==OP_FkCounter && pOp->p1==0 && pOp->p2==1) | |
| 64455 | -#endif | |
| 64456 | 64520 | || ((opcode==OP_Halt || opcode==OP_HaltIfNull) |
| 64457 | 64521 | && ((pOp->p1&0xff)==SQLITE_CONSTRAINT && pOp->p2==OE_Abort)) |
| 64458 | 64522 | ){ |
| 64459 | 64523 | hasAbort = 1; |
| 64460 | 64524 | break; |
| 64461 | 64525 | } |
| 64526 | +#ifndef SQLITE_OMIT_FOREIGN_KEY | |
| 64527 | + if( opcode==OP_FkCounter && pOp->p1==0 && pOp->p2==1 ){ | |
| 64528 | + hasFkCounter = 1; | |
| 64529 | + } | |
| 64530 | +#endif | |
| 64462 | 64531 | } |
| 64463 | 64532 | sqlite3DbFree(v->db, sIter.apSub); |
| 64464 | 64533 | |
| 64465 | 64534 | /* Return true if hasAbort==mayAbort. Or if a malloc failure occurred. |
| 64466 | 64535 | ** If malloc failed, then the while() loop above may not have iterated |
| 64467 | 64536 | ** through all opcodes and hasAbort may be set incorrectly. Return |
| 64468 | 64537 | ** true for this case to prevent the assert() in the callers frame |
| 64469 | 64538 | ** from failing. */ |
| 64470 | - return ( v->db->mallocFailed || hasAbort==mayAbort ); | |
| 64539 | + return ( v->db->mallocFailed || hasAbort==mayAbort || hasFkCounter ); | |
| 64471 | 64540 | } |
| 64472 | 64541 | #endif /* SQLITE_DEBUG - the sqlite3AssertMayAbort() function */ |
| 64473 | 64542 | |
| 64474 | 64543 | /* |
| 64475 | 64544 | ** Loop through the program looking for P2 values that are negative |
| @@ -68589,11 +68658,14 @@ | ||
| 68589 | 68658 | #ifndef SQLITE_OMIT_WAL |
| 68590 | 68659 | int i; |
| 68591 | 68660 | for(i=0; i<db->nDb; i++){ |
| 68592 | 68661 | Btree *pBt = db->aDb[i].pBt; |
| 68593 | 68662 | if( pBt ){ |
| 68594 | - int nEntry = sqlite3PagerWalCallback(sqlite3BtreePager(pBt)); | |
| 68663 | + int nEntry; | |
| 68664 | + sqlite3BtreeEnter(pBt); | |
| 68665 | + nEntry = sqlite3PagerWalCallback(sqlite3BtreePager(pBt)); | |
| 68666 | + sqlite3BtreeLeave(pBt); | |
| 68595 | 68667 | if( db->xWalCallback && nEntry>0 && rc==SQLITE_OK ){ |
| 68596 | 68668 | rc = db->xWalCallback(db->pWalArg, db, db->aDb[i].zName, nEntry); |
| 68597 | 68669 | } |
| 68598 | 68670 | } |
| 68599 | 68671 | } |
| @@ -68769,11 +68841,10 @@ | ||
| 68769 | 68841 | ** program counter to 0 to ensure that when the statement is |
| 68770 | 68842 | ** finalized or reset the parser error message is available via |
| 68771 | 68843 | ** sqlite3_errmsg() and sqlite3_errcode(). |
| 68772 | 68844 | */ |
| 68773 | 68845 | const char *zErr = (const char *)sqlite3_value_text(db->pErr); |
| 68774 | - assert( zErr!=0 || db->mallocFailed ); | |
| 68775 | 68846 | sqlite3DbFree(db, v->zErrMsg); |
| 68776 | 68847 | if( !db->mallocFailed ){ |
| 68777 | 68848 | v->zErrMsg = sqlite3DbStrDup(db, zErr); |
| 68778 | 68849 | v->rc = rc2; |
| 68779 | 68850 | } else { |
| @@ -77131,11 +77202,11 @@ | ||
| 77131 | 77202 | /* |
| 77132 | 77203 | ** Hard-coded maximum amount of data to accumulate in memory before flushing |
| 77133 | 77204 | ** to a level 0 PMA. The purpose of this limit is to prevent various integer |
| 77134 | 77205 | ** overflows. 512MiB. |
| 77135 | 77206 | */ |
| 77136 | -#define SQLITE_MAX_MXPMASIZE (1<<29) | |
| 77207 | +#define SQLITE_MAX_PMASZ (1<<29) | |
| 77137 | 77208 | |
| 77138 | 77209 | /* |
| 77139 | 77210 | ** Private objects used by the sorter |
| 77140 | 77211 | */ |
| 77141 | 77212 | typedef struct MergeEngine MergeEngine; /* Merge PMAs together */ |
| @@ -77427,13 +77498,10 @@ | ||
| 77427 | 77498 | ** |
| 77428 | 77499 | ** void *SRVAL(SorterRecord *p) { return (void*)&p[1]; } |
| 77429 | 77500 | */ |
| 77430 | 77501 | #define SRVAL(p) ((void*)((SorterRecord*)(p) + 1)) |
| 77431 | 77502 | |
| 77432 | -/* The minimum PMA size is set to this value multiplied by the database | |
| 77433 | -** page size in bytes. */ | |
| 77434 | -#define SORTER_MIN_WORKING 10 | |
| 77435 | 77503 | |
| 77436 | 77504 | /* Maximum number of PMAs that a single MergeEngine can merge */ |
| 77437 | 77505 | #define SORTER_MAX_MERGE_COUNT 16 |
| 77438 | 77506 | |
| 77439 | 77507 | static int vdbeIncrSwap(IncrMerger*); |
| @@ -77828,14 +77896,15 @@ | ||
| 77828 | 77896 | SortSubtask *pTask = &pSorter->aTask[i]; |
| 77829 | 77897 | pTask->pSorter = pSorter; |
| 77830 | 77898 | } |
| 77831 | 77899 | |
| 77832 | 77900 | if( !sqlite3TempInMemory(db) ){ |
| 77833 | - pSorter->mnPmaSize = SORTER_MIN_WORKING * pgsz; | |
| 77901 | + u32 szPma = sqlite3GlobalConfig.szPma; | |
| 77902 | + pSorter->mnPmaSize = szPma * pgsz; | |
| 77834 | 77903 | mxCache = db->aDb[0].pSchema->cache_size; |
| 77835 | - if( mxCache<SORTER_MIN_WORKING ) mxCache = SORTER_MIN_WORKING; | |
| 77836 | - pSorter->mxPmaSize = MIN((i64)mxCache*pgsz, SQLITE_MAX_MXPMASIZE); | |
| 77904 | + if( mxCache<(int)szPma ) mxCache = (int)szPma; | |
| 77905 | + pSorter->mxPmaSize = MIN((i64)mxCache*pgsz, SQLITE_MAX_PMASZ); | |
| 77837 | 77906 | |
| 77838 | 77907 | /* EVIDENCE-OF: R-26747-61719 When the application provides any amount of |
| 77839 | 77908 | ** scratch memory using SQLITE_CONFIG_SCRATCH, SQLite avoids unnecessary |
| 77840 | 77909 | ** large heap allocations. |
| 77841 | 77910 | */ |
| @@ -78109,16 +78178,16 @@ | ||
| 78109 | 78178 | ** Whether or not the file does end up memory mapped of course depends on |
| 78110 | 78179 | ** the specific VFS implementation. |
| 78111 | 78180 | */ |
| 78112 | 78181 | static void vdbeSorterExtendFile(sqlite3 *db, sqlite3_file *pFd, i64 nByte){ |
| 78113 | 78182 | if( nByte<=(i64)(db->nMaxSorterMmap) && pFd->pMethods->iVersion>=3 ){ |
| 78114 | - int rc = sqlite3OsTruncate(pFd, nByte); | |
| 78115 | - if( rc==SQLITE_OK ){ | |
| 78116 | - void *p = 0; | |
| 78117 | - sqlite3OsFetch(pFd, 0, (int)nByte, &p); | |
| 78118 | - sqlite3OsUnfetch(pFd, 0, p); | |
| 78119 | - } | |
| 78183 | + void *p = 0; | |
| 78184 | + int chunksize = 4*1024; | |
| 78185 | + sqlite3OsFileControlHint(pFd, SQLITE_FCNTL_CHUNK_SIZE, &chunksize); | |
| 78186 | + sqlite3OsFileControlHint(pFd, SQLITE_FCNTL_SIZE_HINT, &nByte); | |
| 78187 | + sqlite3OsFetch(pFd, 0, (int)nByte, &p); | |
| 78188 | + sqlite3OsUnfetch(pFd, 0, p); | |
| 78120 | 78189 | } |
| 78121 | 78190 | } |
| 78122 | 78191 | #else |
| 78123 | 78192 | # define vdbeSorterExtendFile(x,y,z) |
| 78124 | 78193 | #endif |
| @@ -87296,11 +87365,11 @@ | ||
| 87296 | 87365 | |
| 87297 | 87366 | p->iGet = -1; |
| 87298 | 87367 | p->mxSample = mxSample; |
| 87299 | 87368 | p->nPSample = (tRowcnt)(sqlite3_value_int64(argv[2])/(mxSample/3+1) + 1); |
| 87300 | 87369 | p->current.anLt = &p->current.anEq[nColUp]; |
| 87301 | - p->iPrn = nCol*0x689e962d ^ sqlite3_value_int(argv[2])*0xd0944565; | |
| 87370 | + p->iPrn = 0x689e962d*(u32)nCol ^ 0xd0944565*(u32)sqlite3_value_int(argv[2]); | |
| 87302 | 87371 | |
| 87303 | 87372 | /* Set up the Stat4Accum.a[] and aBest[] arrays */ |
| 87304 | 87373 | p->a = (struct Stat4Sample*)&p->current.anLt[nColUp]; |
| 87305 | 87374 | p->aBest = &p->a[mxSample]; |
| 87306 | 87375 | pSpace = (u8*)(&p->a[mxSample+nCol]); |
| @@ -88889,17 +88958,19 @@ | ||
| 88889 | 88958 | }else if( aNew->pSchema->file_format && aNew->pSchema->enc!=ENC(db) ){ |
| 88890 | 88959 | zErrDyn = sqlite3MPrintf(db, |
| 88891 | 88960 | "attached databases must use the same text encoding as main database"); |
| 88892 | 88961 | rc = SQLITE_ERROR; |
| 88893 | 88962 | } |
| 88963 | + sqlite3BtreeEnter(aNew->pBt); | |
| 88894 | 88964 | pPager = sqlite3BtreePager(aNew->pBt); |
| 88895 | 88965 | sqlite3PagerLockingMode(pPager, db->dfltLockMode); |
| 88896 | 88966 | sqlite3BtreeSecureDelete(aNew->pBt, |
| 88897 | 88967 | sqlite3BtreeSecureDelete(db->aDb[0].pBt,-1) ); |
| 88898 | 88968 | #ifndef SQLITE_OMIT_PAGER_PRAGMAS |
| 88899 | 88969 | sqlite3BtreeSetPagerFlags(aNew->pBt, 3 | (db->flags & PAGER_FLAGS_MASK)); |
| 88900 | 88970 | #endif |
| 88971 | + sqlite3BtreeLeave(aNew->pBt); | |
| 88901 | 88972 | } |
| 88902 | 88973 | aNew->safety_level = 3; |
| 88903 | 88974 | aNew->zName = sqlite3DbStrDup(db, zName); |
| 88904 | 88975 | if( rc==SQLITE_OK && aNew->zName==0 ){ |
| 88905 | 88976 | rc = SQLITE_NOMEM; |
| @@ -90021,11 +90092,10 @@ | ||
| 90021 | 90092 | */ |
| 90022 | 90093 | static void freeIndex(sqlite3 *db, Index *p){ |
| 90023 | 90094 | #ifndef SQLITE_OMIT_ANALYZE |
| 90024 | 90095 | sqlite3DeleteIndexSamples(db, p); |
| 90025 | 90096 | #endif |
| 90026 | - if( db==0 || db->pnBytesFreed==0 ) sqlite3KeyInfoUnref(p->pKeyInfo); | |
| 90027 | 90097 | sqlite3ExprDelete(db, p->pPartIdxWhere); |
| 90028 | 90098 | sqlite3DbFree(db, p->zColAff); |
| 90029 | 90099 | if( p->isResized ) sqlite3DbFree(db, p->azColl); |
| 90030 | 90100 | #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 |
| 90031 | 90101 | sqlite3_free(p->aiRowEst); |
| @@ -91300,10 +91370,23 @@ | ||
| 91300 | 91370 | if( pPk==0 ) return; |
| 91301 | 91371 | pPk->idxType = SQLITE_IDXTYPE_PRIMARYKEY; |
| 91302 | 91372 | pTab->iPKey = -1; |
| 91303 | 91373 | }else{ |
| 91304 | 91374 | pPk = sqlite3PrimaryKeyIndex(pTab); |
| 91375 | + /* | |
| 91376 | + ** Remove all redundant columns from the PRIMARY KEY. For example, change | |
| 91377 | + ** "PRIMARY KEY(a,b,a,b,c,b,c,d)" into just "PRIMARY KEY(a,b,c,d)". Later | |
| 91378 | + ** code assumes the PRIMARY KEY contains no repeated columns. | |
| 91379 | + */ | |
| 91380 | + for(i=j=1; i<pPk->nKeyCol; i++){ | |
| 91381 | + if( hasColumn(pPk->aiColumn, j, pPk->aiColumn[i]) ){ | |
| 91382 | + pPk->nColumn--; | |
| 91383 | + }else{ | |
| 91384 | + pPk->aiColumn[j++] = pPk->aiColumn[i]; | |
| 91385 | + } | |
| 91386 | + } | |
| 91387 | + pPk->nKeyCol = j; | |
| 91305 | 91388 | } |
| 91306 | 91389 | pPk->isCovering = 1; |
| 91307 | 91390 | assert( pPk!=0 ); |
| 91308 | 91391 | nPk = pPk->nKeyCol; |
| 91309 | 91392 | |
| @@ -93776,44 +93859,35 @@ | ||
| 93776 | 93859 | ** |
| 93777 | 93860 | ** The caller should invoke sqlite3KeyInfoUnref() on the returned object |
| 93778 | 93861 | ** when it has finished using it. |
| 93779 | 93862 | */ |
| 93780 | 93863 | SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoOfIndex(Parse *pParse, Index *pIdx){ |
| 93864 | + int i; | |
| 93865 | + int nCol = pIdx->nColumn; | |
| 93866 | + int nKey = pIdx->nKeyCol; | |
| 93867 | + KeyInfo *pKey; | |
| 93781 | 93868 | if( pParse->nErr ) return 0; |
| 93782 | -#ifndef SQLITE_OMIT_SHARED_CACHE | |
| 93783 | - if( pIdx->pKeyInfo && pIdx->pKeyInfo->db!=pParse->db ){ | |
| 93784 | - sqlite3KeyInfoUnref(pIdx->pKeyInfo); | |
| 93785 | - pIdx->pKeyInfo = 0; | |
| 93786 | - } | |
| 93787 | -#endif | |
| 93788 | - if( pIdx->pKeyInfo==0 ){ | |
| 93789 | - int i; | |
| 93790 | - int nCol = pIdx->nColumn; | |
| 93791 | - int nKey = pIdx->nKeyCol; | |
| 93792 | - KeyInfo *pKey; | |
| 93793 | - if( pIdx->uniqNotNull ){ | |
| 93794 | - pKey = sqlite3KeyInfoAlloc(pParse->db, nKey, nCol-nKey); | |
| 93795 | - }else{ | |
| 93796 | - pKey = sqlite3KeyInfoAlloc(pParse->db, nCol, 0); | |
| 93797 | - } | |
| 93798 | - if( pKey ){ | |
| 93799 | - assert( sqlite3KeyInfoIsWriteable(pKey) ); | |
| 93800 | - for(i=0; i<nCol; i++){ | |
| 93801 | - char *zColl = pIdx->azColl[i]; | |
| 93802 | - assert( zColl!=0 ); | |
| 93803 | - pKey->aColl[i] = strcmp(zColl,"BINARY")==0 ? 0 : | |
| 93804 | - sqlite3LocateCollSeq(pParse, zColl); | |
| 93805 | - pKey->aSortOrder[i] = pIdx->aSortOrder[i]; | |
| 93806 | - } | |
| 93807 | - if( pParse->nErr ){ | |
| 93808 | - sqlite3KeyInfoUnref(pKey); | |
| 93809 | - }else{ | |
| 93810 | - pIdx->pKeyInfo = pKey; | |
| 93811 | - } | |
| 93812 | - } | |
| 93813 | - } | |
| 93814 | - return sqlite3KeyInfoRef(pIdx->pKeyInfo); | |
| 93869 | + if( pIdx->uniqNotNull ){ | |
| 93870 | + pKey = sqlite3KeyInfoAlloc(pParse->db, nKey, nCol-nKey); | |
| 93871 | + }else{ | |
| 93872 | + pKey = sqlite3KeyInfoAlloc(pParse->db, nCol, 0); | |
| 93873 | + } | |
| 93874 | + if( pKey ){ | |
| 93875 | + assert( sqlite3KeyInfoIsWriteable(pKey) ); | |
| 93876 | + for(i=0; i<nCol; i++){ | |
| 93877 | + char *zColl = pIdx->azColl[i]; | |
| 93878 | + assert( zColl!=0 ); | |
| 93879 | + pKey->aColl[i] = strcmp(zColl,"BINARY")==0 ? 0 : | |
| 93880 | + sqlite3LocateCollSeq(pParse, zColl); | |
| 93881 | + pKey->aSortOrder[i] = pIdx->aSortOrder[i]; | |
| 93882 | + } | |
| 93883 | + if( pParse->nErr ){ | |
| 93884 | + sqlite3KeyInfoUnref(pKey); | |
| 93885 | + pKey = 0; | |
| 93886 | + } | |
| 93887 | + } | |
| 93888 | + return pKey; | |
| 93815 | 93889 | } |
| 93816 | 93890 | |
| 93817 | 93891 | #ifndef SQLITE_OMIT_CTE |
| 93818 | 93892 | /* |
| 93819 | 93893 | ** This routine is invoked once per CTE by the parser while parsing a |
| @@ -97430,11 +97504,11 @@ | ||
| 97430 | 97504 | assert( nIncr==1 ); |
| 97431 | 97505 | sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_FOREIGNKEY, |
| 97432 | 97506 | OE_Abort, 0, P4_STATIC, P5_ConstraintFK); |
| 97433 | 97507 | }else{ |
| 97434 | 97508 | if( nIncr>0 && pFKey->isDeferred==0 ){ |
| 97435 | - sqlite3ParseToplevel(pParse)->mayAbort = 1; | |
| 97509 | + sqlite3MayAbort(pParse); | |
| 97436 | 97510 | } |
| 97437 | 97511 | sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr); |
| 97438 | 97512 | } |
| 97439 | 97513 | |
| 97440 | 97514 | sqlite3VdbeResolveLabel(v, iOk); |
| @@ -97501,10 +97575,14 @@ | ||
| 97501 | 97575 | ** This function is called to generate code executed when a row is deleted |
| 97502 | 97576 | ** from the parent table of foreign key constraint pFKey and, if pFKey is |
| 97503 | 97577 | ** deferred, when a row is inserted into the same table. When generating |
| 97504 | 97578 | ** code for an SQL UPDATE operation, this function may be called twice - |
| 97505 | 97579 | ** once to "delete" the old row and once to "insert" the new row. |
| 97580 | +** | |
| 97581 | +** Parameter nIncr is passed -1 when inserting a row (as this may decrease | |
| 97582 | +** the number of FK violations in the db) or +1 when deleting one (as this | |
| 97583 | +** may increase the number of FK constraint problems). | |
| 97506 | 97584 | ** |
| 97507 | 97585 | ** The code generated by this function scans through the rows in the child |
| 97508 | 97586 | ** table that correspond to the parent table row being deleted or inserted. |
| 97509 | 97587 | ** For each child row found, one of the following actions is taken: |
| 97510 | 97588 | ** |
| @@ -97618,17 +97696,13 @@ | ||
| 97618 | 97696 | sNameContext.pSrcList = pSrc; |
| 97619 | 97697 | sNameContext.pParse = pParse; |
| 97620 | 97698 | sqlite3ResolveExprNames(&sNameContext, pWhere); |
| 97621 | 97699 | |
| 97622 | 97700 | /* Create VDBE to loop through the entries in pSrc that match the WHERE |
| 97623 | - ** clause. If the constraint is not deferred, throw an exception for | |
| 97624 | - ** each row found. Otherwise, for deferred constraints, increment the | |
| 97625 | - ** deferred constraint counter by nIncr for each row selected. */ | |
| 97701 | + ** clause. For each row found, increment either the deferred or immediate | |
| 97702 | + ** foreign key constraint counter. */ | |
| 97626 | 97703 | pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0, 0, 0); |
| 97627 | - if( nIncr>0 && pFKey->isDeferred==0 ){ | |
| 97628 | - sqlite3ParseToplevel(pParse)->mayAbort = 1; | |
| 97629 | - } | |
| 97630 | 97704 | sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr); |
| 97631 | 97705 | if( pWInfo ){ |
| 97632 | 97706 | sqlite3WhereEnd(pWInfo); |
| 97633 | 97707 | } |
| 97634 | 97708 | |
| @@ -97802,10 +97876,28 @@ | ||
| 97802 | 97876 | } |
| 97803 | 97877 | } |
| 97804 | 97878 | } |
| 97805 | 97879 | return 0; |
| 97806 | 97880 | } |
| 97881 | + | |
| 97882 | +/* | |
| 97883 | +** Return true if the parser passed as the first argument is being | |
| 97884 | +** used to code a trigger that is really a "SET NULL" action belonging | |
| 97885 | +** to trigger pFKey. | |
| 97886 | +*/ | |
| 97887 | +static int isSetNullAction(Parse *pParse, FKey *pFKey){ | |
| 97888 | + Parse *pTop = sqlite3ParseToplevel(pParse); | |
| 97889 | + if( pTop->pTriggerPrg ){ | |
| 97890 | + Trigger *p = pTop->pTriggerPrg->pTrigger; | |
| 97891 | + if( (p==pFKey->apTrigger[0] && pFKey->aAction[0]==OE_SetNull) | |
| 97892 | + || (p==pFKey->apTrigger[1] && pFKey->aAction[1]==OE_SetNull) | |
| 97893 | + ){ | |
| 97894 | + return 1; | |
| 97895 | + } | |
| 97896 | + } | |
| 97897 | + return 0; | |
| 97898 | +} | |
| 97807 | 97899 | |
| 97808 | 97900 | /* |
| 97809 | 97901 | ** This function is called when inserting, deleting or updating a row of |
| 97810 | 97902 | ** table pTab to generate VDBE code to perform foreign key constraint |
| 97811 | 97903 | ** processing for the operation. |
| @@ -97855,11 +97947,11 @@ | ||
| 97855 | 97947 | Index *pIdx = 0; /* Index on key columns in pTo */ |
| 97856 | 97948 | int *aiFree = 0; |
| 97857 | 97949 | int *aiCol; |
| 97858 | 97950 | int iCol; |
| 97859 | 97951 | int i; |
| 97860 | - int isIgnore = 0; | |
| 97952 | + int bIgnore = 0; | |
| 97861 | 97953 | |
| 97862 | 97954 | if( aChange |
| 97863 | 97955 | && sqlite3_stricmp(pTab->zName, pFKey->zTo)!=0 |
| 97864 | 97956 | && fkChildIsModified(pTab, pFKey, aChange, bChngRowid)==0 |
| 97865 | 97957 | ){ |
| @@ -97914,11 +98006,11 @@ | ||
| 97914 | 98006 | ** values read from the parent table are NULL. */ |
| 97915 | 98007 | if( db->xAuth ){ |
| 97916 | 98008 | int rcauth; |
| 97917 | 98009 | char *zCol = pTo->aCol[pIdx ? pIdx->aiColumn[i] : pTo->iPKey].zName; |
| 97918 | 98010 | rcauth = sqlite3AuthReadCol(pParse, pTo->zName, zCol, iDb); |
| 97919 | - isIgnore = (rcauth==SQLITE_IGNORE); | |
| 98011 | + bIgnore = (rcauth==SQLITE_IGNORE); | |
| 97920 | 98012 | } |
| 97921 | 98013 | #endif |
| 97922 | 98014 | } |
| 97923 | 98015 | |
| 97924 | 98016 | /* Take a shared-cache advisory read-lock on the parent table. Allocate |
| @@ -97929,16 +98021,22 @@ | ||
| 97929 | 98021 | |
| 97930 | 98022 | if( regOld!=0 ){ |
| 97931 | 98023 | /* A row is being removed from the child table. Search for the parent. |
| 97932 | 98024 | ** If the parent does not exist, removing the child row resolves an |
| 97933 | 98025 | ** outstanding foreign key constraint violation. */ |
| 97934 | - fkLookupParent(pParse, iDb, pTo, pIdx, pFKey, aiCol, regOld, -1,isIgnore); | |
| 98026 | + fkLookupParent(pParse, iDb, pTo, pIdx, pFKey, aiCol, regOld, -1, bIgnore); | |
| 97935 | 98027 | } |
| 97936 | - if( regNew!=0 ){ | |
| 98028 | + if( regNew!=0 && !isSetNullAction(pParse, pFKey) ){ | |
| 97937 | 98029 | /* A row is being added to the child table. If a parent row cannot |
| 97938 | - ** be found, adding the child row has violated the FK constraint. */ | |
| 97939 | - fkLookupParent(pParse, iDb, pTo, pIdx, pFKey, aiCol, regNew, +1,isIgnore); | |
| 98030 | + ** be found, adding the child row has violated the FK constraint. | |
| 98031 | + ** | |
| 98032 | + ** If this operation is being performed as part of a trigger program | |
| 98033 | + ** that is actually a "SET NULL" action belonging to this very | |
| 98034 | + ** foreign key, then omit this scan altogether. As all child key | |
| 98035 | + ** values are guaranteed to be NULL, it is not possible for adding | |
| 98036 | + ** this row to cause an FK violation. */ | |
| 98037 | + fkLookupParent(pParse, iDb, pTo, pIdx, pFKey, aiCol, regNew, +1, bIgnore); | |
| 97940 | 98038 | } |
| 97941 | 98039 | |
| 97942 | 98040 | sqlite3DbFree(db, aiFree); |
| 97943 | 98041 | } |
| 97944 | 98042 | |
| @@ -97955,12 +98053,12 @@ | ||
| 97955 | 98053 | |
| 97956 | 98054 | if( !pFKey->isDeferred && !(db->flags & SQLITE_DeferFKs) |
| 97957 | 98055 | && !pParse->pToplevel && !pParse->isMultiWrite |
| 97958 | 98056 | ){ |
| 97959 | 98057 | assert( regOld==0 && regNew!=0 ); |
| 97960 | - /* Inserting a single row into a parent table cannot cause an immediate | |
| 97961 | - ** foreign key violation. So do nothing in this case. */ | |
| 98058 | + /* Inserting a single row into a parent table cannot cause (or fix) | |
| 98059 | + ** an immediate foreign key violation. So do nothing in this case. */ | |
| 97962 | 98060 | continue; |
| 97963 | 98061 | } |
| 97964 | 98062 | |
| 97965 | 98063 | if( sqlite3FkLocateIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ){ |
| 97966 | 98064 | if( !isIgnoreErrors || db->mallocFailed ) return; |
| @@ -97980,17 +98078,32 @@ | ||
| 97980 | 98078 | |
| 97981 | 98079 | if( regNew!=0 ){ |
| 97982 | 98080 | fkScanChildren(pParse, pSrc, pTab, pIdx, pFKey, aiCol, regNew, -1); |
| 97983 | 98081 | } |
| 97984 | 98082 | if( regOld!=0 ){ |
| 97985 | - /* If there is a RESTRICT action configured for the current operation | |
| 97986 | - ** on the parent table of this FK, then throw an exception | |
| 97987 | - ** immediately if the FK constraint is violated, even if this is a | |
| 97988 | - ** deferred trigger. That's what RESTRICT means. To defer checking | |
| 97989 | - ** the constraint, the FK should specify NO ACTION (represented | |
| 97990 | - ** using OE_None). NO ACTION is the default. */ | |
| 98083 | + int eAction = pFKey->aAction[aChange!=0]; | |
| 97991 | 98084 | fkScanChildren(pParse, pSrc, pTab, pIdx, pFKey, aiCol, regOld, 1); |
| 98085 | + /* If this is a deferred FK constraint, or a CASCADE or SET NULL | |
| 98086 | + ** action applies, then any foreign key violations caused by | |
| 98087 | + ** removing the parent key will be rectified by the action trigger. | |
| 98088 | + ** So do not set the "may-abort" flag in this case. | |
| 98089 | + ** | |
| 98090 | + ** Note 1: If the FK is declared "ON UPDATE CASCADE", then the | |
| 98091 | + ** may-abort flag will eventually be set on this statement anyway | |
| 98092 | + ** (when this function is called as part of processing the UPDATE | |
| 98093 | + ** within the action trigger). | |
| 98094 | + ** | |
| 98095 | + ** Note 2: At first glance it may seem like SQLite could simply omit | |
| 98096 | + ** all OP_FkCounter related scans when either CASCADE or SET NULL | |
| 98097 | + ** applies. The trouble starts if the CASCADE or SET NULL action | |
| 98098 | + ** trigger causes other triggers or action rules attached to the | |
| 98099 | + ** child table to fire. In these cases the fk constraint counters | |
| 98100 | + ** might be set incorrectly if any OP_FkCounter related scans are | |
| 98101 | + ** omitted. */ | |
| 98102 | + if( !pFKey->isDeferred && eAction!=OE_Cascade && eAction!=OE_SetNull ){ | |
| 98103 | + sqlite3MayAbort(pParse); | |
| 98104 | + } | |
| 97992 | 98105 | } |
| 97993 | 98106 | pItem->zName = 0; |
| 97994 | 98107 | sqlite3SrcListDelete(db, pSrc); |
| 97995 | 98108 | } |
| 97996 | 98109 | sqlite3DbFree(db, aiCol); |
| @@ -101080,11 +101193,10 @@ | ||
| 101080 | 101193 | # define sqlite3_column_database_name16 0 |
| 101081 | 101194 | # define sqlite3_column_table_name 0 |
| 101082 | 101195 | # define sqlite3_column_table_name16 0 |
| 101083 | 101196 | # define sqlite3_column_origin_name 0 |
| 101084 | 101197 | # define sqlite3_column_origin_name16 0 |
| 101085 | -# define sqlite3_table_column_metadata 0 | |
| 101086 | 101198 | #endif |
| 101087 | 101199 | |
| 101088 | 101200 | #ifdef SQLITE_OMIT_AUTHORIZATION |
| 101089 | 101201 | # define sqlite3_set_authorizer 0 |
| 101090 | 101202 | #endif |
| @@ -101890,10 +102002,11 @@ | ||
| 101890 | 102002 | #define PragTyp_KEY 38 |
| 101891 | 102003 | #define PragTyp_REKEY 39 |
| 101892 | 102004 | #define PragTyp_LOCK_STATUS 40 |
| 101893 | 102005 | #define PragTyp_PARSER_TRACE 41 |
| 101894 | 102006 | #define PragFlag_NeedSchema 0x01 |
| 102007 | +#define PragFlag_ReadOnly 0x02 | |
| 101895 | 102008 | static const struct sPragmaNames { |
| 101896 | 102009 | const char *const zName; /* Name of pragma */ |
| 101897 | 102010 | u8 ePragTyp; /* PragTyp_XXX value */ |
| 101898 | 102011 | u8 mPragFlag; /* Zero or more PragFlag_XXX values */ |
| 101899 | 102012 | u32 iArg; /* Extra argument */ |
| @@ -101906,11 +102019,11 @@ | ||
| 101906 | 102019 | #endif |
| 101907 | 102020 | #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) |
| 101908 | 102021 | { /* zName: */ "application_id", |
| 101909 | 102022 | /* ePragTyp: */ PragTyp_HEADER_VALUE, |
| 101910 | 102023 | /* ePragFlag: */ 0, |
| 101911 | - /* iArg: */ 0 }, | |
| 102024 | + /* iArg: */ BTREE_APPLICATION_ID }, | |
| 101912 | 102025 | #endif |
| 101913 | 102026 | #if !defined(SQLITE_OMIT_AUTOVACUUM) |
| 101914 | 102027 | { /* zName: */ "auto_vacuum", |
| 101915 | 102028 | /* ePragTyp: */ PragTyp_AUTO_VACUUM, |
| 101916 | 102029 | /* ePragFlag: */ PragFlag_NeedSchema, |
| @@ -101972,10 +102085,16 @@ | ||
| 101972 | 102085 | { /* zName: */ "data_store_directory", |
| 101973 | 102086 | /* ePragTyp: */ PragTyp_DATA_STORE_DIRECTORY, |
| 101974 | 102087 | /* ePragFlag: */ 0, |
| 101975 | 102088 | /* iArg: */ 0 }, |
| 101976 | 102089 | #endif |
| 102090 | +#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) | |
| 102091 | + { /* zName: */ "data_version", | |
| 102092 | + /* ePragTyp: */ PragTyp_HEADER_VALUE, | |
| 102093 | + /* ePragFlag: */ PragFlag_ReadOnly, | |
| 102094 | + /* iArg: */ BTREE_DATA_VERSION }, | |
| 102095 | +#endif | |
| 101977 | 102096 | #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) |
| 101978 | 102097 | { /* zName: */ "database_list", |
| 101979 | 102098 | /* ePragTyp: */ PragTyp_DATABASE_LIST, |
| 101980 | 102099 | /* ePragFlag: */ PragFlag_NeedSchema, |
| 101981 | 102100 | /* iArg: */ 0 }, |
| @@ -102027,12 +102146,12 @@ | ||
| 102027 | 102146 | #endif |
| 102028 | 102147 | #endif |
| 102029 | 102148 | #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) |
| 102030 | 102149 | { /* zName: */ "freelist_count", |
| 102031 | 102150 | /* ePragTyp: */ PragTyp_HEADER_VALUE, |
| 102032 | - /* ePragFlag: */ 0, | |
| 102033 | - /* iArg: */ 0 }, | |
| 102151 | + /* ePragFlag: */ PragFlag_ReadOnly, | |
| 102152 | + /* iArg: */ BTREE_FREE_PAGE_COUNT }, | |
| 102034 | 102153 | #endif |
| 102035 | 102154 | #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) |
| 102036 | 102155 | { /* zName: */ "full_column_names", |
| 102037 | 102156 | /* ePragTyp: */ PragTyp_FLAG, |
| 102038 | 102157 | /* ePragFlag: */ 0, |
| @@ -102180,11 +102299,11 @@ | ||
| 102180 | 102299 | #endif |
| 102181 | 102300 | #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) |
| 102182 | 102301 | { /* zName: */ "schema_version", |
| 102183 | 102302 | /* ePragTyp: */ PragTyp_HEADER_VALUE, |
| 102184 | 102303 | /* ePragFlag: */ 0, |
| 102185 | - /* iArg: */ 0 }, | |
| 102304 | + /* iArg: */ BTREE_SCHEMA_VERSION }, | |
| 102186 | 102305 | #endif |
| 102187 | 102306 | #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) |
| 102188 | 102307 | { /* zName: */ "secure_delete", |
| 102189 | 102308 | /* ePragTyp: */ PragTyp_SECURE_DELETE, |
| 102190 | 102309 | /* ePragFlag: */ 0, |
| @@ -102246,11 +102365,11 @@ | ||
| 102246 | 102365 | /* iArg: */ 0 }, |
| 102247 | 102366 | #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) |
| 102248 | 102367 | { /* zName: */ "user_version", |
| 102249 | 102368 | /* ePragTyp: */ PragTyp_HEADER_VALUE, |
| 102250 | 102369 | /* ePragFlag: */ 0, |
| 102251 | - /* iArg: */ 0 }, | |
| 102370 | + /* iArg: */ BTREE_USER_VERSION }, | |
| 102252 | 102371 | #endif |
| 102253 | 102372 | #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) |
| 102254 | 102373 | #if defined(SQLITE_DEBUG) |
| 102255 | 102374 | { /* zName: */ "vdbe_addoptrace", |
| 102256 | 102375 | /* ePragTyp: */ PragTyp_FLAG, |
| @@ -102289,11 +102408,11 @@ | ||
| 102289 | 102408 | /* ePragTyp: */ PragTyp_FLAG, |
| 102290 | 102409 | /* ePragFlag: */ 0, |
| 102291 | 102410 | /* iArg: */ SQLITE_WriteSchema|SQLITE_RecoveryMode }, |
| 102292 | 102411 | #endif |
| 102293 | 102412 | }; |
| 102294 | -/* Number of pragmas: 57 on by default, 70 total. */ | |
| 102413 | +/* Number of pragmas: 58 on by default, 71 total. */ | |
| 102295 | 102414 | /* End of the automatically generated pragma table. |
| 102296 | 102415 | ***************************************************************************/ |
| 102297 | 102416 | |
| 102298 | 102417 | /* |
| 102299 | 102418 | ** Interpret the given string as a safety level. Return 0 for OFF, |
| @@ -103899,11 +104018,12 @@ | ||
| 103899 | 104018 | !(DbHasProperty(db, 0, DB_SchemaLoaded)) || |
| 103900 | 104019 | DbHasProperty(db, 0, DB_Empty) |
| 103901 | 104020 | ){ |
| 103902 | 104021 | for(pEnc=&encnames[0]; pEnc->zName; pEnc++){ |
| 103903 | 104022 | if( 0==sqlite3StrICmp(zRight, pEnc->zName) ){ |
| 103904 | - ENC(pParse->db) = pEnc->enc ? pEnc->enc : SQLITE_UTF16NATIVE; | |
| 104023 | + SCHEMA_ENC(db) = ENC(db) = | |
| 104024 | + pEnc->enc ? pEnc->enc : SQLITE_UTF16NATIVE; | |
| 103905 | 104025 | break; |
| 103906 | 104026 | } |
| 103907 | 104027 | } |
| 103908 | 104028 | if( !pEnc->zName ){ |
| 103909 | 104029 | sqlite3ErrorMsg(pParse, "unsupported encoding: %s", zRight); |
| @@ -103944,28 +104064,13 @@ | ||
| 103944 | 104064 | ** |
| 103945 | 104065 | ** The user-version is not used internally by SQLite. It may be used by |
| 103946 | 104066 | ** applications for any purpose. |
| 103947 | 104067 | */ |
| 103948 | 104068 | case PragTyp_HEADER_VALUE: { |
| 103949 | - int iCookie; /* Cookie index. 1 for schema-cookie, 6 for user-cookie. */ | |
| 104069 | + int iCookie = aPragmaNames[mid].iArg; /* Which cookie to read or write */ | |
| 103950 | 104070 | sqlite3VdbeUsesBtree(v, iDb); |
| 103951 | - switch( zLeft[0] ){ | |
| 103952 | - case 'a': case 'A': | |
| 103953 | - iCookie = BTREE_APPLICATION_ID; | |
| 103954 | - break; | |
| 103955 | - case 'f': case 'F': | |
| 103956 | - iCookie = BTREE_FREE_PAGE_COUNT; | |
| 103957 | - break; | |
| 103958 | - case 's': case 'S': | |
| 103959 | - iCookie = BTREE_SCHEMA_VERSION; | |
| 103960 | - break; | |
| 103961 | - default: | |
| 103962 | - iCookie = BTREE_USER_VERSION; | |
| 103963 | - break; | |
| 103964 | - } | |
| 103965 | - | |
| 103966 | - if( zRight && iCookie!=BTREE_FREE_PAGE_COUNT ){ | |
| 104071 | + if( zRight && (aPragmaNames[mid].mPragFlag & PragFlag_ReadOnly)==0 ){ | |
| 103967 | 104072 | /* Write the specified cookie value */ |
| 103968 | 104073 | static const VdbeOpList setCookie[] = { |
| 103969 | 104074 | { OP_Transaction, 0, 1, 0}, /* 0 */ |
| 103970 | 104075 | { OP_Integer, 0, 1, 0}, /* 1 */ |
| 103971 | 104076 | { OP_SetCookie, 0, 0, 1}, /* 2 */ |
| @@ -104607,13 +104712,15 @@ | ||
| 104607 | 104712 | SQLITE_PRIVATE int sqlite3Init(sqlite3 *db, char **pzErrMsg){ |
| 104608 | 104713 | int i, rc; |
| 104609 | 104714 | int commit_internal = !(db->flags&SQLITE_InternChanges); |
| 104610 | 104715 | |
| 104611 | 104716 | assert( sqlite3_mutex_held(db->mutex) ); |
| 104717 | + assert( sqlite3BtreeHoldsMutex(db->aDb[0].pBt) ); | |
| 104612 | 104718 | assert( db->init.busy==0 ); |
| 104613 | 104719 | rc = SQLITE_OK; |
| 104614 | 104720 | db->init.busy = 1; |
| 104721 | + ENC(db) = SCHEMA_ENC(db); | |
| 104615 | 104722 | for(i=0; rc==SQLITE_OK && i<db->nDb; i++){ |
| 104616 | 104723 | if( DbHasProperty(db, i, DB_SchemaLoaded) || i==1 ) continue; |
| 104617 | 104724 | rc = sqlite3InitOne(db, i, pzErrMsg); |
| 104618 | 104725 | if( rc ){ |
| 104619 | 104726 | sqlite3ResetOneSchema(db, i); |
| @@ -110751,11 +110858,11 @@ | ||
| 110751 | 110858 | ){ |
| 110752 | 110859 | int rc; |
| 110753 | 110860 | TabResult res; |
| 110754 | 110861 | |
| 110755 | 110862 | #ifdef SQLITE_ENABLE_API_ARMOR |
| 110756 | - if( pazResult==0 ) return SQLITE_MISUSE_BKPT; | |
| 110863 | + if( !sqlite3SafetyCheckOk(db) || pazResult==0 ) return SQLITE_MISUSE_BKPT; | |
| 110757 | 110864 | #endif |
| 110758 | 110865 | *pazResult = 0; |
| 110759 | 110866 | if( pnColumn ) *pnColumn = 0; |
| 110760 | 110867 | if( pnRow ) *pnRow = 0; |
| 110761 | 110868 | if( pzErrMsg ) *pzErrMsg = 0; |
| @@ -118621,11 +118728,10 @@ | ||
| 118621 | 118728 | sqlite3_free(p->u.vtab.idxStr); |
| 118622 | 118729 | p->u.vtab.needFree = 0; |
| 118623 | 118730 | p->u.vtab.idxStr = 0; |
| 118624 | 118731 | }else if( (p->wsFlags & WHERE_AUTO_INDEX)!=0 && p->u.btree.pIndex!=0 ){ |
| 118625 | 118732 | sqlite3DbFree(db, p->u.btree.pIndex->zColAff); |
| 118626 | - sqlite3KeyInfoUnref(p->u.btree.pIndex->pKeyInfo); | |
| 118627 | 118733 | sqlite3DbFree(db, p->u.btree.pIndex); |
| 118628 | 118734 | p->u.btree.pIndex = 0; |
| 118629 | 118735 | } |
| 118630 | 118736 | } |
| 118631 | 118737 | } |
| @@ -125628,10 +125734,13 @@ | ||
| 125628 | 125734 | u8 enableLookaside; /* Saved value of db->lookaside.bEnabled */ |
| 125629 | 125735 | sqlite3 *db = pParse->db; /* The database connection */ |
| 125630 | 125736 | int mxSqlLen; /* Max length of an SQL string */ |
| 125631 | 125737 | |
| 125632 | 125738 | |
| 125739 | +#ifdef SQLITE_ENABLE_API_ARMOR | |
| 125740 | + if( zSql==0 || pzErrMsg==0 ) return SQLITE_MISUSE_BKPT; | |
| 125741 | +#endif | |
| 125633 | 125742 | mxSqlLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH]; |
| 125634 | 125743 | if( db->nVdbeActive==0 ){ |
| 125635 | 125744 | db->u1.isInterrupted = 0; |
| 125636 | 125745 | } |
| 125637 | 125746 | pParse->rc = SQLITE_OK; |
| @@ -125866,17 +125975,10 @@ | ||
| 125866 | 125975 | */ |
| 125867 | 125976 | SQLITE_API int sqlite3_complete(const char *zSql){ |
| 125868 | 125977 | u8 state = 0; /* Current state, using numbers defined in header comment */ |
| 125869 | 125978 | u8 token; /* Value of the next token */ |
| 125870 | 125979 | |
| 125871 | -#ifdef SQLITE_ENABLE_API_ARMOR | |
| 125872 | - if( zSql==0 ){ | |
| 125873 | - (void)SQLITE_MISUSE_BKPT; | |
| 125874 | - return 0; | |
| 125875 | - } | |
| 125876 | -#endif | |
| 125877 | - | |
| 125878 | 125980 | #ifndef SQLITE_OMIT_TRIGGER |
| 125879 | 125981 | /* A complex statement machine used to detect the end of a CREATE TRIGGER |
| 125880 | 125982 | ** statement. This is the normal case. |
| 125881 | 125983 | */ |
| 125882 | 125984 | static const u8 trans[8][8] = { |
| @@ -125901,10 +126003,17 @@ | ||
| 125901 | 126003 | /* 0 INVALID: */ { 1, 0, 2, }, |
| 125902 | 126004 | /* 1 START: */ { 1, 1, 2, }, |
| 125903 | 126005 | /* 2 NORMAL: */ { 1, 2, 2, }, |
| 125904 | 126006 | }; |
| 125905 | 126007 | #endif /* SQLITE_OMIT_TRIGGER */ |
| 126008 | + | |
| 126009 | +#ifdef SQLITE_ENABLE_API_ARMOR | |
| 126010 | + if( zSql==0 ){ | |
| 126011 | + (void)SQLITE_MISUSE_BKPT; | |
| 126012 | + return 0; | |
| 126013 | + } | |
| 126014 | +#endif | |
| 125906 | 126015 | |
| 125907 | 126016 | while( *zSql ){ |
| 125908 | 126017 | switch( *zSql ){ |
| 125909 | 126018 | case ';': { /* A semicolon */ |
| 125910 | 126019 | token = tkSEMI; |
| @@ -126203,11 +126312,11 @@ | ||
| 126203 | 126312 | ** If the following function pointer is not NULL and if |
| 126204 | 126313 | ** SQLITE_ENABLE_IOTRACE is enabled, then messages describing |
| 126205 | 126314 | ** I/O active are written using this function. These messages |
| 126206 | 126315 | ** are intended for debugging activity only. |
| 126207 | 126316 | */ |
| 126208 | -SQLITE_PRIVATE void (*sqlite3IoTrace)(const char*, ...) = 0; | |
| 126317 | +/* not-private */ void (*sqlite3IoTrace)(const char*, ...) = 0; | |
| 126209 | 126318 | #endif |
| 126210 | 126319 | |
| 126211 | 126320 | /* |
| 126212 | 126321 | ** If the following global variable points to a string which is the |
| 126213 | 126322 | ** name of a directory, then that directory will be used to store |
| @@ -126412,10 +126521,17 @@ | ||
| 126412 | 126521 | ** routine is not threadsafe. But it is safe to invoke this routine |
| 126413 | 126522 | ** on when SQLite is already shut down. If SQLite is already shut down |
| 126414 | 126523 | ** when this routine is invoked, then this routine is a harmless no-op. |
| 126415 | 126524 | */ |
| 126416 | 126525 | SQLITE_API int sqlite3_shutdown(void){ |
| 126526 | +#ifdef SQLITE_OMIT_WSD | |
| 126527 | + int rc = sqlite3_wsd_init(4096, 24); | |
| 126528 | + if( rc!=SQLITE_OK ){ | |
| 126529 | + return rc; | |
| 126530 | + } | |
| 126531 | +#endif | |
| 126532 | + | |
| 126417 | 126533 | if( sqlite3GlobalConfig.isInit ){ |
| 126418 | 126534 | #ifdef SQLITE_EXTRA_SHUTDOWN |
| 126419 | 126535 | void SQLITE_EXTRA_SHUTDOWN(void); |
| 126420 | 126536 | SQLITE_EXTRA_SHUTDOWN(); |
| 126421 | 126537 | #endif |
| @@ -126727,10 +126843,15 @@ | ||
| 126727 | 126843 | ** heap. */ |
| 126728 | 126844 | sqlite3GlobalConfig.nHeap = va_arg(ap, int); |
| 126729 | 126845 | break; |
| 126730 | 126846 | } |
| 126731 | 126847 | #endif |
| 126848 | + | |
| 126849 | + case SQLITE_CONFIG_PMASZ: { | |
| 126850 | + sqlite3GlobalConfig.szPma = va_arg(ap, unsigned int); | |
| 126851 | + break; | |
| 126852 | + } | |
| 126732 | 126853 | |
| 126733 | 126854 | default: { |
| 126734 | 126855 | rc = SQLITE_ERROR; |
| 126735 | 126856 | break; |
| 126736 | 126857 | } |
| @@ -127173,18 +127294,10 @@ | ||
| 127173 | 127294 | |
| 127174 | 127295 | /* Close all database connections */ |
| 127175 | 127296 | for(j=0; j<db->nDb; j++){ |
| 127176 | 127297 | struct Db *pDb = &db->aDb[j]; |
| 127177 | 127298 | if( pDb->pBt ){ |
| 127178 | - if( pDb->pSchema ){ | |
| 127179 | - /* Must clear the KeyInfo cache. See ticket [e4a18565a36884b00edf] */ | |
| 127180 | - for(i=sqliteHashFirst(&pDb->pSchema->idxHash); i; i=sqliteHashNext(i)){ | |
| 127181 | - Index *pIdx = sqliteHashData(i); | |
| 127182 | - sqlite3KeyInfoUnref(pIdx->pKeyInfo); | |
| 127183 | - pIdx->pKeyInfo = 0; | |
| 127184 | - } | |
| 127185 | - } | |
| 127186 | 127299 | sqlite3BtreeClose(pDb->pBt); |
| 127187 | 127300 | pDb->pBt = 0; |
| 127188 | 127301 | if( j!=1 ){ |
| 127189 | 127302 | pDb->pSchema = 0; |
| 127190 | 127303 | } |
| @@ -128308,36 +128421,10 @@ | ||
| 128308 | 128421 | */ |
| 128309 | 128422 | SQLITE_API const char *sqlite3_errstr(int rc){ |
| 128310 | 128423 | return sqlite3ErrStr(rc); |
| 128311 | 128424 | } |
| 128312 | 128425 | |
| 128313 | -/* | |
| 128314 | -** Invalidate all cached KeyInfo objects for database connection "db" | |
| 128315 | -*/ | |
| 128316 | -static void invalidateCachedKeyInfo(sqlite3 *db){ | |
| 128317 | - Db *pDb; /* A single database */ | |
| 128318 | - int iDb; /* The database index number */ | |
| 128319 | - HashElem *k; /* For looping over tables in pDb */ | |
| 128320 | - Table *pTab; /* A table in the database */ | |
| 128321 | - Index *pIdx; /* Each index */ | |
| 128322 | - | |
| 128323 | - for(iDb=0, pDb=db->aDb; iDb<db->nDb; iDb++, pDb++){ | |
| 128324 | - if( pDb->pBt==0 ) continue; | |
| 128325 | - sqlite3BtreeEnter(pDb->pBt); | |
| 128326 | - for(k=sqliteHashFirst(&pDb->pSchema->tblHash); k; k=sqliteHashNext(k)){ | |
| 128327 | - pTab = (Table*)sqliteHashData(k); | |
| 128328 | - for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ | |
| 128329 | - if( pIdx->pKeyInfo && pIdx->pKeyInfo->db==db ){ | |
| 128330 | - sqlite3KeyInfoUnref(pIdx->pKeyInfo); | |
| 128331 | - pIdx->pKeyInfo = 0; | |
| 128332 | - } | |
| 128333 | - } | |
| 128334 | - } | |
| 128335 | - sqlite3BtreeLeave(pDb->pBt); | |
| 128336 | - } | |
| 128337 | -} | |
| 128338 | - | |
| 128339 | 128426 | /* |
| 128340 | 128427 | ** Create a new collating function for database "db". The name is zName |
| 128341 | 128428 | ** and the encoding is enc. |
| 128342 | 128429 | */ |
| 128343 | 128430 | static int createCollation( |
| @@ -128377,11 +128464,10 @@ | ||
| 128377 | 128464 | sqlite3ErrorWithMsg(db, SQLITE_BUSY, |
| 128378 | 128465 | "unable to delete/modify collation sequence due to active statements"); |
| 128379 | 128466 | return SQLITE_BUSY; |
| 128380 | 128467 | } |
| 128381 | 128468 | sqlite3ExpirePreparedStatements(db); |
| 128382 | - invalidateCachedKeyInfo(db); | |
| 128383 | 128469 | |
| 128384 | 128470 | /* If collation sequence pColl was created directly by a call to |
| 128385 | 128471 | ** sqlite3_create_collation, and not generated by synthCollSeq(), |
| 128386 | 128472 | ** then any copies made by synthCollSeq() need to be invalidated. |
| 128387 | 128473 | ** Also, collation destructor - CollSeq.xDel() - function may need |
| @@ -128882,10 +128968,13 @@ | ||
| 128882 | 128968 | | SQLITE_RecTriggers |
| 128883 | 128969 | #endif |
| 128884 | 128970 | #if defined(SQLITE_DEFAULT_FOREIGN_KEYS) && SQLITE_DEFAULT_FOREIGN_KEYS |
| 128885 | 128971 | | SQLITE_ForeignKeys |
| 128886 | 128972 | #endif |
| 128973 | +#if defined(SQLITE_REVERSE_UNORDERED_SELECTS) | |
| 128974 | + | SQLITE_ReverseOrder | |
| 128975 | +#endif | |
| 128887 | 128976 | ; |
| 128888 | 128977 | sqlite3HashInit(&db->aCollSeq); |
| 128889 | 128978 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| 128890 | 128979 | sqlite3HashInit(&db->aModule); |
| 128891 | 128980 | #endif |
| @@ -128929,11 +129018,14 @@ | ||
| 128929 | 129018 | rc = SQLITE_NOMEM; |
| 128930 | 129019 | } |
| 128931 | 129020 | sqlite3Error(db, rc); |
| 128932 | 129021 | goto opendb_out; |
| 128933 | 129022 | } |
| 129023 | + sqlite3BtreeEnter(db->aDb[0].pBt); | |
| 128934 | 129024 | db->aDb[0].pSchema = sqlite3SchemaGet(db, db->aDb[0].pBt); |
| 129025 | + if( !db->mallocFailed ) ENC(db) = SCHEMA_ENC(db); | |
| 129026 | + sqlite3BtreeLeave(db->aDb[0].pBt); | |
| 128935 | 129027 | db->aDb[1].pSchema = sqlite3SchemaGet(db, 0); |
| 128936 | 129028 | |
| 128937 | 129029 | /* The default safety_level for the main database is 'full'; for the temp |
| 128938 | 129030 | ** database it is 'NONE'. This matches the pager layer defaults. |
| 128939 | 129031 | */ |
| @@ -129087,11 +129179,11 @@ | ||
| 129087 | 129179 | if( zFilename8 ){ |
| 129088 | 129180 | rc = openDatabase(zFilename8, ppDb, |
| 129089 | 129181 | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0); |
| 129090 | 129182 | assert( *ppDb || rc==SQLITE_NOMEM ); |
| 129091 | 129183 | if( rc==SQLITE_OK && !DbHasProperty(*ppDb, 0, DB_SchemaLoaded) ){ |
| 129092 | - ENC(*ppDb) = SQLITE_UTF16NATIVE; | |
| 129184 | + SCHEMA_ENC(*ppDb) = ENC(*ppDb) = SQLITE_UTF16NATIVE; | |
| 129093 | 129185 | } |
| 129094 | 129186 | }else{ |
| 129095 | 129187 | rc = SQLITE_NOMEM; |
| 129096 | 129188 | } |
| 129097 | 129189 | sqlite3ValueFree(pVal); |
| @@ -129283,11 +129375,10 @@ | ||
| 129283 | 129375 | |
| 129284 | 129376 | /* |
| 129285 | 129377 | ** Return meta information about a specific column of a database table. |
| 129286 | 129378 | ** See comment in sqlite3.h (sqlite.h.in) for details. |
| 129287 | 129379 | */ |
| 129288 | -#ifdef SQLITE_ENABLE_COLUMN_METADATA | |
| 129289 | 129380 | SQLITE_API int sqlite3_table_column_metadata( |
| 129290 | 129381 | sqlite3 *db, /* Connection handle */ |
| 129291 | 129382 | const char *zDbName, /* Database name or NULL */ |
| 129292 | 129383 | const char *zTableName, /* Table name */ |
| 129293 | 129384 | const char *zColumnName, /* Column name */ |
| @@ -129323,25 +129414,27 @@ | ||
| 129323 | 129414 | pTab = 0; |
| 129324 | 129415 | goto error_out; |
| 129325 | 129416 | } |
| 129326 | 129417 | |
| 129327 | 129418 | /* Find the column for which info is requested */ |
| 129328 | - if( sqlite3IsRowid(zColumnName) ){ | |
| 129329 | - iCol = pTab->iPKey; | |
| 129330 | - if( iCol>=0 ){ | |
| 129331 | - pCol = &pTab->aCol[iCol]; | |
| 129332 | - } | |
| 129419 | + if( zColumnName==0 ){ | |
| 129420 | + /* Query for existance of table only */ | |
| 129333 | 129421 | }else{ |
| 129334 | 129422 | for(iCol=0; iCol<pTab->nCol; iCol++){ |
| 129335 | 129423 | pCol = &pTab->aCol[iCol]; |
| 129336 | 129424 | if( 0==sqlite3StrICmp(pCol->zName, zColumnName) ){ |
| 129337 | 129425 | break; |
| 129338 | 129426 | } |
| 129339 | 129427 | } |
| 129340 | 129428 | if( iCol==pTab->nCol ){ |
| 129341 | - pTab = 0; | |
| 129342 | - goto error_out; | |
| 129429 | + if( HasRowid(pTab) && sqlite3IsRowid(zColumnName) ){ | |
| 129430 | + iCol = pTab->iPKey; | |
| 129431 | + pCol = iCol>=0 ? &pTab->aCol[iCol] : 0; | |
| 129432 | + }else{ | |
| 129433 | + pTab = 0; | |
| 129434 | + goto error_out; | |
| 129435 | + } | |
| 129343 | 129436 | } |
| 129344 | 129437 | } |
| 129345 | 129438 | |
| 129346 | 129439 | /* The following block stores the meta information that will be returned |
| 129347 | 129440 | ** to the caller in local variables zDataType, zCollSeq, notnull, primarykey |
| @@ -129390,11 +129483,10 @@ | ||
| 129390 | 129483 | sqlite3DbFree(db, zErrMsg); |
| 129391 | 129484 | rc = sqlite3ApiExit(db, rc); |
| 129392 | 129485 | sqlite3_mutex_leave(db->mutex); |
| 129393 | 129486 | return rc; |
| 129394 | 129487 | } |
| 129395 | -#endif | |
| 129396 | 129488 | |
| 129397 | 129489 | /* |
| 129398 | 129490 | ** Sleep for a little while. Return the amount of time slept. |
| 129399 | 129491 | */ |
| 129400 | 129492 | SQLITE_API int sqlite3_sleep(int ms){ |
| @@ -129829,32 +129921,34 @@ | ||
| 129829 | 129921 | /* |
| 129830 | 129922 | ** Return the filename of the database associated with a database |
| 129831 | 129923 | ** connection. |
| 129832 | 129924 | */ |
| 129833 | 129925 | SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName){ |
| 129926 | + Btree *pBt; | |
| 129834 | 129927 | #ifdef SQLITE_ENABLE_API_ARMOR |
| 129835 | 129928 | if( !sqlite3SafetyCheckOk(db) ){ |
| 129836 | 129929 | (void)SQLITE_MISUSE_BKPT; |
| 129837 | 129930 | return 0; |
| 129838 | 129931 | } |
| 129839 | 129932 | #endif |
| 129840 | - Btree *pBt = sqlite3DbNameToBtree(db, zDbName); | |
| 129933 | + pBt = sqlite3DbNameToBtree(db, zDbName); | |
| 129841 | 129934 | return pBt ? sqlite3BtreeGetFilename(pBt) : 0; |
| 129842 | 129935 | } |
| 129843 | 129936 | |
| 129844 | 129937 | /* |
| 129845 | 129938 | ** Return 1 if database is read-only or 0 if read/write. Return -1 if |
| 129846 | 129939 | ** no such database exists. |
| 129847 | 129940 | */ |
| 129848 | 129941 | SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName){ |
| 129942 | + Btree *pBt; | |
| 129849 | 129943 | #ifdef SQLITE_ENABLE_API_ARMOR |
| 129850 | 129944 | if( !sqlite3SafetyCheckOk(db) ){ |
| 129851 | 129945 | (void)SQLITE_MISUSE_BKPT; |
| 129852 | 129946 | return -1; |
| 129853 | 129947 | } |
| 129854 | 129948 | #endif |
| 129855 | - Btree *pBt = sqlite3DbNameToBtree(db, zDbName); | |
| 129949 | + pBt = sqlite3DbNameToBtree(db, zDbName); | |
| 129856 | 129950 | return pBt ? sqlite3BtreeIsReadonly(pBt) : -1; |
| 129857 | 129951 | } |
| 129858 | 129952 | |
| 129859 | 129953 | /************** End of main.c ************************************************/ |
| 129860 | 129954 | /************** Begin file notify.c ******************************************/ |
| @@ -150061,11 +150155,11 @@ | ||
| 150061 | 150155 | } |
| 150062 | 150156 | i = pCur->nPoint++; |
| 150063 | 150157 | pNew = pCur->aPoint + i; |
| 150064 | 150158 | pNew->rScore = rScore; |
| 150065 | 150159 | pNew->iLevel = iLevel; |
| 150066 | - assert( iLevel>=0 && iLevel<=RTREE_MAX_DEPTH ); | |
| 150160 | + assert( iLevel<=RTREE_MAX_DEPTH ); | |
| 150067 | 150161 | while( i>0 ){ |
| 150068 | 150162 | RtreeSearchPoint *pParent; |
| 150069 | 150163 | j = (i-1)/2; |
| 150070 | 150164 | pParent = pCur->aPoint + j; |
| 150071 | 150165 | if( rtreeSearchPointCompare(pNew, pParent)>=0 ) break; |
| 150072 | 150166 |
| --- src/sqlite3.c | |
| +++ src/sqlite3.c | |
| @@ -231,11 +231,11 @@ | |
| 231 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 232 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 233 | */ |
| 234 | #define SQLITE_VERSION "3.8.8" |
| 235 | #define SQLITE_VERSION_NUMBER 3008008 |
| 236 | #define SQLITE_SOURCE_ID "2014-12-06 14:56:49 6aeece19a235344be2537e66a3fe08b1febfb5a0" |
| 237 | |
| 238 | /* |
| 239 | ** CAPI3REF: Run-Time Library Version Numbers |
| 240 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 241 | ** |
| @@ -323,11 +323,11 @@ | |
| 323 | ** This interface only reports on the compile-time mutex setting |
| 324 | ** of the [SQLITE_THREADSAFE] flag. If SQLite is compiled with |
| 325 | ** SQLITE_THREADSAFE=1 or =2 then mutexes are enabled by default but |
| 326 | ** can be fully or partially disabled using a call to [sqlite3_config()] |
| 327 | ** with the verbs [SQLITE_CONFIG_SINGLETHREAD], [SQLITE_CONFIG_MULTITHREAD], |
| 328 | ** or [SQLITE_CONFIG_MUTEX]. ^(The return value of the |
| 329 | ** sqlite3_threadsafe() function shows only the compile-time setting of |
| 330 | ** thread safety, not any run-time changes to that setting made by |
| 331 | ** sqlite3_config(). In other words, the return value from sqlite3_threadsafe() |
| 332 | ** is unchanged by calls to sqlite3_config().)^ |
| 333 | ** |
| @@ -1692,11 +1692,11 @@ | |
| 1692 | ** configuration option. |
| 1693 | ** ^There are three arguments to SQLITE_CONFIG_PAGECACHE: A pointer to |
| 1694 | ** 8-byte aligned |
| 1695 | ** memory, the size of each page buffer (sz), and the number of pages (N). |
| 1696 | ** The sz argument should be the size of the largest database page |
| 1697 | ** (a power of two between 512 and 32768) plus some extra bytes for each |
| 1698 | ** page header. ^The number of extra bytes needed by the page header |
| 1699 | ** can be determined using the [SQLITE_CONFIG_PCACHE_HDRSZ] option |
| 1700 | ** to [sqlite3_config()]. |
| 1701 | ** ^It is harmless, apart from the wasted memory, |
| 1702 | ** for the sz parameter to be larger than necessary. The first |
| @@ -1872,10 +1872,21 @@ | |
| 1872 | ** <dd>^The SQLITE_CONFIG_PCACHE_HDRSZ option takes a single parameter which |
| 1873 | ** is a pointer to an integer and writes into that integer the number of extra |
| 1874 | ** bytes per page required for each page in [SQLITE_CONFIG_PAGECACHE]. |
| 1875 | ** The amount of extra space required can change depending on the compiler, |
| 1876 | ** target platform, and SQLite version. |
| 1877 | ** </dl> |
| 1878 | */ |
| 1879 | #define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */ |
| 1880 | #define SQLITE_CONFIG_MULTITHREAD 2 /* nil */ |
| 1881 | #define SQLITE_CONFIG_SERIALIZED 3 /* nil */ |
| @@ -1898,10 +1909,11 @@ | |
| 1898 | #define SQLITE_CONFIG_COVERING_INDEX_SCAN 20 /* int */ |
| 1899 | #define SQLITE_CONFIG_SQLLOG 21 /* xSqllog, void* */ |
| 1900 | #define SQLITE_CONFIG_MMAP_SIZE 22 /* sqlite3_int64, sqlite3_int64 */ |
| 1901 | #define SQLITE_CONFIG_WIN32_HEAPSIZE 23 /* int nByte */ |
| 1902 | #define SQLITE_CONFIG_PCACHE_HDRSZ 24 /* int *psz */ |
| 1903 | |
| 1904 | /* |
| 1905 | ** CAPI3REF: Database Connection Configuration Options |
| 1906 | ** |
| 1907 | ** These constants are the available integer configuration options that |
| @@ -5279,24 +5291,31 @@ | |
| 5279 | |
| 5280 | |
| 5281 | /* |
| 5282 | ** CAPI3REF: Extract Metadata About A Column Of A Table |
| 5283 | ** |
| 5284 | ** ^This routine returns metadata about a specific column of a specific |
| 5285 | ** database table accessible using the [database connection] handle |
| 5286 | ** passed as the first function argument. |
| 5287 | ** |
| 5288 | ** ^The column is identified by the second, third and fourth parameters to |
| 5289 | ** this function. ^The second parameter is either the name of the database |
| 5290 | ** (i.e. "main", "temp", or an attached database) containing the specified |
| 5291 | ** table or NULL. ^If it is NULL, then all attached databases are searched |
| 5292 | ** for the table using the same algorithm used by the database engine to |
| 5293 | ** resolve unqualified table references. |
| 5294 | ** |
| 5295 | ** ^The third and fourth parameters to this function are the table and column |
| 5296 | ** name of the desired column, respectively. Neither of these parameters |
| 5297 | ** may be NULL. |
| 5298 | ** |
| 5299 | ** ^Metadata is returned by writing to the memory locations passed as the 5th |
| 5300 | ** and subsequent parameters to this function. ^Any of these arguments may be |
| 5301 | ** NULL, in which case the corresponding element of metadata is omitted. |
| 5302 | ** |
| @@ -5311,36 +5330,33 @@ | |
| 5311 | ** <tr><td> 9th <td> int <td> True if column is [AUTOINCREMENT] |
| 5312 | ** </table> |
| 5313 | ** </blockquote>)^ |
| 5314 | ** |
| 5315 | ** ^The memory pointed to by the character pointers returned for the |
| 5316 | ** declaration type and collation sequence is valid only until the next |
| 5317 | ** call to any SQLite API function. |
| 5318 | ** |
| 5319 | ** ^If the specified table is actually a view, an [error code] is returned. |
| 5320 | ** |
| 5321 | ** ^If the specified column is "rowid", "oid" or "_rowid_" and an |
| 5322 | ** [INTEGER PRIMARY KEY] column has been explicitly declared, then the output |
| 5323 | ** parameters are set for the explicitly declared column. ^(If there is no |
| 5324 | ** explicitly declared [INTEGER PRIMARY KEY] column, then the output |
| 5325 | ** parameters are set as follows: |
| 5326 | ** |
| 5327 | ** <pre> |
| 5328 | ** data type: "INTEGER" |
| 5329 | ** collation sequence: "BINARY" |
| 5330 | ** not null: 0 |
| 5331 | ** primary key: 1 |
| 5332 | ** auto increment: 0 |
| 5333 | ** </pre>)^ |
| 5334 | ** |
| 5335 | ** ^(This function may load one or more schemas from database files. If an |
| 5336 | ** error occurs during this process, or if the requested table or column |
| 5337 | ** cannot be found, an [error code] is returned and an error message left |
| 5338 | ** in the [database connection] (to be retrieved using sqlite3_errmsg()).)^ |
| 5339 | ** |
| 5340 | ** ^This API is only available if the library was compiled with the |
| 5341 | ** [SQLITE_ENABLE_COLUMN_METADATA] C-preprocessor symbol defined. |
| 5342 | */ |
| 5343 | SQLITE_API int sqlite3_table_column_metadata( |
| 5344 | sqlite3 *db, /* Connection handle */ |
| 5345 | const char *zDbName, /* Database name or NULL */ |
| 5346 | const char *zTableName, /* Table name */ |
| @@ -7303,16 +7319,14 @@ | |
| 7303 | |
| 7304 | /* |
| 7305 | ** CAPI3REF: Write-Ahead Log Commit Hook |
| 7306 | ** |
| 7307 | ** ^The [sqlite3_wal_hook()] function is used to register a callback that |
| 7308 | ** will be invoked each time a database connection commits data to a |
| 7309 | ** [write-ahead log] (i.e. whenever a transaction is committed in |
| 7310 | ** [journal_mode | journal_mode=WAL mode]). |
| 7311 | ** |
| 7312 | ** ^The callback is invoked by SQLite after the commit has taken place and |
| 7313 | ** the associated write-lock on the database released, so the implementation |
| 7314 | ** may read, write or [checkpoint] the database as required. |
| 7315 | ** |
| 7316 | ** ^The first parameter passed to the callback function when it is invoked |
| 7317 | ** is a copy of the third parameter passed to sqlite3_wal_hook() when |
| 7318 | ** registering the callback. ^The second is a copy of the database handle. |
| @@ -9096,11 +9110,11 @@ | |
| 9096 | #define _BTREE_H_ |
| 9097 | |
| 9098 | /* TODO: This definition is just included so other modules compile. It |
| 9099 | ** needs to be revisited. |
| 9100 | */ |
| 9101 | #define SQLITE_N_BTREE_META 10 |
| 9102 | |
| 9103 | /* |
| 9104 | ** If defined as non-zero, auto-vacuum is enabled by default. Otherwise |
| 9105 | ** it must be turned on for each database using "PRAGMA auto_vacuum = 1". |
| 9106 | */ |
| @@ -9211,10 +9225,15 @@ | |
| 9211 | ** offset = 36 + (idx * 4) |
| 9212 | ** |
| 9213 | ** For example, the free-page-count field is located at byte offset 36 of |
| 9214 | ** the database file header. The incr-vacuum-flag field is located at |
| 9215 | ** byte offset 64 (== 36+4*7). |
| 9216 | */ |
| 9217 | #define BTREE_FREE_PAGE_COUNT 0 |
| 9218 | #define BTREE_SCHEMA_VERSION 1 |
| 9219 | #define BTREE_FILE_FORMAT 2 |
| 9220 | #define BTREE_DEFAULT_CACHE_SIZE 3 |
| @@ -9221,10 +9240,11 @@ | |
| 9221 | #define BTREE_LARGEST_ROOT_PAGE 4 |
| 9222 | #define BTREE_TEXT_ENCODING 5 |
| 9223 | #define BTREE_USER_VERSION 6 |
| 9224 | #define BTREE_INCR_VACUUM 7 |
| 9225 | #define BTREE_APPLICATION_ID 8 |
| 9226 | |
| 9227 | /* |
| 9228 | ** Values that may be OR'd together to form the second argument of an |
| 9229 | ** sqlite3BtreeCursorHints() call. |
| 9230 | */ |
| @@ -10002,10 +10022,11 @@ | |
| 10002 | SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager); |
| 10003 | #endif |
| 10004 | |
| 10005 | /* Functions used to query pager state and configuration. */ |
| 10006 | SQLITE_PRIVATE u8 sqlite3PagerIsreadonly(Pager*); |
| 10007 | SQLITE_PRIVATE int sqlite3PagerRefcount(Pager*); |
| 10008 | SQLITE_PRIVATE int sqlite3PagerMemUsed(Pager*); |
| 10009 | SQLITE_PRIVATE const char *sqlite3PagerFilename(Pager*, int); |
| 10010 | SQLITE_PRIVATE const sqlite3_vfs *sqlite3PagerVfs(Pager*); |
| 10011 | SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager*); |
| @@ -10743,10 +10764,11 @@ | |
| 10743 | i64 szMmap; /* Default mmap_size setting */ |
| 10744 | unsigned int openFlags; /* Flags passed to sqlite3_vfs.xOpen() */ |
| 10745 | int errCode; /* Most recent error code (SQLITE_*) */ |
| 10746 | int errMask; /* & result codes with this before returning */ |
| 10747 | u16 dbOptFlags; /* Flags to enable/disable optimizations */ |
| 10748 | u8 autoCommit; /* The auto-commit flag. */ |
| 10749 | u8 temp_store; /* 1: file 2: memory 0: default */ |
| 10750 | u8 mallocFailed; /* True if we have seen a malloc failure */ |
| 10751 | u8 dfltLockMode; /* Default locking-mode for attached dbs */ |
| 10752 | signed char nextAutovac; /* Autovac setting after VACUUM if >=0 */ |
| @@ -10844,11 +10866,12 @@ | |
| 10844 | }; |
| 10845 | |
| 10846 | /* |
| 10847 | ** A macro to discover the encoding of a database. |
| 10848 | */ |
| 10849 | #define ENC(db) ((db)->aDb[0].pSchema->enc) |
| 10850 | |
| 10851 | /* |
| 10852 | ** Possible values for the sqlite3.flags. |
| 10853 | */ |
| 10854 | #define SQLITE_VdbeTrace 0x00000001 /* True to trace VDBE execution */ |
| @@ -11468,11 +11491,10 @@ | |
| 11468 | Index *pNext; /* The next index associated with the same table */ |
| 11469 | Schema *pSchema; /* Schema containing this index */ |
| 11470 | u8 *aSortOrder; /* for each column: True==DESC, False==ASC */ |
| 11471 | char **azColl; /* Array of collation sequence names for index */ |
| 11472 | Expr *pPartIdxWhere; /* WHERE clause for partial indices */ |
| 11473 | KeyInfo *pKeyInfo; /* A KeyInfo object suitable for this index */ |
| 11474 | int tnum; /* DB Page containing root of this index */ |
| 11475 | LogEst szIdxRow; /* Estimated average row size in bytes */ |
| 11476 | u16 nKeyCol; /* Number of columns forming the key */ |
| 11477 | u16 nColumn; /* Number of columns stored in the index */ |
| 11478 | u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */ |
| @@ -12522,10 +12544,11 @@ | |
| 12522 | void *pPage; /* Page cache memory */ |
| 12523 | int szPage; /* Size of each page in pPage[] */ |
| 12524 | int nPage; /* Number of pages in pPage[] */ |
| 12525 | int mxParserStack; /* maximum depth of the parser stack */ |
| 12526 | int sharedCacheEnabled; /* true if shared-cache mode enabled */ |
| 12527 | /* The above might be initialized to non-zero. The following need to always |
| 12528 | ** initially be zero, however. */ |
| 12529 | int isInit; /* True after initialization has finished */ |
| 12530 | int inProgress; /* True while initialization in progress */ |
| 12531 | int isMutexInit; /* True after mutexes are initialized */ |
| @@ -13444,11 +13467,11 @@ | |
| 13444 | ** print I/O tracing messages. |
| 13445 | */ |
| 13446 | #ifdef SQLITE_ENABLE_IOTRACE |
| 13447 | # define IOTRACE(A) if( sqlite3IoTrace ){ sqlite3IoTrace A; } |
| 13448 | SQLITE_PRIVATE void sqlite3VdbeIOTraceSql(Vdbe*); |
| 13449 | SQLITE_PRIVATE void (*sqlite3IoTrace)(const char*,...); |
| 13450 | #else |
| 13451 | # define IOTRACE(A) |
| 13452 | # define sqlite3VdbeIOTraceSql(X) |
| 13453 | #endif |
| 13454 | |
| @@ -13657,10 +13680,17 @@ | |
| 13657 | */ |
| 13658 | #ifndef SQLITE_ALLOW_COVERING_INDEX_SCAN |
| 13659 | # define SQLITE_ALLOW_COVERING_INDEX_SCAN 1 |
| 13660 | #endif |
| 13661 | |
| 13662 | /* |
| 13663 | ** The following singleton contains the global configuration for |
| 13664 | ** the SQLite library. |
| 13665 | */ |
| 13666 | SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = { |
| @@ -13687,10 +13717,11 @@ | |
| 13687 | (void*)0, /* pPage */ |
| 13688 | 0, /* szPage */ |
| 13689 | 0, /* nPage */ |
| 13690 | 0, /* mxParserStack */ |
| 13691 | 0, /* sharedCacheEnabled */ |
| 13692 | /* All the rest should always be initialized to zero */ |
| 13693 | 0, /* isInit */ |
| 13694 | 0, /* inProgress */ |
| 13695 | 0, /* isMutexInit */ |
| 13696 | 0, /* isMallocInit */ |
| @@ -19972,10 +20003,16 @@ | |
| 19972 | #endif |
| 19973 | } |
| 19974 | break; |
| 19975 | } |
| 19976 | default: { |
| 19977 | assert( iType-2 >= 0 ); |
| 19978 | assert( iType-2 < ArraySize(winMutex_staticMutexes) ); |
| 19979 | assert( winMutex_isInit==1 ); |
| 19980 | p = &winMutex_staticMutexes[iType-2]; |
| 19981 | #ifdef SQLITE_DEBUG |
| @@ -28779,28 +28816,31 @@ | |
| 28779 | do{ |
| 28780 | err = osFallocate(pFile->h, buf.st_size, nSize-buf.st_size); |
| 28781 | }while( err==EINTR ); |
| 28782 | if( err ) return SQLITE_IOERR_WRITE; |
| 28783 | #else |
| 28784 | /* If the OS does not have posix_fallocate(), fake it. First use |
| 28785 | ** ftruncate() to set the file size, then write a single byte to |
| 28786 | ** the last byte in each block within the extended region. This |
| 28787 | ** is the same technique used by glibc to implement posix_fallocate() |
| 28788 | ** on systems that do not have a real fallocate() system call. |
| 28789 | */ |
| 28790 | int nBlk = buf.st_blksize; /* File-system block size */ |
| 28791 | i64 iWrite; /* Next offset to write to */ |
| 28792 | |
| 28793 | if( robust_ftruncate(pFile->h, nSize) ){ |
| 28794 | pFile->lastErrno = errno; |
| 28795 | return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath); |
| 28796 | } |
| 28797 | iWrite = ((buf.st_size + 2*nBlk - 1)/nBlk)*nBlk-1; |
| 28798 | while( iWrite<nSize ){ |
| 28799 | int nWrite = seekAndWrite(pFile, iWrite, "", 1); |
| 28800 | if( nWrite!=1 ) return SQLITE_IOERR_WRITE; |
| 28801 | iWrite += nBlk; |
| 28802 | } |
| 28803 | #endif |
| 28804 | } |
| 28805 | } |
| 28806 | |
| @@ -34014,12 +34054,12 @@ | |
| 34014 | */ |
| 34015 | SQLITE_API int sqlite3_win32_reset_heap(){ |
| 34016 | int rc; |
| 34017 | MUTEX_LOGIC( sqlite3_mutex *pMaster; ) /* The main static mutex */ |
| 34018 | MUTEX_LOGIC( sqlite3_mutex *pMem; ) /* The memsys static mutex */ |
| 34019 | MUTEX_LOGIC( pMaster = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); ) |
| 34020 | MUTEX_LOGIC( pMem = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM); ) |
| 34021 | sqlite3_mutex_enter(pMaster); |
| 34022 | sqlite3_mutex_enter(pMem); |
| 34023 | winMemAssertMagic(); |
| 34024 | if( winMemGetHeap()!=NULL && winMemGetOwned() && sqlite3_memory_used()==0 ){ |
| 34025 | /* |
| @@ -35290,11 +35330,11 @@ | |
| 35290 | sqlite3_file *id, /* File to read from */ |
| 35291 | void *pBuf, /* Write content into this buffer */ |
| 35292 | int amt, /* Number of bytes to read */ |
| 35293 | sqlite3_int64 offset /* Begin reading at this offset */ |
| 35294 | ){ |
| 35295 | #if !SQLITE_OS_WINCE |
| 35296 | OVERLAPPED overlapped; /* The offset for ReadFile. */ |
| 35297 | #endif |
| 35298 | winFile *pFile = (winFile*)id; /* file handle */ |
| 35299 | DWORD nRead; /* Number of bytes actually read from file */ |
| 35300 | int nRetry = 0; /* Number of retrys */ |
| @@ -35322,11 +35362,11 @@ | |
| 35322 | offset += nCopy; |
| 35323 | } |
| 35324 | } |
| 35325 | #endif |
| 35326 | |
| 35327 | #if SQLITE_OS_WINCE |
| 35328 | if( winSeekFile(pFile, offset) ){ |
| 35329 | OSTRACE(("READ file=%p, rc=SQLITE_FULL\n", pFile->h)); |
| 35330 | return SQLITE_FULL; |
| 35331 | } |
| 35332 | while( !osReadFile(pFile->h, pBuf, amt, &nRead, 0) ){ |
| @@ -35394,32 +35434,32 @@ | |
| 35394 | offset += nCopy; |
| 35395 | } |
| 35396 | } |
| 35397 | #endif |
| 35398 | |
| 35399 | #if SQLITE_OS_WINCE |
| 35400 | rc = winSeekFile(pFile, offset); |
| 35401 | if( rc==0 ){ |
| 35402 | #else |
| 35403 | { |
| 35404 | #endif |
| 35405 | #if !SQLITE_OS_WINCE |
| 35406 | OVERLAPPED overlapped; /* The offset for WriteFile. */ |
| 35407 | #endif |
| 35408 | u8 *aRem = (u8 *)pBuf; /* Data yet to be written */ |
| 35409 | int nRem = amt; /* Number of bytes yet to be written */ |
| 35410 | DWORD nWrite; /* Bytes written by each WriteFile() call */ |
| 35411 | DWORD lastErrno = NO_ERROR; /* Value returned by GetLastError() */ |
| 35412 | |
| 35413 | #if !SQLITE_OS_WINCE |
| 35414 | memset(&overlapped, 0, sizeof(OVERLAPPED)); |
| 35415 | overlapped.Offset = (LONG)(offset & 0xffffffff); |
| 35416 | overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff); |
| 35417 | #endif |
| 35418 | |
| 35419 | while( nRem>0 ){ |
| 35420 | #if SQLITE_OS_WINCE |
| 35421 | if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, 0) ){ |
| 35422 | #else |
| 35423 | if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, &overlapped) ){ |
| 35424 | #endif |
| 35425 | if( winRetryIoerr(&nRetry, &lastErrno) ) continue; |
| @@ -35428,11 +35468,11 @@ | |
| 35428 | assert( nWrite==0 || nWrite<=(DWORD)nRem ); |
| 35429 | if( nWrite==0 || nWrite>(DWORD)nRem ){ |
| 35430 | lastErrno = osGetLastError(); |
| 35431 | break; |
| 35432 | } |
| 35433 | #if !SQLITE_OS_WINCE |
| 35434 | offset += nWrite; |
| 35435 | overlapped.Offset = (LONG)(offset & 0xffffffff); |
| 35436 | overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff); |
| 35437 | #endif |
| 35438 | aRem += nWrite; |
| @@ -38974,11 +39014,12 @@ | |
| 38974 | SQLITE_PRIVATE int sqlite3PcacheSetPageSize(PCache *pCache, int szPage){ |
| 38975 | assert( pCache->nRef==0 && pCache->pDirty==0 ); |
| 38976 | if( pCache->szPage ){ |
| 38977 | sqlite3_pcache *pNew; |
| 38978 | pNew = sqlite3GlobalConfig.pcache2.xCreate( |
| 38979 | szPage, pCache->szExtra + sizeof(PgHdr), pCache->bPurgeable |
| 38980 | ); |
| 38981 | if( pNew==0 ) return SQLITE_NOMEM; |
| 38982 | sqlite3GlobalConfig.pcache2.xCachesize(pNew, numberOfCachePages(pCache)); |
| 38983 | if( pCache->pCache ){ |
| 38984 | sqlite3GlobalConfig.pcache2.xDestroy(pCache->pCache); |
| @@ -39433,11 +39474,11 @@ | |
| 39433 | |
| 39434 | /* |
| 39435 | ** Return the size of the header added by this middleware layer |
| 39436 | ** in the page-cache hierarchy. |
| 39437 | */ |
| 39438 | SQLITE_PRIVATE int sqlite3HeaderSizePcache(void){ return sizeof(PgHdr); } |
| 39439 | |
| 39440 | |
| 39441 | #if defined(SQLITE_CHECK_PAGES) || defined(SQLITE_DEBUG) |
| 39442 | /* |
| 39443 | ** For all dirty pages currently in the cache, invoke the specified |
| @@ -39749,11 +39790,11 @@ | |
| 39749 | pcache1Free(pPg); |
| 39750 | sqlite3_free(p); |
| 39751 | pPg = 0; |
| 39752 | } |
| 39753 | #else |
| 39754 | pPg = pcache1Alloc(sizeof(PgHdr1) + pCache->szPage + pCache->szExtra); |
| 39755 | p = (PgHdr1 *)&((u8 *)pPg)[pCache->szPage]; |
| 39756 | #endif |
| 39757 | pcache1EnterMutex(pCache->pGroup); |
| 39758 | |
| 39759 | if( pPg ){ |
| @@ -40437,11 +40478,11 @@ | |
| 40437 | } |
| 40438 | |
| 40439 | /* |
| 40440 | ** Return the size of the header on each page of this PCACHE implementation. |
| 40441 | */ |
| 40442 | SQLITE_PRIVATE int sqlite3HeaderSizePcache1(void){ return sizeof(PgHdr1); } |
| 40443 | |
| 40444 | #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT |
| 40445 | /* |
| 40446 | ** This function is called to free superfluous dynamically allocated memory |
| 40447 | ** held by the pager system. Memory in use by any SQLite pager allocated |
| @@ -41795,10 +41836,12 @@ | |
| 41795 | u8 eLock; /* Current lock held on database file */ |
| 41796 | u8 changeCountDone; /* Set after incrementing the change-counter */ |
| 41797 | u8 setMaster; /* True if a m-j name has been written to jrnl */ |
| 41798 | u8 doNotSpill; /* Do not spill the cache when non-zero */ |
| 41799 | u8 subjInMemory; /* True to use in-memory sub-journals */ |
| 41800 | Pgno dbSize; /* Number of pages in the database */ |
| 41801 | Pgno dbOrigSize; /* dbSize before the current transaction */ |
| 41802 | Pgno dbFileSize; /* Number of pages in the database file */ |
| 41803 | Pgno dbHintSize; /* Value passed to FCNTL_SIZE_HINT call */ |
| 41804 | int errCode; /* One of several kinds of errors */ |
| @@ -41812,13 +41855,13 @@ | |
| 41812 | i64 journalOff; /* Current write offset in the journal file */ |
| 41813 | i64 journalHdr; /* Byte offset to previous journal header */ |
| 41814 | sqlite3_backup *pBackup; /* Pointer to list of ongoing backup processes */ |
| 41815 | PagerSavepoint *aSavepoint; /* Array of active savepoints */ |
| 41816 | int nSavepoint; /* Number of elements in aSavepoint[] */ |
| 41817 | char dbFileVers[16]; /* Changes whenever database file changes */ |
| 41818 | |
| 41819 | u8 bUseFetch; /* True to use xFetch() */ |
| 41820 | int nMmapOut; /* Number of mmap pages currently outstanding */ |
| 41821 | sqlite3_int64 szMmap; /* Desired maximum mmap size */ |
| 41822 | PgHdr *pMmapFreelist; /* List of free mmap page headers (pDirty) */ |
| 41823 | /* |
| 41824 | ** End of the routinely-changing class members |
| @@ -42830,13 +42873,22 @@ | |
| 42830 | |
| 42831 | /* |
| 42832 | ** Discard the entire contents of the in-memory page-cache. |
| 42833 | */ |
| 42834 | static void pager_reset(Pager *pPager){ |
| 42835 | sqlite3BackupRestart(pPager->pBackup); |
| 42836 | sqlite3PcacheClear(pPager->pPCache); |
| 42837 | } |
| 42838 | |
| 42839 | /* |
| 42840 | ** Free all structures in the Pager.aSavepoint[] array and set both |
| 42841 | ** Pager.aSavepoint and Pager.nSavepoint to zero. Close the sub-journal |
| 42842 | ** if it is open and the pager is not in exclusive mode. |
| @@ -45036,11 +45088,11 @@ | |
| 45036 | Pgno pgno, /* Page number */ |
| 45037 | void *pData, /* xFetch()'d data for this page */ |
| 45038 | PgHdr **ppPage /* OUT: Acquired page object */ |
| 45039 | ){ |
| 45040 | PgHdr *p; /* Memory mapped page to return */ |
| 45041 | |
| 45042 | if( pPager->pMmapFreelist ){ |
| 45043 | *ppPage = p = pPager->pMmapFreelist; |
| 45044 | pPager->pMmapFreelist = p->pDirty; |
| 45045 | p->pDirty = 0; |
| 45046 | memset(p->pExtra, 0, pPager->nExtra); |
| @@ -46267,20 +46319,16 @@ | |
| 46267 | assert( (pPager->eLock==SHARED_LOCK) |
| 46268 | || (pPager->exclusiveMode && pPager->eLock>SHARED_LOCK) |
| 46269 | ); |
| 46270 | } |
| 46271 | |
| 46272 | if( !pPager->tempFile && ( |
| 46273 | pPager->pBackup |
| 46274 | || sqlite3PcachePagecount(pPager->pPCache)>0 |
| 46275 | || USEFETCH(pPager) |
| 46276 | )){ |
| 46277 | /* The shared-lock has just been acquired on the database file |
| 46278 | ** and there are already pages in the cache (from a previous |
| 46279 | ** read or write transaction). Check to see if the database |
| 46280 | ** has been modified. If the database has changed, flush the |
| 46281 | ** cache. |
| 46282 | ** |
| 46283 | ** Database changes is detected by looking at 15 bytes beginning |
| 46284 | ** at offset 24 into the file. The first 4 of these 16 bytes are |
| 46285 | ** a 32-bit counter that is incremented with each change. The |
| 46286 | ** other bytes change randomly with each file change when |
| @@ -46441,10 +46489,11 @@ | |
| 46441 | assert( noContent==0 || bMmapOk==0 ); |
| 46442 | |
| 46443 | if( pgno==0 ){ |
| 46444 | return SQLITE_CORRUPT_BKPT; |
| 46445 | } |
| 46446 | |
| 46447 | /* If the pager is in the error state, return an error immediately. |
| 46448 | ** Otherwise, request the page from the PCache layer. */ |
| 46449 | if( pPager->errCode!=SQLITE_OK ){ |
| 46450 | rc = pPager->errCode; |
| @@ -46590,10 +46639,11 @@ | |
| 46590 | sqlite3_pcache_page *pPage; |
| 46591 | assert( pPager!=0 ); |
| 46592 | assert( pgno!=0 ); |
| 46593 | assert( pPager->pPCache!=0 ); |
| 46594 | pPage = sqlite3PcacheFetch(pPager->pPCache, pgno, 0); |
| 46595 | return sqlite3PcacheFetchFinish(pPager->pPCache, pgno, pPage); |
| 46596 | } |
| 46597 | |
| 46598 | /* |
| 46599 | ** Release a page reference. |
| @@ -47456,10 +47506,11 @@ | |
| 47456 | pPager->eState = PAGER_READER; |
| 47457 | return SQLITE_OK; |
| 47458 | } |
| 47459 | |
| 47460 | PAGERTRACE(("COMMIT %d\n", PAGERID(pPager))); |
| 47461 | rc = pager_end_transaction(pPager, pPager->setMaster, 1); |
| 47462 | return pager_error(pPager, rc); |
| 47463 | } |
| 47464 | |
| 47465 | /* |
| @@ -50825,11 +50876,11 @@ | |
| 50825 | } |
| 50826 | nCollide = HASHTABLE_NSLOT; |
| 50827 | for(iKey=walHash(pgno); aHash[iKey]; iKey=walNextHash(iKey)){ |
| 50828 | u32 iFrame = aHash[iKey] + iZero; |
| 50829 | if( iFrame<=iLast && aPgno[aHash[iKey]]==pgno ){ |
| 50830 | /* assert( iFrame>iRead ); -- not true if there is corruption */ |
| 50831 | iRead = iFrame; |
| 50832 | } |
| 50833 | if( (nCollide--)==0 ){ |
| 50834 | return SQLITE_CORRUPT_BKPT; |
| 50835 | } |
| @@ -51931,10 +51982,11 @@ | |
| 51931 | u8 inTrans; /* TRANS_NONE, TRANS_READ or TRANS_WRITE */ |
| 51932 | u8 sharable; /* True if we can share pBt with another db */ |
| 51933 | u8 locked; /* True if db currently has pBt locked */ |
| 51934 | int wantToLock; /* Number of nested calls to sqlite3BtreeEnter() */ |
| 51935 | int nBackup; /* Number of backup operations reading this btree */ |
| 51936 | Btree *pNext; /* List of other sharable Btrees from the same db */ |
| 51937 | Btree *pPrev; /* Back pointer of the same list */ |
| 51938 | #ifndef SQLITE_OMIT_SHARED_CACHE |
| 51939 | BtLock lock; /* Object used to lock page 1 */ |
| 51940 | #endif |
| @@ -56094,10 +56146,11 @@ | |
| 56094 | rc = sqlite3PagerCommitPhaseTwo(pBt->pPager); |
| 56095 | if( rc!=SQLITE_OK && bCleanup==0 ){ |
| 56096 | sqlite3BtreeLeave(p); |
| 56097 | return rc; |
| 56098 | } |
| 56099 | pBt->inTransaction = TRANS_READ; |
| 56100 | btreeClearHasContent(pBt); |
| 56101 | } |
| 56102 | |
| 56103 | btreeEndTransaction(p); |
| @@ -56457,11 +56510,11 @@ | |
| 56457 | } |
| 56458 | for(i=0; i<=pCur->iPage; i++){ |
| 56459 | releasePage(pCur->apPage[i]); |
| 56460 | } |
| 56461 | unlockBtreeIfUnused(pBt); |
| 56462 | sqlite3DbFree(pBtree->db, pCur->aOverflow); |
| 56463 | /* sqlite3_free(pCur); */ |
| 56464 | sqlite3BtreeLeave(pBtree); |
| 56465 | } |
| 56466 | return SQLITE_OK; |
| 56467 | } |
| @@ -56751,10 +56804,11 @@ | |
| 56751 | pBuf += a; |
| 56752 | amt -= a; |
| 56753 | }else{ |
| 56754 | offset -= pCur->info.nLocal; |
| 56755 | } |
| 56756 | |
| 56757 | if( rc==SQLITE_OK && amt>0 ){ |
| 56758 | const u32 ovflSize = pBt->usableSize - 4; /* Bytes content per ovfl page */ |
| 56759 | Pgno nextPage; |
| 56760 | |
| @@ -56769,12 +56823,12 @@ | |
| 56769 | ** means "not yet known" (the cache is lazily populated). |
| 56770 | */ |
| 56771 | if( eOp!=2 && (pCur->curFlags & BTCF_ValidOvfl)==0 ){ |
| 56772 | int nOvfl = (pCur->info.nPayload-pCur->info.nLocal+ovflSize-1)/ovflSize; |
| 56773 | if( nOvfl>pCur->nOvflAlloc ){ |
| 56774 | Pgno *aNew = (Pgno*)sqlite3DbRealloc( |
| 56775 | pCur->pBtree->db, pCur->aOverflow, nOvfl*2*sizeof(Pgno) |
| 56776 | ); |
| 56777 | if( aNew==0 ){ |
| 56778 | rc = SQLITE_NOMEM; |
| 56779 | }else{ |
| 56780 | pCur->nOvflAlloc = nOvfl*2; |
| @@ -56817,10 +56871,11 @@ | |
| 56817 | ** Note that the aOverflow[] array must be allocated because eOp!=2 |
| 56818 | ** here. If eOp==2, then offset==0 and this branch is never taken. |
| 56819 | */ |
| 56820 | assert( eOp!=2 ); |
| 56821 | assert( pCur->curFlags & BTCF_ValidOvfl ); |
| 56822 | if( pCur->aOverflow[iIdx+1] ){ |
| 56823 | nextPage = pCur->aOverflow[iIdx+1]; |
| 56824 | }else{ |
| 56825 | rc = getOverflowPage(pBt, nextPage, 0, &nextPage); |
| 56826 | } |
| @@ -59329,11 +59384,11 @@ | |
| 59329 | + nMaxCells*sizeof(u16) /* szCell */ |
| 59330 | + pBt->pageSize; /* aSpace1 */ |
| 59331 | |
| 59332 | /* EVIDENCE-OF: R-28375-38319 SQLite will never request a scratch buffer |
| 59333 | ** that is more than 6 times the database page size. */ |
| 59334 | assert( szScratch<=6*pBt->pageSize ); |
| 59335 | apCell = sqlite3ScratchMalloc( szScratch ); |
| 59336 | if( apCell==0 ){ |
| 59337 | rc = SQLITE_NOMEM; |
| 59338 | goto balance_cleanup; |
| 59339 | } |
| @@ -59406,12 +59461,12 @@ | |
| 59406 | assert( leafCorrection==4 ); |
| 59407 | if( szCell[nCell]<4 ){ |
| 59408 | /* Do not allow any cells smaller than 4 bytes. If a smaller cell |
| 59409 | ** does exist, pad it with 0x00 bytes. */ |
| 59410 | assert( szCell[nCell]==3 ); |
| 59411 | assert( apCell[nCell]==&pTemp[iSpace1-3] ); |
| 59412 | pTemp[iSpace1++] = 0x00; |
| 59413 | szCell[nCell] = 4; |
| 59414 | } |
| 59415 | } |
| 59416 | nCell++; |
| 59417 | } |
| @@ -60719,10 +60774,17 @@ | |
| 60719 | ** is read-only, the others are read/write. |
| 60720 | ** |
| 60721 | ** The schema layer numbers meta values differently. At the schema |
| 60722 | ** layer (and the SetCookie and ReadCookie opcodes) the number of |
| 60723 | ** free pages is not visible. So Cookie[0] is the same as Meta[1]. |
| 60724 | */ |
| 60725 | SQLITE_PRIVATE void sqlite3BtreeGetMeta(Btree *p, int idx, u32 *pMeta){ |
| 60726 | BtShared *pBt = p->pBt; |
| 60727 | |
| 60728 | sqlite3BtreeEnter(p); |
| @@ -60729,11 +60791,15 @@ | |
| 60729 | assert( p->inTrans>TRANS_NONE ); |
| 60730 | assert( SQLITE_OK==querySharedCacheTableLock(p, MASTER_ROOT, READ_LOCK) ); |
| 60731 | assert( pBt->pPage1 ); |
| 60732 | assert( idx>=0 && idx<=15 ); |
| 60733 | |
| 60734 | *pMeta = get4byte(&pBt->pPage1->aData[36 + idx*4]); |
| 60735 | |
| 60736 | /* If auto-vacuum is disabled in this build and this is an auto-vacuum |
| 60737 | ** database, mark the database as read-only. */ |
| 60738 | #ifdef SQLITE_OMIT_AUTOVACUUM |
| 60739 | if( idx==BTREE_LARGEST_ROOT_PAGE && *pMeta>0 ){ |
| @@ -60820,11 +60886,11 @@ | |
| 60820 | if( pPage->leaf ){ |
| 60821 | do { |
| 60822 | if( pCur->iPage==0 ){ |
| 60823 | /* All pages of the b-tree have been visited. Return successfully. */ |
| 60824 | *pnEntry = nEntry; |
| 60825 | return SQLITE_OK; |
| 60826 | } |
| 60827 | moveToParent(pCur); |
| 60828 | }while ( pCur->aiIdx[pCur->iPage]>=pCur->apPage[pCur->iPage]->nCell ); |
| 60829 | |
| 60830 | pCur->aiIdx[pCur->iPage]++; |
| @@ -61676,11 +61742,11 @@ | |
| 61676 | } |
| 61677 | |
| 61678 | /* |
| 61679 | ** Return the size of the header added to each page by this module. |
| 61680 | */ |
| 61681 | SQLITE_PRIVATE int sqlite3HeaderSizeBtree(void){ return sizeof(MemPage); } |
| 61682 | |
| 61683 | /************** End of btree.c ***********************************************/ |
| 61684 | /************** Begin file backup.c ******************************************/ |
| 61685 | /* |
| 61686 | ** 2009 January 28 |
| @@ -64440,36 +64506,39 @@ | |
| 64440 | ** |
| 64441 | ** assert( sqlite3VdbeAssertMayAbort(pParse->pVdbe, pParse->mayAbort) ); |
| 64442 | */ |
| 64443 | SQLITE_PRIVATE int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){ |
| 64444 | int hasAbort = 0; |
| 64445 | Op *pOp; |
| 64446 | VdbeOpIter sIter; |
| 64447 | memset(&sIter, 0, sizeof(sIter)); |
| 64448 | sIter.v = v; |
| 64449 | |
| 64450 | while( (pOp = opIterNext(&sIter))!=0 ){ |
| 64451 | int opcode = pOp->opcode; |
| 64452 | if( opcode==OP_Destroy || opcode==OP_VUpdate || opcode==OP_VRename |
| 64453 | #ifndef SQLITE_OMIT_FOREIGN_KEY |
| 64454 | || (opcode==OP_FkCounter && pOp->p1==0 && pOp->p2==1) |
| 64455 | #endif |
| 64456 | || ((opcode==OP_Halt || opcode==OP_HaltIfNull) |
| 64457 | && ((pOp->p1&0xff)==SQLITE_CONSTRAINT && pOp->p2==OE_Abort)) |
| 64458 | ){ |
| 64459 | hasAbort = 1; |
| 64460 | break; |
| 64461 | } |
| 64462 | } |
| 64463 | sqlite3DbFree(v->db, sIter.apSub); |
| 64464 | |
| 64465 | /* Return true if hasAbort==mayAbort. Or if a malloc failure occurred. |
| 64466 | ** If malloc failed, then the while() loop above may not have iterated |
| 64467 | ** through all opcodes and hasAbort may be set incorrectly. Return |
| 64468 | ** true for this case to prevent the assert() in the callers frame |
| 64469 | ** from failing. */ |
| 64470 | return ( v->db->mallocFailed || hasAbort==mayAbort ); |
| 64471 | } |
| 64472 | #endif /* SQLITE_DEBUG - the sqlite3AssertMayAbort() function */ |
| 64473 | |
| 64474 | /* |
| 64475 | ** Loop through the program looking for P2 values that are negative |
| @@ -68589,11 +68658,14 @@ | |
| 68589 | #ifndef SQLITE_OMIT_WAL |
| 68590 | int i; |
| 68591 | for(i=0; i<db->nDb; i++){ |
| 68592 | Btree *pBt = db->aDb[i].pBt; |
| 68593 | if( pBt ){ |
| 68594 | int nEntry = sqlite3PagerWalCallback(sqlite3BtreePager(pBt)); |
| 68595 | if( db->xWalCallback && nEntry>0 && rc==SQLITE_OK ){ |
| 68596 | rc = db->xWalCallback(db->pWalArg, db, db->aDb[i].zName, nEntry); |
| 68597 | } |
| 68598 | } |
| 68599 | } |
| @@ -68769,11 +68841,10 @@ | |
| 68769 | ** program counter to 0 to ensure that when the statement is |
| 68770 | ** finalized or reset the parser error message is available via |
| 68771 | ** sqlite3_errmsg() and sqlite3_errcode(). |
| 68772 | */ |
| 68773 | const char *zErr = (const char *)sqlite3_value_text(db->pErr); |
| 68774 | assert( zErr!=0 || db->mallocFailed ); |
| 68775 | sqlite3DbFree(db, v->zErrMsg); |
| 68776 | if( !db->mallocFailed ){ |
| 68777 | v->zErrMsg = sqlite3DbStrDup(db, zErr); |
| 68778 | v->rc = rc2; |
| 68779 | } else { |
| @@ -77131,11 +77202,11 @@ | |
| 77131 | /* |
| 77132 | ** Hard-coded maximum amount of data to accumulate in memory before flushing |
| 77133 | ** to a level 0 PMA. The purpose of this limit is to prevent various integer |
| 77134 | ** overflows. 512MiB. |
| 77135 | */ |
| 77136 | #define SQLITE_MAX_MXPMASIZE (1<<29) |
| 77137 | |
| 77138 | /* |
| 77139 | ** Private objects used by the sorter |
| 77140 | */ |
| 77141 | typedef struct MergeEngine MergeEngine; /* Merge PMAs together */ |
| @@ -77427,13 +77498,10 @@ | |
| 77427 | ** |
| 77428 | ** void *SRVAL(SorterRecord *p) { return (void*)&p[1]; } |
| 77429 | */ |
| 77430 | #define SRVAL(p) ((void*)((SorterRecord*)(p) + 1)) |
| 77431 | |
| 77432 | /* The minimum PMA size is set to this value multiplied by the database |
| 77433 | ** page size in bytes. */ |
| 77434 | #define SORTER_MIN_WORKING 10 |
| 77435 | |
| 77436 | /* Maximum number of PMAs that a single MergeEngine can merge */ |
| 77437 | #define SORTER_MAX_MERGE_COUNT 16 |
| 77438 | |
| 77439 | static int vdbeIncrSwap(IncrMerger*); |
| @@ -77828,14 +77896,15 @@ | |
| 77828 | SortSubtask *pTask = &pSorter->aTask[i]; |
| 77829 | pTask->pSorter = pSorter; |
| 77830 | } |
| 77831 | |
| 77832 | if( !sqlite3TempInMemory(db) ){ |
| 77833 | pSorter->mnPmaSize = SORTER_MIN_WORKING * pgsz; |
| 77834 | mxCache = db->aDb[0].pSchema->cache_size; |
| 77835 | if( mxCache<SORTER_MIN_WORKING ) mxCache = SORTER_MIN_WORKING; |
| 77836 | pSorter->mxPmaSize = MIN((i64)mxCache*pgsz, SQLITE_MAX_MXPMASIZE); |
| 77837 | |
| 77838 | /* EVIDENCE-OF: R-26747-61719 When the application provides any amount of |
| 77839 | ** scratch memory using SQLITE_CONFIG_SCRATCH, SQLite avoids unnecessary |
| 77840 | ** large heap allocations. |
| 77841 | */ |
| @@ -78109,16 +78178,16 @@ | |
| 78109 | ** Whether or not the file does end up memory mapped of course depends on |
| 78110 | ** the specific VFS implementation. |
| 78111 | */ |
| 78112 | static void vdbeSorterExtendFile(sqlite3 *db, sqlite3_file *pFd, i64 nByte){ |
| 78113 | if( nByte<=(i64)(db->nMaxSorterMmap) && pFd->pMethods->iVersion>=3 ){ |
| 78114 | int rc = sqlite3OsTruncate(pFd, nByte); |
| 78115 | if( rc==SQLITE_OK ){ |
| 78116 | void *p = 0; |
| 78117 | sqlite3OsFetch(pFd, 0, (int)nByte, &p); |
| 78118 | sqlite3OsUnfetch(pFd, 0, p); |
| 78119 | } |
| 78120 | } |
| 78121 | } |
| 78122 | #else |
| 78123 | # define vdbeSorterExtendFile(x,y,z) |
| 78124 | #endif |
| @@ -87296,11 +87365,11 @@ | |
| 87296 | |
| 87297 | p->iGet = -1; |
| 87298 | p->mxSample = mxSample; |
| 87299 | p->nPSample = (tRowcnt)(sqlite3_value_int64(argv[2])/(mxSample/3+1) + 1); |
| 87300 | p->current.anLt = &p->current.anEq[nColUp]; |
| 87301 | p->iPrn = nCol*0x689e962d ^ sqlite3_value_int(argv[2])*0xd0944565; |
| 87302 | |
| 87303 | /* Set up the Stat4Accum.a[] and aBest[] arrays */ |
| 87304 | p->a = (struct Stat4Sample*)&p->current.anLt[nColUp]; |
| 87305 | p->aBest = &p->a[mxSample]; |
| 87306 | pSpace = (u8*)(&p->a[mxSample+nCol]); |
| @@ -88889,17 +88958,19 @@ | |
| 88889 | }else if( aNew->pSchema->file_format && aNew->pSchema->enc!=ENC(db) ){ |
| 88890 | zErrDyn = sqlite3MPrintf(db, |
| 88891 | "attached databases must use the same text encoding as main database"); |
| 88892 | rc = SQLITE_ERROR; |
| 88893 | } |
| 88894 | pPager = sqlite3BtreePager(aNew->pBt); |
| 88895 | sqlite3PagerLockingMode(pPager, db->dfltLockMode); |
| 88896 | sqlite3BtreeSecureDelete(aNew->pBt, |
| 88897 | sqlite3BtreeSecureDelete(db->aDb[0].pBt,-1) ); |
| 88898 | #ifndef SQLITE_OMIT_PAGER_PRAGMAS |
| 88899 | sqlite3BtreeSetPagerFlags(aNew->pBt, 3 | (db->flags & PAGER_FLAGS_MASK)); |
| 88900 | #endif |
| 88901 | } |
| 88902 | aNew->safety_level = 3; |
| 88903 | aNew->zName = sqlite3DbStrDup(db, zName); |
| 88904 | if( rc==SQLITE_OK && aNew->zName==0 ){ |
| 88905 | rc = SQLITE_NOMEM; |
| @@ -90021,11 +90092,10 @@ | |
| 90021 | */ |
| 90022 | static void freeIndex(sqlite3 *db, Index *p){ |
| 90023 | #ifndef SQLITE_OMIT_ANALYZE |
| 90024 | sqlite3DeleteIndexSamples(db, p); |
| 90025 | #endif |
| 90026 | if( db==0 || db->pnBytesFreed==0 ) sqlite3KeyInfoUnref(p->pKeyInfo); |
| 90027 | sqlite3ExprDelete(db, p->pPartIdxWhere); |
| 90028 | sqlite3DbFree(db, p->zColAff); |
| 90029 | if( p->isResized ) sqlite3DbFree(db, p->azColl); |
| 90030 | #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 |
| 90031 | sqlite3_free(p->aiRowEst); |
| @@ -91300,10 +91370,23 @@ | |
| 91300 | if( pPk==0 ) return; |
| 91301 | pPk->idxType = SQLITE_IDXTYPE_PRIMARYKEY; |
| 91302 | pTab->iPKey = -1; |
| 91303 | }else{ |
| 91304 | pPk = sqlite3PrimaryKeyIndex(pTab); |
| 91305 | } |
| 91306 | pPk->isCovering = 1; |
| 91307 | assert( pPk!=0 ); |
| 91308 | nPk = pPk->nKeyCol; |
| 91309 | |
| @@ -93776,44 +93859,35 @@ | |
| 93776 | ** |
| 93777 | ** The caller should invoke sqlite3KeyInfoUnref() on the returned object |
| 93778 | ** when it has finished using it. |
| 93779 | */ |
| 93780 | SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoOfIndex(Parse *pParse, Index *pIdx){ |
| 93781 | if( pParse->nErr ) return 0; |
| 93782 | #ifndef SQLITE_OMIT_SHARED_CACHE |
| 93783 | if( pIdx->pKeyInfo && pIdx->pKeyInfo->db!=pParse->db ){ |
| 93784 | sqlite3KeyInfoUnref(pIdx->pKeyInfo); |
| 93785 | pIdx->pKeyInfo = 0; |
| 93786 | } |
| 93787 | #endif |
| 93788 | if( pIdx->pKeyInfo==0 ){ |
| 93789 | int i; |
| 93790 | int nCol = pIdx->nColumn; |
| 93791 | int nKey = pIdx->nKeyCol; |
| 93792 | KeyInfo *pKey; |
| 93793 | if( pIdx->uniqNotNull ){ |
| 93794 | pKey = sqlite3KeyInfoAlloc(pParse->db, nKey, nCol-nKey); |
| 93795 | }else{ |
| 93796 | pKey = sqlite3KeyInfoAlloc(pParse->db, nCol, 0); |
| 93797 | } |
| 93798 | if( pKey ){ |
| 93799 | assert( sqlite3KeyInfoIsWriteable(pKey) ); |
| 93800 | for(i=0; i<nCol; i++){ |
| 93801 | char *zColl = pIdx->azColl[i]; |
| 93802 | assert( zColl!=0 ); |
| 93803 | pKey->aColl[i] = strcmp(zColl,"BINARY")==0 ? 0 : |
| 93804 | sqlite3LocateCollSeq(pParse, zColl); |
| 93805 | pKey->aSortOrder[i] = pIdx->aSortOrder[i]; |
| 93806 | } |
| 93807 | if( pParse->nErr ){ |
| 93808 | sqlite3KeyInfoUnref(pKey); |
| 93809 | }else{ |
| 93810 | pIdx->pKeyInfo = pKey; |
| 93811 | } |
| 93812 | } |
| 93813 | } |
| 93814 | return sqlite3KeyInfoRef(pIdx->pKeyInfo); |
| 93815 | } |
| 93816 | |
| 93817 | #ifndef SQLITE_OMIT_CTE |
| 93818 | /* |
| 93819 | ** This routine is invoked once per CTE by the parser while parsing a |
| @@ -97430,11 +97504,11 @@ | |
| 97430 | assert( nIncr==1 ); |
| 97431 | sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_FOREIGNKEY, |
| 97432 | OE_Abort, 0, P4_STATIC, P5_ConstraintFK); |
| 97433 | }else{ |
| 97434 | if( nIncr>0 && pFKey->isDeferred==0 ){ |
| 97435 | sqlite3ParseToplevel(pParse)->mayAbort = 1; |
| 97436 | } |
| 97437 | sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr); |
| 97438 | } |
| 97439 | |
| 97440 | sqlite3VdbeResolveLabel(v, iOk); |
| @@ -97501,10 +97575,14 @@ | |
| 97501 | ** This function is called to generate code executed when a row is deleted |
| 97502 | ** from the parent table of foreign key constraint pFKey and, if pFKey is |
| 97503 | ** deferred, when a row is inserted into the same table. When generating |
| 97504 | ** code for an SQL UPDATE operation, this function may be called twice - |
| 97505 | ** once to "delete" the old row and once to "insert" the new row. |
| 97506 | ** |
| 97507 | ** The code generated by this function scans through the rows in the child |
| 97508 | ** table that correspond to the parent table row being deleted or inserted. |
| 97509 | ** For each child row found, one of the following actions is taken: |
| 97510 | ** |
| @@ -97618,17 +97696,13 @@ | |
| 97618 | sNameContext.pSrcList = pSrc; |
| 97619 | sNameContext.pParse = pParse; |
| 97620 | sqlite3ResolveExprNames(&sNameContext, pWhere); |
| 97621 | |
| 97622 | /* Create VDBE to loop through the entries in pSrc that match the WHERE |
| 97623 | ** clause. If the constraint is not deferred, throw an exception for |
| 97624 | ** each row found. Otherwise, for deferred constraints, increment the |
| 97625 | ** deferred constraint counter by nIncr for each row selected. */ |
| 97626 | pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0, 0, 0); |
| 97627 | if( nIncr>0 && pFKey->isDeferred==0 ){ |
| 97628 | sqlite3ParseToplevel(pParse)->mayAbort = 1; |
| 97629 | } |
| 97630 | sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr); |
| 97631 | if( pWInfo ){ |
| 97632 | sqlite3WhereEnd(pWInfo); |
| 97633 | } |
| 97634 | |
| @@ -97802,10 +97876,28 @@ | |
| 97802 | } |
| 97803 | } |
| 97804 | } |
| 97805 | return 0; |
| 97806 | } |
| 97807 | |
| 97808 | /* |
| 97809 | ** This function is called when inserting, deleting or updating a row of |
| 97810 | ** table pTab to generate VDBE code to perform foreign key constraint |
| 97811 | ** processing for the operation. |
| @@ -97855,11 +97947,11 @@ | |
| 97855 | Index *pIdx = 0; /* Index on key columns in pTo */ |
| 97856 | int *aiFree = 0; |
| 97857 | int *aiCol; |
| 97858 | int iCol; |
| 97859 | int i; |
| 97860 | int isIgnore = 0; |
| 97861 | |
| 97862 | if( aChange |
| 97863 | && sqlite3_stricmp(pTab->zName, pFKey->zTo)!=0 |
| 97864 | && fkChildIsModified(pTab, pFKey, aChange, bChngRowid)==0 |
| 97865 | ){ |
| @@ -97914,11 +98006,11 @@ | |
| 97914 | ** values read from the parent table are NULL. */ |
| 97915 | if( db->xAuth ){ |
| 97916 | int rcauth; |
| 97917 | char *zCol = pTo->aCol[pIdx ? pIdx->aiColumn[i] : pTo->iPKey].zName; |
| 97918 | rcauth = sqlite3AuthReadCol(pParse, pTo->zName, zCol, iDb); |
| 97919 | isIgnore = (rcauth==SQLITE_IGNORE); |
| 97920 | } |
| 97921 | #endif |
| 97922 | } |
| 97923 | |
| 97924 | /* Take a shared-cache advisory read-lock on the parent table. Allocate |
| @@ -97929,16 +98021,22 @@ | |
| 97929 | |
| 97930 | if( regOld!=0 ){ |
| 97931 | /* A row is being removed from the child table. Search for the parent. |
| 97932 | ** If the parent does not exist, removing the child row resolves an |
| 97933 | ** outstanding foreign key constraint violation. */ |
| 97934 | fkLookupParent(pParse, iDb, pTo, pIdx, pFKey, aiCol, regOld, -1,isIgnore); |
| 97935 | } |
| 97936 | if( regNew!=0 ){ |
| 97937 | /* A row is being added to the child table. If a parent row cannot |
| 97938 | ** be found, adding the child row has violated the FK constraint. */ |
| 97939 | fkLookupParent(pParse, iDb, pTo, pIdx, pFKey, aiCol, regNew, +1,isIgnore); |
| 97940 | } |
| 97941 | |
| 97942 | sqlite3DbFree(db, aiFree); |
| 97943 | } |
| 97944 | |
| @@ -97955,12 +98053,12 @@ | |
| 97955 | |
| 97956 | if( !pFKey->isDeferred && !(db->flags & SQLITE_DeferFKs) |
| 97957 | && !pParse->pToplevel && !pParse->isMultiWrite |
| 97958 | ){ |
| 97959 | assert( regOld==0 && regNew!=0 ); |
| 97960 | /* Inserting a single row into a parent table cannot cause an immediate |
| 97961 | ** foreign key violation. So do nothing in this case. */ |
| 97962 | continue; |
| 97963 | } |
| 97964 | |
| 97965 | if( sqlite3FkLocateIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ){ |
| 97966 | if( !isIgnoreErrors || db->mallocFailed ) return; |
| @@ -97980,17 +98078,32 @@ | |
| 97980 | |
| 97981 | if( regNew!=0 ){ |
| 97982 | fkScanChildren(pParse, pSrc, pTab, pIdx, pFKey, aiCol, regNew, -1); |
| 97983 | } |
| 97984 | if( regOld!=0 ){ |
| 97985 | /* If there is a RESTRICT action configured for the current operation |
| 97986 | ** on the parent table of this FK, then throw an exception |
| 97987 | ** immediately if the FK constraint is violated, even if this is a |
| 97988 | ** deferred trigger. That's what RESTRICT means. To defer checking |
| 97989 | ** the constraint, the FK should specify NO ACTION (represented |
| 97990 | ** using OE_None). NO ACTION is the default. */ |
| 97991 | fkScanChildren(pParse, pSrc, pTab, pIdx, pFKey, aiCol, regOld, 1); |
| 97992 | } |
| 97993 | pItem->zName = 0; |
| 97994 | sqlite3SrcListDelete(db, pSrc); |
| 97995 | } |
| 97996 | sqlite3DbFree(db, aiCol); |
| @@ -101080,11 +101193,10 @@ | |
| 101080 | # define sqlite3_column_database_name16 0 |
| 101081 | # define sqlite3_column_table_name 0 |
| 101082 | # define sqlite3_column_table_name16 0 |
| 101083 | # define sqlite3_column_origin_name 0 |
| 101084 | # define sqlite3_column_origin_name16 0 |
| 101085 | # define sqlite3_table_column_metadata 0 |
| 101086 | #endif |
| 101087 | |
| 101088 | #ifdef SQLITE_OMIT_AUTHORIZATION |
| 101089 | # define sqlite3_set_authorizer 0 |
| 101090 | #endif |
| @@ -101890,10 +102002,11 @@ | |
| 101890 | #define PragTyp_KEY 38 |
| 101891 | #define PragTyp_REKEY 39 |
| 101892 | #define PragTyp_LOCK_STATUS 40 |
| 101893 | #define PragTyp_PARSER_TRACE 41 |
| 101894 | #define PragFlag_NeedSchema 0x01 |
| 101895 | static const struct sPragmaNames { |
| 101896 | const char *const zName; /* Name of pragma */ |
| 101897 | u8 ePragTyp; /* PragTyp_XXX value */ |
| 101898 | u8 mPragFlag; /* Zero or more PragFlag_XXX values */ |
| 101899 | u32 iArg; /* Extra argument */ |
| @@ -101906,11 +102019,11 @@ | |
| 101906 | #endif |
| 101907 | #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) |
| 101908 | { /* zName: */ "application_id", |
| 101909 | /* ePragTyp: */ PragTyp_HEADER_VALUE, |
| 101910 | /* ePragFlag: */ 0, |
| 101911 | /* iArg: */ 0 }, |
| 101912 | #endif |
| 101913 | #if !defined(SQLITE_OMIT_AUTOVACUUM) |
| 101914 | { /* zName: */ "auto_vacuum", |
| 101915 | /* ePragTyp: */ PragTyp_AUTO_VACUUM, |
| 101916 | /* ePragFlag: */ PragFlag_NeedSchema, |
| @@ -101972,10 +102085,16 @@ | |
| 101972 | { /* zName: */ "data_store_directory", |
| 101973 | /* ePragTyp: */ PragTyp_DATA_STORE_DIRECTORY, |
| 101974 | /* ePragFlag: */ 0, |
| 101975 | /* iArg: */ 0 }, |
| 101976 | #endif |
| 101977 | #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) |
| 101978 | { /* zName: */ "database_list", |
| 101979 | /* ePragTyp: */ PragTyp_DATABASE_LIST, |
| 101980 | /* ePragFlag: */ PragFlag_NeedSchema, |
| 101981 | /* iArg: */ 0 }, |
| @@ -102027,12 +102146,12 @@ | |
| 102027 | #endif |
| 102028 | #endif |
| 102029 | #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) |
| 102030 | { /* zName: */ "freelist_count", |
| 102031 | /* ePragTyp: */ PragTyp_HEADER_VALUE, |
| 102032 | /* ePragFlag: */ 0, |
| 102033 | /* iArg: */ 0 }, |
| 102034 | #endif |
| 102035 | #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) |
| 102036 | { /* zName: */ "full_column_names", |
| 102037 | /* ePragTyp: */ PragTyp_FLAG, |
| 102038 | /* ePragFlag: */ 0, |
| @@ -102180,11 +102299,11 @@ | |
| 102180 | #endif |
| 102181 | #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) |
| 102182 | { /* zName: */ "schema_version", |
| 102183 | /* ePragTyp: */ PragTyp_HEADER_VALUE, |
| 102184 | /* ePragFlag: */ 0, |
| 102185 | /* iArg: */ 0 }, |
| 102186 | #endif |
| 102187 | #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) |
| 102188 | { /* zName: */ "secure_delete", |
| 102189 | /* ePragTyp: */ PragTyp_SECURE_DELETE, |
| 102190 | /* ePragFlag: */ 0, |
| @@ -102246,11 +102365,11 @@ | |
| 102246 | /* iArg: */ 0 }, |
| 102247 | #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) |
| 102248 | { /* zName: */ "user_version", |
| 102249 | /* ePragTyp: */ PragTyp_HEADER_VALUE, |
| 102250 | /* ePragFlag: */ 0, |
| 102251 | /* iArg: */ 0 }, |
| 102252 | #endif |
| 102253 | #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) |
| 102254 | #if defined(SQLITE_DEBUG) |
| 102255 | { /* zName: */ "vdbe_addoptrace", |
| 102256 | /* ePragTyp: */ PragTyp_FLAG, |
| @@ -102289,11 +102408,11 @@ | |
| 102289 | /* ePragTyp: */ PragTyp_FLAG, |
| 102290 | /* ePragFlag: */ 0, |
| 102291 | /* iArg: */ SQLITE_WriteSchema|SQLITE_RecoveryMode }, |
| 102292 | #endif |
| 102293 | }; |
| 102294 | /* Number of pragmas: 57 on by default, 70 total. */ |
| 102295 | /* End of the automatically generated pragma table. |
| 102296 | ***************************************************************************/ |
| 102297 | |
| 102298 | /* |
| 102299 | ** Interpret the given string as a safety level. Return 0 for OFF, |
| @@ -103899,11 +104018,12 @@ | |
| 103899 | !(DbHasProperty(db, 0, DB_SchemaLoaded)) || |
| 103900 | DbHasProperty(db, 0, DB_Empty) |
| 103901 | ){ |
| 103902 | for(pEnc=&encnames[0]; pEnc->zName; pEnc++){ |
| 103903 | if( 0==sqlite3StrICmp(zRight, pEnc->zName) ){ |
| 103904 | ENC(pParse->db) = pEnc->enc ? pEnc->enc : SQLITE_UTF16NATIVE; |
| 103905 | break; |
| 103906 | } |
| 103907 | } |
| 103908 | if( !pEnc->zName ){ |
| 103909 | sqlite3ErrorMsg(pParse, "unsupported encoding: %s", zRight); |
| @@ -103944,28 +104064,13 @@ | |
| 103944 | ** |
| 103945 | ** The user-version is not used internally by SQLite. It may be used by |
| 103946 | ** applications for any purpose. |
| 103947 | */ |
| 103948 | case PragTyp_HEADER_VALUE: { |
| 103949 | int iCookie; /* Cookie index. 1 for schema-cookie, 6 for user-cookie. */ |
| 103950 | sqlite3VdbeUsesBtree(v, iDb); |
| 103951 | switch( zLeft[0] ){ |
| 103952 | case 'a': case 'A': |
| 103953 | iCookie = BTREE_APPLICATION_ID; |
| 103954 | break; |
| 103955 | case 'f': case 'F': |
| 103956 | iCookie = BTREE_FREE_PAGE_COUNT; |
| 103957 | break; |
| 103958 | case 's': case 'S': |
| 103959 | iCookie = BTREE_SCHEMA_VERSION; |
| 103960 | break; |
| 103961 | default: |
| 103962 | iCookie = BTREE_USER_VERSION; |
| 103963 | break; |
| 103964 | } |
| 103965 | |
| 103966 | if( zRight && iCookie!=BTREE_FREE_PAGE_COUNT ){ |
| 103967 | /* Write the specified cookie value */ |
| 103968 | static const VdbeOpList setCookie[] = { |
| 103969 | { OP_Transaction, 0, 1, 0}, /* 0 */ |
| 103970 | { OP_Integer, 0, 1, 0}, /* 1 */ |
| 103971 | { OP_SetCookie, 0, 0, 1}, /* 2 */ |
| @@ -104607,13 +104712,15 @@ | |
| 104607 | SQLITE_PRIVATE int sqlite3Init(sqlite3 *db, char **pzErrMsg){ |
| 104608 | int i, rc; |
| 104609 | int commit_internal = !(db->flags&SQLITE_InternChanges); |
| 104610 | |
| 104611 | assert( sqlite3_mutex_held(db->mutex) ); |
| 104612 | assert( db->init.busy==0 ); |
| 104613 | rc = SQLITE_OK; |
| 104614 | db->init.busy = 1; |
| 104615 | for(i=0; rc==SQLITE_OK && i<db->nDb; i++){ |
| 104616 | if( DbHasProperty(db, i, DB_SchemaLoaded) || i==1 ) continue; |
| 104617 | rc = sqlite3InitOne(db, i, pzErrMsg); |
| 104618 | if( rc ){ |
| 104619 | sqlite3ResetOneSchema(db, i); |
| @@ -110751,11 +110858,11 @@ | |
| 110751 | ){ |
| 110752 | int rc; |
| 110753 | TabResult res; |
| 110754 | |
| 110755 | #ifdef SQLITE_ENABLE_API_ARMOR |
| 110756 | if( pazResult==0 ) return SQLITE_MISUSE_BKPT; |
| 110757 | #endif |
| 110758 | *pazResult = 0; |
| 110759 | if( pnColumn ) *pnColumn = 0; |
| 110760 | if( pnRow ) *pnRow = 0; |
| 110761 | if( pzErrMsg ) *pzErrMsg = 0; |
| @@ -118621,11 +118728,10 @@ | |
| 118621 | sqlite3_free(p->u.vtab.idxStr); |
| 118622 | p->u.vtab.needFree = 0; |
| 118623 | p->u.vtab.idxStr = 0; |
| 118624 | }else if( (p->wsFlags & WHERE_AUTO_INDEX)!=0 && p->u.btree.pIndex!=0 ){ |
| 118625 | sqlite3DbFree(db, p->u.btree.pIndex->zColAff); |
| 118626 | sqlite3KeyInfoUnref(p->u.btree.pIndex->pKeyInfo); |
| 118627 | sqlite3DbFree(db, p->u.btree.pIndex); |
| 118628 | p->u.btree.pIndex = 0; |
| 118629 | } |
| 118630 | } |
| 118631 | } |
| @@ -125628,10 +125734,13 @@ | |
| 125628 | u8 enableLookaside; /* Saved value of db->lookaside.bEnabled */ |
| 125629 | sqlite3 *db = pParse->db; /* The database connection */ |
| 125630 | int mxSqlLen; /* Max length of an SQL string */ |
| 125631 | |
| 125632 | |
| 125633 | mxSqlLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH]; |
| 125634 | if( db->nVdbeActive==0 ){ |
| 125635 | db->u1.isInterrupted = 0; |
| 125636 | } |
| 125637 | pParse->rc = SQLITE_OK; |
| @@ -125866,17 +125975,10 @@ | |
| 125866 | */ |
| 125867 | SQLITE_API int sqlite3_complete(const char *zSql){ |
| 125868 | u8 state = 0; /* Current state, using numbers defined in header comment */ |
| 125869 | u8 token; /* Value of the next token */ |
| 125870 | |
| 125871 | #ifdef SQLITE_ENABLE_API_ARMOR |
| 125872 | if( zSql==0 ){ |
| 125873 | (void)SQLITE_MISUSE_BKPT; |
| 125874 | return 0; |
| 125875 | } |
| 125876 | #endif |
| 125877 | |
| 125878 | #ifndef SQLITE_OMIT_TRIGGER |
| 125879 | /* A complex statement machine used to detect the end of a CREATE TRIGGER |
| 125880 | ** statement. This is the normal case. |
| 125881 | */ |
| 125882 | static const u8 trans[8][8] = { |
| @@ -125901,10 +126003,17 @@ | |
| 125901 | /* 0 INVALID: */ { 1, 0, 2, }, |
| 125902 | /* 1 START: */ { 1, 1, 2, }, |
| 125903 | /* 2 NORMAL: */ { 1, 2, 2, }, |
| 125904 | }; |
| 125905 | #endif /* SQLITE_OMIT_TRIGGER */ |
| 125906 | |
| 125907 | while( *zSql ){ |
| 125908 | switch( *zSql ){ |
| 125909 | case ';': { /* A semicolon */ |
| 125910 | token = tkSEMI; |
| @@ -126203,11 +126312,11 @@ | |
| 126203 | ** If the following function pointer is not NULL and if |
| 126204 | ** SQLITE_ENABLE_IOTRACE is enabled, then messages describing |
| 126205 | ** I/O active are written using this function. These messages |
| 126206 | ** are intended for debugging activity only. |
| 126207 | */ |
| 126208 | SQLITE_PRIVATE void (*sqlite3IoTrace)(const char*, ...) = 0; |
| 126209 | #endif |
| 126210 | |
| 126211 | /* |
| 126212 | ** If the following global variable points to a string which is the |
| 126213 | ** name of a directory, then that directory will be used to store |
| @@ -126412,10 +126521,17 @@ | |
| 126412 | ** routine is not threadsafe. But it is safe to invoke this routine |
| 126413 | ** on when SQLite is already shut down. If SQLite is already shut down |
| 126414 | ** when this routine is invoked, then this routine is a harmless no-op. |
| 126415 | */ |
| 126416 | SQLITE_API int sqlite3_shutdown(void){ |
| 126417 | if( sqlite3GlobalConfig.isInit ){ |
| 126418 | #ifdef SQLITE_EXTRA_SHUTDOWN |
| 126419 | void SQLITE_EXTRA_SHUTDOWN(void); |
| 126420 | SQLITE_EXTRA_SHUTDOWN(); |
| 126421 | #endif |
| @@ -126727,10 +126843,15 @@ | |
| 126727 | ** heap. */ |
| 126728 | sqlite3GlobalConfig.nHeap = va_arg(ap, int); |
| 126729 | break; |
| 126730 | } |
| 126731 | #endif |
| 126732 | |
| 126733 | default: { |
| 126734 | rc = SQLITE_ERROR; |
| 126735 | break; |
| 126736 | } |
| @@ -127173,18 +127294,10 @@ | |
| 127173 | |
| 127174 | /* Close all database connections */ |
| 127175 | for(j=0; j<db->nDb; j++){ |
| 127176 | struct Db *pDb = &db->aDb[j]; |
| 127177 | if( pDb->pBt ){ |
| 127178 | if( pDb->pSchema ){ |
| 127179 | /* Must clear the KeyInfo cache. See ticket [e4a18565a36884b00edf] */ |
| 127180 | for(i=sqliteHashFirst(&pDb->pSchema->idxHash); i; i=sqliteHashNext(i)){ |
| 127181 | Index *pIdx = sqliteHashData(i); |
| 127182 | sqlite3KeyInfoUnref(pIdx->pKeyInfo); |
| 127183 | pIdx->pKeyInfo = 0; |
| 127184 | } |
| 127185 | } |
| 127186 | sqlite3BtreeClose(pDb->pBt); |
| 127187 | pDb->pBt = 0; |
| 127188 | if( j!=1 ){ |
| 127189 | pDb->pSchema = 0; |
| 127190 | } |
| @@ -128308,36 +128421,10 @@ | |
| 128308 | */ |
| 128309 | SQLITE_API const char *sqlite3_errstr(int rc){ |
| 128310 | return sqlite3ErrStr(rc); |
| 128311 | } |
| 128312 | |
| 128313 | /* |
| 128314 | ** Invalidate all cached KeyInfo objects for database connection "db" |
| 128315 | */ |
| 128316 | static void invalidateCachedKeyInfo(sqlite3 *db){ |
| 128317 | Db *pDb; /* A single database */ |
| 128318 | int iDb; /* The database index number */ |
| 128319 | HashElem *k; /* For looping over tables in pDb */ |
| 128320 | Table *pTab; /* A table in the database */ |
| 128321 | Index *pIdx; /* Each index */ |
| 128322 | |
| 128323 | for(iDb=0, pDb=db->aDb; iDb<db->nDb; iDb++, pDb++){ |
| 128324 | if( pDb->pBt==0 ) continue; |
| 128325 | sqlite3BtreeEnter(pDb->pBt); |
| 128326 | for(k=sqliteHashFirst(&pDb->pSchema->tblHash); k; k=sqliteHashNext(k)){ |
| 128327 | pTab = (Table*)sqliteHashData(k); |
| 128328 | for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ |
| 128329 | if( pIdx->pKeyInfo && pIdx->pKeyInfo->db==db ){ |
| 128330 | sqlite3KeyInfoUnref(pIdx->pKeyInfo); |
| 128331 | pIdx->pKeyInfo = 0; |
| 128332 | } |
| 128333 | } |
| 128334 | } |
| 128335 | sqlite3BtreeLeave(pDb->pBt); |
| 128336 | } |
| 128337 | } |
| 128338 | |
| 128339 | /* |
| 128340 | ** Create a new collating function for database "db". The name is zName |
| 128341 | ** and the encoding is enc. |
| 128342 | */ |
| 128343 | static int createCollation( |
| @@ -128377,11 +128464,10 @@ | |
| 128377 | sqlite3ErrorWithMsg(db, SQLITE_BUSY, |
| 128378 | "unable to delete/modify collation sequence due to active statements"); |
| 128379 | return SQLITE_BUSY; |
| 128380 | } |
| 128381 | sqlite3ExpirePreparedStatements(db); |
| 128382 | invalidateCachedKeyInfo(db); |
| 128383 | |
| 128384 | /* If collation sequence pColl was created directly by a call to |
| 128385 | ** sqlite3_create_collation, and not generated by synthCollSeq(), |
| 128386 | ** then any copies made by synthCollSeq() need to be invalidated. |
| 128387 | ** Also, collation destructor - CollSeq.xDel() - function may need |
| @@ -128882,10 +128968,13 @@ | |
| 128882 | | SQLITE_RecTriggers |
| 128883 | #endif |
| 128884 | #if defined(SQLITE_DEFAULT_FOREIGN_KEYS) && SQLITE_DEFAULT_FOREIGN_KEYS |
| 128885 | | SQLITE_ForeignKeys |
| 128886 | #endif |
| 128887 | ; |
| 128888 | sqlite3HashInit(&db->aCollSeq); |
| 128889 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| 128890 | sqlite3HashInit(&db->aModule); |
| 128891 | #endif |
| @@ -128929,11 +129018,14 @@ | |
| 128929 | rc = SQLITE_NOMEM; |
| 128930 | } |
| 128931 | sqlite3Error(db, rc); |
| 128932 | goto opendb_out; |
| 128933 | } |
| 128934 | db->aDb[0].pSchema = sqlite3SchemaGet(db, db->aDb[0].pBt); |
| 128935 | db->aDb[1].pSchema = sqlite3SchemaGet(db, 0); |
| 128936 | |
| 128937 | /* The default safety_level for the main database is 'full'; for the temp |
| 128938 | ** database it is 'NONE'. This matches the pager layer defaults. |
| 128939 | */ |
| @@ -129087,11 +129179,11 @@ | |
| 129087 | if( zFilename8 ){ |
| 129088 | rc = openDatabase(zFilename8, ppDb, |
| 129089 | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0); |
| 129090 | assert( *ppDb || rc==SQLITE_NOMEM ); |
| 129091 | if( rc==SQLITE_OK && !DbHasProperty(*ppDb, 0, DB_SchemaLoaded) ){ |
| 129092 | ENC(*ppDb) = SQLITE_UTF16NATIVE; |
| 129093 | } |
| 129094 | }else{ |
| 129095 | rc = SQLITE_NOMEM; |
| 129096 | } |
| 129097 | sqlite3ValueFree(pVal); |
| @@ -129283,11 +129375,10 @@ | |
| 129283 | |
| 129284 | /* |
| 129285 | ** Return meta information about a specific column of a database table. |
| 129286 | ** See comment in sqlite3.h (sqlite.h.in) for details. |
| 129287 | */ |
| 129288 | #ifdef SQLITE_ENABLE_COLUMN_METADATA |
| 129289 | SQLITE_API int sqlite3_table_column_metadata( |
| 129290 | sqlite3 *db, /* Connection handle */ |
| 129291 | const char *zDbName, /* Database name or NULL */ |
| 129292 | const char *zTableName, /* Table name */ |
| 129293 | const char *zColumnName, /* Column name */ |
| @@ -129323,25 +129414,27 @@ | |
| 129323 | pTab = 0; |
| 129324 | goto error_out; |
| 129325 | } |
| 129326 | |
| 129327 | /* Find the column for which info is requested */ |
| 129328 | if( sqlite3IsRowid(zColumnName) ){ |
| 129329 | iCol = pTab->iPKey; |
| 129330 | if( iCol>=0 ){ |
| 129331 | pCol = &pTab->aCol[iCol]; |
| 129332 | } |
| 129333 | }else{ |
| 129334 | for(iCol=0; iCol<pTab->nCol; iCol++){ |
| 129335 | pCol = &pTab->aCol[iCol]; |
| 129336 | if( 0==sqlite3StrICmp(pCol->zName, zColumnName) ){ |
| 129337 | break; |
| 129338 | } |
| 129339 | } |
| 129340 | if( iCol==pTab->nCol ){ |
| 129341 | pTab = 0; |
| 129342 | goto error_out; |
| 129343 | } |
| 129344 | } |
| 129345 | |
| 129346 | /* The following block stores the meta information that will be returned |
| 129347 | ** to the caller in local variables zDataType, zCollSeq, notnull, primarykey |
| @@ -129390,11 +129483,10 @@ | |
| 129390 | sqlite3DbFree(db, zErrMsg); |
| 129391 | rc = sqlite3ApiExit(db, rc); |
| 129392 | sqlite3_mutex_leave(db->mutex); |
| 129393 | return rc; |
| 129394 | } |
| 129395 | #endif |
| 129396 | |
| 129397 | /* |
| 129398 | ** Sleep for a little while. Return the amount of time slept. |
| 129399 | */ |
| 129400 | SQLITE_API int sqlite3_sleep(int ms){ |
| @@ -129829,32 +129921,34 @@ | |
| 129829 | /* |
| 129830 | ** Return the filename of the database associated with a database |
| 129831 | ** connection. |
| 129832 | */ |
| 129833 | SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName){ |
| 129834 | #ifdef SQLITE_ENABLE_API_ARMOR |
| 129835 | if( !sqlite3SafetyCheckOk(db) ){ |
| 129836 | (void)SQLITE_MISUSE_BKPT; |
| 129837 | return 0; |
| 129838 | } |
| 129839 | #endif |
| 129840 | Btree *pBt = sqlite3DbNameToBtree(db, zDbName); |
| 129841 | return pBt ? sqlite3BtreeGetFilename(pBt) : 0; |
| 129842 | } |
| 129843 | |
| 129844 | /* |
| 129845 | ** Return 1 if database is read-only or 0 if read/write. Return -1 if |
| 129846 | ** no such database exists. |
| 129847 | */ |
| 129848 | SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName){ |
| 129849 | #ifdef SQLITE_ENABLE_API_ARMOR |
| 129850 | if( !sqlite3SafetyCheckOk(db) ){ |
| 129851 | (void)SQLITE_MISUSE_BKPT; |
| 129852 | return -1; |
| 129853 | } |
| 129854 | #endif |
| 129855 | Btree *pBt = sqlite3DbNameToBtree(db, zDbName); |
| 129856 | return pBt ? sqlite3BtreeIsReadonly(pBt) : -1; |
| 129857 | } |
| 129858 | |
| 129859 | /************** End of main.c ************************************************/ |
| 129860 | /************** Begin file notify.c ******************************************/ |
| @@ -150061,11 +150155,11 @@ | |
| 150061 | } |
| 150062 | i = pCur->nPoint++; |
| 150063 | pNew = pCur->aPoint + i; |
| 150064 | pNew->rScore = rScore; |
| 150065 | pNew->iLevel = iLevel; |
| 150066 | assert( iLevel>=0 && iLevel<=RTREE_MAX_DEPTH ); |
| 150067 | while( i>0 ){ |
| 150068 | RtreeSearchPoint *pParent; |
| 150069 | j = (i-1)/2; |
| 150070 | pParent = pCur->aPoint + j; |
| 150071 | if( rtreeSearchPointCompare(pNew, pParent)>=0 ) break; |
| 150072 |
| --- src/sqlite3.c | |
| +++ src/sqlite3.c | |
| @@ -231,11 +231,11 @@ | |
| 231 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 232 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 233 | */ |
| 234 | #define SQLITE_VERSION "3.8.8" |
| 235 | #define SQLITE_VERSION_NUMBER 3008008 |
| 236 | #define SQLITE_SOURCE_ID "2015-01-03 18:59:17 23d4c07eb81db5a5c6beb56b5820f0b6501f1fb6" |
| 237 | |
| 238 | /* |
| 239 | ** CAPI3REF: Run-Time Library Version Numbers |
| 240 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 241 | ** |
| @@ -323,11 +323,11 @@ | |
| 323 | ** This interface only reports on the compile-time mutex setting |
| 324 | ** of the [SQLITE_THREADSAFE] flag. If SQLite is compiled with |
| 325 | ** SQLITE_THREADSAFE=1 or =2 then mutexes are enabled by default but |
| 326 | ** can be fully or partially disabled using a call to [sqlite3_config()] |
| 327 | ** with the verbs [SQLITE_CONFIG_SINGLETHREAD], [SQLITE_CONFIG_MULTITHREAD], |
| 328 | ** or [SQLITE_CONFIG_SERIALIZED]. ^(The return value of the |
| 329 | ** sqlite3_threadsafe() function shows only the compile-time setting of |
| 330 | ** thread safety, not any run-time changes to that setting made by |
| 331 | ** sqlite3_config(). In other words, the return value from sqlite3_threadsafe() |
| 332 | ** is unchanged by calls to sqlite3_config().)^ |
| 333 | ** |
| @@ -1692,11 +1692,11 @@ | |
| 1692 | ** configuration option. |
| 1693 | ** ^There are three arguments to SQLITE_CONFIG_PAGECACHE: A pointer to |
| 1694 | ** 8-byte aligned |
| 1695 | ** memory, the size of each page buffer (sz), and the number of pages (N). |
| 1696 | ** The sz argument should be the size of the largest database page |
| 1697 | ** (a power of two between 512 and 65536) plus some extra bytes for each |
| 1698 | ** page header. ^The number of extra bytes needed by the page header |
| 1699 | ** can be determined using the [SQLITE_CONFIG_PCACHE_HDRSZ] option |
| 1700 | ** to [sqlite3_config()]. |
| 1701 | ** ^It is harmless, apart from the wasted memory, |
| 1702 | ** for the sz parameter to be larger than necessary. The first |
| @@ -1872,10 +1872,21 @@ | |
| 1872 | ** <dd>^The SQLITE_CONFIG_PCACHE_HDRSZ option takes a single parameter which |
| 1873 | ** is a pointer to an integer and writes into that integer the number of extra |
| 1874 | ** bytes per page required for each page in [SQLITE_CONFIG_PAGECACHE]. |
| 1875 | ** The amount of extra space required can change depending on the compiler, |
| 1876 | ** target platform, and SQLite version. |
| 1877 | ** |
| 1878 | ** [[SQLITE_CONFIG_PMASZ]] |
| 1879 | ** <dt>SQLITE_CONFIG_PMASZ |
| 1880 | ** <dd>^The SQLITE_CONFIG_PMASZ option takes a single parameter which |
| 1881 | ** is an unsigned integer and sets the "Minimum PMA Size" for the multithreaded |
| 1882 | ** sorter to that integer. The default minimum PMA Size is set by the |
| 1883 | ** [SQLITE_SORTER_PMASZ] compile-time option. New threads are launched |
| 1884 | ** to help with sort operations when multithreaded sorting |
| 1885 | ** is enabled (using the [PRAGMA threads] command) and the amount of content |
| 1886 | ** to be sorted exceeds the page size times the minimum of the |
| 1887 | ** [PRAGMA cache_size] setting and this value. |
| 1888 | ** </dl> |
| 1889 | */ |
| 1890 | #define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */ |
| 1891 | #define SQLITE_CONFIG_MULTITHREAD 2 /* nil */ |
| 1892 | #define SQLITE_CONFIG_SERIALIZED 3 /* nil */ |
| @@ -1898,10 +1909,11 @@ | |
| 1909 | #define SQLITE_CONFIG_COVERING_INDEX_SCAN 20 /* int */ |
| 1910 | #define SQLITE_CONFIG_SQLLOG 21 /* xSqllog, void* */ |
| 1911 | #define SQLITE_CONFIG_MMAP_SIZE 22 /* sqlite3_int64, sqlite3_int64 */ |
| 1912 | #define SQLITE_CONFIG_WIN32_HEAPSIZE 23 /* int nByte */ |
| 1913 | #define SQLITE_CONFIG_PCACHE_HDRSZ 24 /* int *psz */ |
| 1914 | #define SQLITE_CONFIG_PMASZ 25 /* unsigned int szPma */ |
| 1915 | |
| 1916 | /* |
| 1917 | ** CAPI3REF: Database Connection Configuration Options |
| 1918 | ** |
| 1919 | ** These constants are the available integer configuration options that |
| @@ -5279,24 +5291,31 @@ | |
| 5291 | |
| 5292 | |
| 5293 | /* |
| 5294 | ** CAPI3REF: Extract Metadata About A Column Of A Table |
| 5295 | ** |
| 5296 | ** ^(The sqlite3_table_column_metadata(X,D,T,C,....) routine returns |
| 5297 | ** information about column C of table T in database D |
| 5298 | ** on [database connection] X.)^ ^The sqlite3_table_column_metadata() |
| 5299 | ** interface returns SQLITE_OK and fills in the non-NULL pointers in |
| 5300 | ** the final five arguments with appropriate values if the specified |
| 5301 | ** column exists. ^The sqlite3_table_column_metadata() interface returns |
| 5302 | ** SQLITE_ERROR and if the specified column does not exist. |
| 5303 | ** ^If the column-name parameter to sqlite3_table_column_metadata() is a |
| 5304 | ** NULL pointer, then this routine simply checks for the existance of the |
| 5305 | ** table and returns SQLITE_OK if the table exists and SQLITE_ERROR if it |
| 5306 | ** does not. |
| 5307 | ** |
| 5308 | ** ^The column is identified by the second, third and fourth parameters to |
| 5309 | ** this function. ^(The second parameter is either the name of the database |
| 5310 | ** (i.e. "main", "temp", or an attached database) containing the specified |
| 5311 | ** table or NULL.)^ ^If it is NULL, then all attached databases are searched |
| 5312 | ** for the table using the same algorithm used by the database engine to |
| 5313 | ** resolve unqualified table references. |
| 5314 | ** |
| 5315 | ** ^The third and fourth parameters to this function are the table and column |
| 5316 | ** name of the desired column, respectively. |
| 5317 | ** |
| 5318 | ** ^Metadata is returned by writing to the memory locations passed as the 5th |
| 5319 | ** and subsequent parameters to this function. ^Any of these arguments may be |
| 5320 | ** NULL, in which case the corresponding element of metadata is omitted. |
| 5321 | ** |
| @@ -5311,36 +5330,33 @@ | |
| 5330 | ** <tr><td> 9th <td> int <td> True if column is [AUTOINCREMENT] |
| 5331 | ** </table> |
| 5332 | ** </blockquote>)^ |
| 5333 | ** |
| 5334 | ** ^The memory pointed to by the character pointers returned for the |
| 5335 | ** declaration type and collation sequence is valid until the next |
| 5336 | ** call to any SQLite API function. |
| 5337 | ** |
| 5338 | ** ^If the specified table is actually a view, an [error code] is returned. |
| 5339 | ** |
| 5340 | ** ^If the specified column is "rowid", "oid" or "_rowid_" and the table |
| 5341 | ** is not a [WITHOUT ROWID] table and an |
| 5342 | ** [INTEGER PRIMARY KEY] column has been explicitly declared, then the output |
| 5343 | ** parameters are set for the explicitly declared column. ^(If there is no |
| 5344 | ** [INTEGER PRIMARY KEY] column, then the outputs |
| 5345 | ** for the [rowid] are set as follows: |
| 5346 | ** |
| 5347 | ** <pre> |
| 5348 | ** data type: "INTEGER" |
| 5349 | ** collation sequence: "BINARY" |
| 5350 | ** not null: 0 |
| 5351 | ** primary key: 1 |
| 5352 | ** auto increment: 0 |
| 5353 | ** </pre>)^ |
| 5354 | ** |
| 5355 | ** ^This function causes all database schemas to be read from disk and |
| 5356 | ** parsed, if that has not already been done, and returns an error if |
| 5357 | ** any errors are encountered while loading the schema. |
| 5358 | */ |
| 5359 | SQLITE_API int sqlite3_table_column_metadata( |
| 5360 | sqlite3 *db, /* Connection handle */ |
| 5361 | const char *zDbName, /* Database name or NULL */ |
| 5362 | const char *zTableName, /* Table name */ |
| @@ -7303,16 +7319,14 @@ | |
| 7319 | |
| 7320 | /* |
| 7321 | ** CAPI3REF: Write-Ahead Log Commit Hook |
| 7322 | ** |
| 7323 | ** ^The [sqlite3_wal_hook()] function is used to register a callback that |
| 7324 | ** is invoked each time data is committed to a database in wal mode. |
| 7325 | ** |
| 7326 | ** ^(The callback is invoked by SQLite after the commit has taken place and |
| 7327 | ** the associated write-lock on the database released)^, so the implementation |
| 7328 | ** may read, write or [checkpoint] the database as required. |
| 7329 | ** |
| 7330 | ** ^The first parameter passed to the callback function when it is invoked |
| 7331 | ** is a copy of the third parameter passed to sqlite3_wal_hook() when |
| 7332 | ** registering the callback. ^The second is a copy of the database handle. |
| @@ -9096,11 +9110,11 @@ | |
| 9110 | #define _BTREE_H_ |
| 9111 | |
| 9112 | /* TODO: This definition is just included so other modules compile. It |
| 9113 | ** needs to be revisited. |
| 9114 | */ |
| 9115 | #define SQLITE_N_BTREE_META 16 |
| 9116 | |
| 9117 | /* |
| 9118 | ** If defined as non-zero, auto-vacuum is enabled by default. Otherwise |
| 9119 | ** it must be turned on for each database using "PRAGMA auto_vacuum = 1". |
| 9120 | */ |
| @@ -9211,10 +9225,15 @@ | |
| 9225 | ** offset = 36 + (idx * 4) |
| 9226 | ** |
| 9227 | ** For example, the free-page-count field is located at byte offset 36 of |
| 9228 | ** the database file header. The incr-vacuum-flag field is located at |
| 9229 | ** byte offset 64 (== 36+4*7). |
| 9230 | ** |
| 9231 | ** The BTREE_DATA_VERSION value is not really a value stored in the header. |
| 9232 | ** It is a read-only number computed by the pager. But we merge it with |
| 9233 | ** the header value access routines since its access pattern is the same. |
| 9234 | ** Call it a "virtual meta value". |
| 9235 | */ |
| 9236 | #define BTREE_FREE_PAGE_COUNT 0 |
| 9237 | #define BTREE_SCHEMA_VERSION 1 |
| 9238 | #define BTREE_FILE_FORMAT 2 |
| 9239 | #define BTREE_DEFAULT_CACHE_SIZE 3 |
| @@ -9221,10 +9240,11 @@ | |
| 9240 | #define BTREE_LARGEST_ROOT_PAGE 4 |
| 9241 | #define BTREE_TEXT_ENCODING 5 |
| 9242 | #define BTREE_USER_VERSION 6 |
| 9243 | #define BTREE_INCR_VACUUM 7 |
| 9244 | #define BTREE_APPLICATION_ID 8 |
| 9245 | #define BTREE_DATA_VERSION 15 /* A virtual meta-value */ |
| 9246 | |
| 9247 | /* |
| 9248 | ** Values that may be OR'd together to form the second argument of an |
| 9249 | ** sqlite3BtreeCursorHints() call. |
| 9250 | */ |
| @@ -10002,10 +10022,11 @@ | |
| 10022 | SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager); |
| 10023 | #endif |
| 10024 | |
| 10025 | /* Functions used to query pager state and configuration. */ |
| 10026 | SQLITE_PRIVATE u8 sqlite3PagerIsreadonly(Pager*); |
| 10027 | SQLITE_PRIVATE u32 sqlite3PagerDataVersion(Pager*); |
| 10028 | SQLITE_PRIVATE int sqlite3PagerRefcount(Pager*); |
| 10029 | SQLITE_PRIVATE int sqlite3PagerMemUsed(Pager*); |
| 10030 | SQLITE_PRIVATE const char *sqlite3PagerFilename(Pager*, int); |
| 10031 | SQLITE_PRIVATE const sqlite3_vfs *sqlite3PagerVfs(Pager*); |
| 10032 | SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager*); |
| @@ -10743,10 +10764,11 @@ | |
| 10764 | i64 szMmap; /* Default mmap_size setting */ |
| 10765 | unsigned int openFlags; /* Flags passed to sqlite3_vfs.xOpen() */ |
| 10766 | int errCode; /* Most recent error code (SQLITE_*) */ |
| 10767 | int errMask; /* & result codes with this before returning */ |
| 10768 | u16 dbOptFlags; /* Flags to enable/disable optimizations */ |
| 10769 | u8 enc; /* Text encoding */ |
| 10770 | u8 autoCommit; /* The auto-commit flag. */ |
| 10771 | u8 temp_store; /* 1: file 2: memory 0: default */ |
| 10772 | u8 mallocFailed; /* True if we have seen a malloc failure */ |
| 10773 | u8 dfltLockMode; /* Default locking-mode for attached dbs */ |
| 10774 | signed char nextAutovac; /* Autovac setting after VACUUM if >=0 */ |
| @@ -10844,11 +10866,12 @@ | |
| 10866 | }; |
| 10867 | |
| 10868 | /* |
| 10869 | ** A macro to discover the encoding of a database. |
| 10870 | */ |
| 10871 | #define SCHEMA_ENC(db) ((db)->aDb[0].pSchema->enc) |
| 10872 | #define ENC(db) ((db)->enc) |
| 10873 | |
| 10874 | /* |
| 10875 | ** Possible values for the sqlite3.flags. |
| 10876 | */ |
| 10877 | #define SQLITE_VdbeTrace 0x00000001 /* True to trace VDBE execution */ |
| @@ -11468,11 +11491,10 @@ | |
| 11491 | Index *pNext; /* The next index associated with the same table */ |
| 11492 | Schema *pSchema; /* Schema containing this index */ |
| 11493 | u8 *aSortOrder; /* for each column: True==DESC, False==ASC */ |
| 11494 | char **azColl; /* Array of collation sequence names for index */ |
| 11495 | Expr *pPartIdxWhere; /* WHERE clause for partial indices */ |
| 11496 | int tnum; /* DB Page containing root of this index */ |
| 11497 | LogEst szIdxRow; /* Estimated average row size in bytes */ |
| 11498 | u16 nKeyCol; /* Number of columns forming the key */ |
| 11499 | u16 nColumn; /* Number of columns stored in the index */ |
| 11500 | u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */ |
| @@ -12522,10 +12544,11 @@ | |
| 12544 | void *pPage; /* Page cache memory */ |
| 12545 | int szPage; /* Size of each page in pPage[] */ |
| 12546 | int nPage; /* Number of pages in pPage[] */ |
| 12547 | int mxParserStack; /* maximum depth of the parser stack */ |
| 12548 | int sharedCacheEnabled; /* true if shared-cache mode enabled */ |
| 12549 | u32 szPma; /* Maximum Sorter PMA size */ |
| 12550 | /* The above might be initialized to non-zero. The following need to always |
| 12551 | ** initially be zero, however. */ |
| 12552 | int isInit; /* True after initialization has finished */ |
| 12553 | int inProgress; /* True while initialization in progress */ |
| 12554 | int isMutexInit; /* True after mutexes are initialized */ |
| @@ -13444,11 +13467,11 @@ | |
| 13467 | ** print I/O tracing messages. |
| 13468 | */ |
| 13469 | #ifdef SQLITE_ENABLE_IOTRACE |
| 13470 | # define IOTRACE(A) if( sqlite3IoTrace ){ sqlite3IoTrace A; } |
| 13471 | SQLITE_PRIVATE void sqlite3VdbeIOTraceSql(Vdbe*); |
| 13472 | void (*sqlite3IoTrace)(const char*,...); |
| 13473 | #else |
| 13474 | # define IOTRACE(A) |
| 13475 | # define sqlite3VdbeIOTraceSql(X) |
| 13476 | #endif |
| 13477 | |
| @@ -13657,10 +13680,17 @@ | |
| 13680 | */ |
| 13681 | #ifndef SQLITE_ALLOW_COVERING_INDEX_SCAN |
| 13682 | # define SQLITE_ALLOW_COVERING_INDEX_SCAN 1 |
| 13683 | #endif |
| 13684 | |
| 13685 | /* The minimum PMA size is set to this value multiplied by the database |
| 13686 | ** page size in bytes. |
| 13687 | */ |
| 13688 | #ifndef SQLITE_SORTER_PMASZ |
| 13689 | # define SQLITE_SORTER_PMASZ 250 |
| 13690 | #endif |
| 13691 | |
| 13692 | /* |
| 13693 | ** The following singleton contains the global configuration for |
| 13694 | ** the SQLite library. |
| 13695 | */ |
| 13696 | SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = { |
| @@ -13687,10 +13717,11 @@ | |
| 13717 | (void*)0, /* pPage */ |
| 13718 | 0, /* szPage */ |
| 13719 | 0, /* nPage */ |
| 13720 | 0, /* mxParserStack */ |
| 13721 | 0, /* sharedCacheEnabled */ |
| 13722 | SQLITE_SORTER_PMASZ, /* szPma */ |
| 13723 | /* All the rest should always be initialized to zero */ |
| 13724 | 0, /* isInit */ |
| 13725 | 0, /* inProgress */ |
| 13726 | 0, /* isMutexInit */ |
| 13727 | 0, /* isMallocInit */ |
| @@ -19972,10 +20003,16 @@ | |
| 20003 | #endif |
| 20004 | } |
| 20005 | break; |
| 20006 | } |
| 20007 | default: { |
| 20008 | #ifdef SQLITE_ENABLE_API_ARMOR |
| 20009 | if( iType-2<0 || iType-2>=ArraySize(winMutex_staticMutexes) ){ |
| 20010 | (void)SQLITE_MISUSE_BKPT; |
| 20011 | return 0; |
| 20012 | } |
| 20013 | #endif |
| 20014 | assert( iType-2 >= 0 ); |
| 20015 | assert( iType-2 < ArraySize(winMutex_staticMutexes) ); |
| 20016 | assert( winMutex_isInit==1 ); |
| 20017 | p = &winMutex_staticMutexes[iType-2]; |
| 20018 | #ifdef SQLITE_DEBUG |
| @@ -28779,28 +28816,31 @@ | |
| 28816 | do{ |
| 28817 | err = osFallocate(pFile->h, buf.st_size, nSize-buf.st_size); |
| 28818 | }while( err==EINTR ); |
| 28819 | if( err ) return SQLITE_IOERR_WRITE; |
| 28820 | #else |
| 28821 | /* If the OS does not have posix_fallocate(), fake it. Write a |
| 28822 | ** single byte to the last byte in each block that falls entirely |
| 28823 | ** within the extended region. Then, if required, a single byte |
| 28824 | ** at offset (nSize-1), to set the size of the file correctly. |
| 28825 | ** This is a similar technique to that used by glibc on systems |
| 28826 | ** that do not have a real fallocate() call. |
| 28827 | */ |
| 28828 | int nBlk = buf.st_blksize; /* File-system block size */ |
| 28829 | i64 iWrite; /* Next offset to write to */ |
| 28830 | |
| 28831 | iWrite = ((buf.st_size + 2*nBlk - 1)/nBlk)*nBlk-1; |
| 28832 | assert( iWrite>=buf.st_size ); |
| 28833 | assert( (iWrite/nBlk)==((buf.st_size+nBlk-1)/nBlk) ); |
| 28834 | assert( ((iWrite+1)%nBlk)==0 ); |
| 28835 | for(/*no-op*/; iWrite<nSize; iWrite+=nBlk ){ |
| 28836 | int nWrite = seekAndWrite(pFile, iWrite, "", 1); |
| 28837 | if( nWrite!=1 ) return SQLITE_IOERR_WRITE; |
| 28838 | } |
| 28839 | if( nSize%nBlk ){ |
| 28840 | int nWrite = seekAndWrite(pFile, nSize-1, "", 1); |
| 28841 | if( nWrite!=1 ) return SQLITE_IOERR_WRITE; |
| 28842 | } |
| 28843 | #endif |
| 28844 | } |
| 28845 | } |
| 28846 | |
| @@ -34014,12 +34054,12 @@ | |
| 34054 | */ |
| 34055 | SQLITE_API int sqlite3_win32_reset_heap(){ |
| 34056 | int rc; |
| 34057 | MUTEX_LOGIC( sqlite3_mutex *pMaster; ) /* The main static mutex */ |
| 34058 | MUTEX_LOGIC( sqlite3_mutex *pMem; ) /* The memsys static mutex */ |
| 34059 | MUTEX_LOGIC( pMaster = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER); ) |
| 34060 | MUTEX_LOGIC( pMem = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM); ) |
| 34061 | sqlite3_mutex_enter(pMaster); |
| 34062 | sqlite3_mutex_enter(pMem); |
| 34063 | winMemAssertMagic(); |
| 34064 | if( winMemGetHeap()!=NULL && winMemGetOwned() && sqlite3_memory_used()==0 ){ |
| 34065 | /* |
| @@ -35290,11 +35330,11 @@ | |
| 35330 | sqlite3_file *id, /* File to read from */ |
| 35331 | void *pBuf, /* Write content into this buffer */ |
| 35332 | int amt, /* Number of bytes to read */ |
| 35333 | sqlite3_int64 offset /* Begin reading at this offset */ |
| 35334 | ){ |
| 35335 | #if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_OVERLAPPED) |
| 35336 | OVERLAPPED overlapped; /* The offset for ReadFile. */ |
| 35337 | #endif |
| 35338 | winFile *pFile = (winFile*)id; /* file handle */ |
| 35339 | DWORD nRead; /* Number of bytes actually read from file */ |
| 35340 | int nRetry = 0; /* Number of retrys */ |
| @@ -35322,11 +35362,11 @@ | |
| 35362 | offset += nCopy; |
| 35363 | } |
| 35364 | } |
| 35365 | #endif |
| 35366 | |
| 35367 | #if SQLITE_OS_WINCE || defined(SQLITE_WIN32_NO_OVERLAPPED) |
| 35368 | if( winSeekFile(pFile, offset) ){ |
| 35369 | OSTRACE(("READ file=%p, rc=SQLITE_FULL\n", pFile->h)); |
| 35370 | return SQLITE_FULL; |
| 35371 | } |
| 35372 | while( !osReadFile(pFile->h, pBuf, amt, &nRead, 0) ){ |
| @@ -35394,32 +35434,32 @@ | |
| 35434 | offset += nCopy; |
| 35435 | } |
| 35436 | } |
| 35437 | #endif |
| 35438 | |
| 35439 | #if SQLITE_OS_WINCE || defined(SQLITE_WIN32_NO_OVERLAPPED) |
| 35440 | rc = winSeekFile(pFile, offset); |
| 35441 | if( rc==0 ){ |
| 35442 | #else |
| 35443 | { |
| 35444 | #endif |
| 35445 | #if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_OVERLAPPED) |
| 35446 | OVERLAPPED overlapped; /* The offset for WriteFile. */ |
| 35447 | #endif |
| 35448 | u8 *aRem = (u8 *)pBuf; /* Data yet to be written */ |
| 35449 | int nRem = amt; /* Number of bytes yet to be written */ |
| 35450 | DWORD nWrite; /* Bytes written by each WriteFile() call */ |
| 35451 | DWORD lastErrno = NO_ERROR; /* Value returned by GetLastError() */ |
| 35452 | |
| 35453 | #if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_OVERLAPPED) |
| 35454 | memset(&overlapped, 0, sizeof(OVERLAPPED)); |
| 35455 | overlapped.Offset = (LONG)(offset & 0xffffffff); |
| 35456 | overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff); |
| 35457 | #endif |
| 35458 | |
| 35459 | while( nRem>0 ){ |
| 35460 | #if SQLITE_OS_WINCE || defined(SQLITE_WIN32_NO_OVERLAPPED) |
| 35461 | if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, 0) ){ |
| 35462 | #else |
| 35463 | if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, &overlapped) ){ |
| 35464 | #endif |
| 35465 | if( winRetryIoerr(&nRetry, &lastErrno) ) continue; |
| @@ -35428,11 +35468,11 @@ | |
| 35468 | assert( nWrite==0 || nWrite<=(DWORD)nRem ); |
| 35469 | if( nWrite==0 || nWrite>(DWORD)nRem ){ |
| 35470 | lastErrno = osGetLastError(); |
| 35471 | break; |
| 35472 | } |
| 35473 | #if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_OVERLAPPED) |
| 35474 | offset += nWrite; |
| 35475 | overlapped.Offset = (LONG)(offset & 0xffffffff); |
| 35476 | overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff); |
| 35477 | #endif |
| 35478 | aRem += nWrite; |
| @@ -38974,11 +39014,12 @@ | |
| 39014 | SQLITE_PRIVATE int sqlite3PcacheSetPageSize(PCache *pCache, int szPage){ |
| 39015 | assert( pCache->nRef==0 && pCache->pDirty==0 ); |
| 39016 | if( pCache->szPage ){ |
| 39017 | sqlite3_pcache *pNew; |
| 39018 | pNew = sqlite3GlobalConfig.pcache2.xCreate( |
| 39019 | szPage, pCache->szExtra + ROUND8(sizeof(PgHdr)), |
| 39020 | pCache->bPurgeable |
| 39021 | ); |
| 39022 | if( pNew==0 ) return SQLITE_NOMEM; |
| 39023 | sqlite3GlobalConfig.pcache2.xCachesize(pNew, numberOfCachePages(pCache)); |
| 39024 | if( pCache->pCache ){ |
| 39025 | sqlite3GlobalConfig.pcache2.xDestroy(pCache->pCache); |
| @@ -39433,11 +39474,11 @@ | |
| 39474 | |
| 39475 | /* |
| 39476 | ** Return the size of the header added by this middleware layer |
| 39477 | ** in the page-cache hierarchy. |
| 39478 | */ |
| 39479 | SQLITE_PRIVATE int sqlite3HeaderSizePcache(void){ return ROUND8(sizeof(PgHdr)); } |
| 39480 | |
| 39481 | |
| 39482 | #if defined(SQLITE_CHECK_PAGES) || defined(SQLITE_DEBUG) |
| 39483 | /* |
| 39484 | ** For all dirty pages currently in the cache, invoke the specified |
| @@ -39749,11 +39790,11 @@ | |
| 39790 | pcache1Free(pPg); |
| 39791 | sqlite3_free(p); |
| 39792 | pPg = 0; |
| 39793 | } |
| 39794 | #else |
| 39795 | pPg = pcache1Alloc(ROUND8(sizeof(PgHdr1)) + pCache->szPage + pCache->szExtra); |
| 39796 | p = (PgHdr1 *)&((u8 *)pPg)[pCache->szPage]; |
| 39797 | #endif |
| 39798 | pcache1EnterMutex(pCache->pGroup); |
| 39799 | |
| 39800 | if( pPg ){ |
| @@ -40437,11 +40478,11 @@ | |
| 40478 | } |
| 40479 | |
| 40480 | /* |
| 40481 | ** Return the size of the header on each page of this PCACHE implementation. |
| 40482 | */ |
| 40483 | SQLITE_PRIVATE int sqlite3HeaderSizePcache1(void){ return ROUND8(sizeof(PgHdr1)); } |
| 40484 | |
| 40485 | #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT |
| 40486 | /* |
| 40487 | ** This function is called to free superfluous dynamically allocated memory |
| 40488 | ** held by the pager system. Memory in use by any SQLite pager allocated |
| @@ -41795,10 +41836,12 @@ | |
| 41836 | u8 eLock; /* Current lock held on database file */ |
| 41837 | u8 changeCountDone; /* Set after incrementing the change-counter */ |
| 41838 | u8 setMaster; /* True if a m-j name has been written to jrnl */ |
| 41839 | u8 doNotSpill; /* Do not spill the cache when non-zero */ |
| 41840 | u8 subjInMemory; /* True to use in-memory sub-journals */ |
| 41841 | u8 bUseFetch; /* True to use xFetch() */ |
| 41842 | u8 hasBeenUsed; /* True if any content previously read from this pager*/ |
| 41843 | Pgno dbSize; /* Number of pages in the database */ |
| 41844 | Pgno dbOrigSize; /* dbSize before the current transaction */ |
| 41845 | Pgno dbFileSize; /* Number of pages in the database file */ |
| 41846 | Pgno dbHintSize; /* Value passed to FCNTL_SIZE_HINT call */ |
| 41847 | int errCode; /* One of several kinds of errors */ |
| @@ -41812,13 +41855,13 @@ | |
| 41855 | i64 journalOff; /* Current write offset in the journal file */ |
| 41856 | i64 journalHdr; /* Byte offset to previous journal header */ |
| 41857 | sqlite3_backup *pBackup; /* Pointer to list of ongoing backup processes */ |
| 41858 | PagerSavepoint *aSavepoint; /* Array of active savepoints */ |
| 41859 | int nSavepoint; /* Number of elements in aSavepoint[] */ |
| 41860 | u32 iDataVersion; /* Changes whenever database content changes */ |
| 41861 | char dbFileVers[16]; /* Changes whenever database file changes */ |
| 41862 | |
| 41863 | int nMmapOut; /* Number of mmap pages currently outstanding */ |
| 41864 | sqlite3_int64 szMmap; /* Desired maximum mmap size */ |
| 41865 | PgHdr *pMmapFreelist; /* List of free mmap page headers (pDirty) */ |
| 41866 | /* |
| 41867 | ** End of the routinely-changing class members |
| @@ -42830,13 +42873,22 @@ | |
| 42873 | |
| 42874 | /* |
| 42875 | ** Discard the entire contents of the in-memory page-cache. |
| 42876 | */ |
| 42877 | static void pager_reset(Pager *pPager){ |
| 42878 | pPager->iDataVersion++; |
| 42879 | sqlite3BackupRestart(pPager->pBackup); |
| 42880 | sqlite3PcacheClear(pPager->pPCache); |
| 42881 | } |
| 42882 | |
| 42883 | /* |
| 42884 | ** Return the pPager->iDataVersion value |
| 42885 | */ |
| 42886 | SQLITE_PRIVATE u32 sqlite3PagerDataVersion(Pager *pPager){ |
| 42887 | assert( pPager->eState>PAGER_OPEN ); |
| 42888 | return pPager->iDataVersion; |
| 42889 | } |
| 42890 | |
| 42891 | /* |
| 42892 | ** Free all structures in the Pager.aSavepoint[] array and set both |
| 42893 | ** Pager.aSavepoint and Pager.nSavepoint to zero. Close the sub-journal |
| 42894 | ** if it is open and the pager is not in exclusive mode. |
| @@ -45036,11 +45088,11 @@ | |
| 45088 | Pgno pgno, /* Page number */ |
| 45089 | void *pData, /* xFetch()'d data for this page */ |
| 45090 | PgHdr **ppPage /* OUT: Acquired page object */ |
| 45091 | ){ |
| 45092 | PgHdr *p; /* Memory mapped page to return */ |
| 45093 | |
| 45094 | if( pPager->pMmapFreelist ){ |
| 45095 | *ppPage = p = pPager->pMmapFreelist; |
| 45096 | pPager->pMmapFreelist = p->pDirty; |
| 45097 | p->pDirty = 0; |
| 45098 | memset(p->pExtra, 0, pPager->nExtra); |
| @@ -46267,20 +46319,16 @@ | |
| 46319 | assert( (pPager->eLock==SHARED_LOCK) |
| 46320 | || (pPager->exclusiveMode && pPager->eLock>SHARED_LOCK) |
| 46321 | ); |
| 46322 | } |
| 46323 | |
| 46324 | if( !pPager->tempFile && pPager->hasBeenUsed ){ |
| 46325 | /* The shared-lock has just been acquired then check to |
| 46326 | ** see if the database has been modified. If the database has changed, |
| 46327 | ** flush the cache. The pPager->hasBeenUsed flag prevents this from |
| 46328 | ** occurring on the very first access to a file, in order to save a |
| 46329 | ** single unnecessary sqlite3OsRead() call at the start-up. |
| 46330 | ** |
| 46331 | ** Database changes is detected by looking at 15 bytes beginning |
| 46332 | ** at offset 24 into the file. The first 4 of these 16 bytes are |
| 46333 | ** a 32-bit counter that is incremented with each change. The |
| 46334 | ** other bytes change randomly with each file change when |
| @@ -46441,10 +46489,11 @@ | |
| 46489 | assert( noContent==0 || bMmapOk==0 ); |
| 46490 | |
| 46491 | if( pgno==0 ){ |
| 46492 | return SQLITE_CORRUPT_BKPT; |
| 46493 | } |
| 46494 | pPager->hasBeenUsed = 1; |
| 46495 | |
| 46496 | /* If the pager is in the error state, return an error immediately. |
| 46497 | ** Otherwise, request the page from the PCache layer. */ |
| 46498 | if( pPager->errCode!=SQLITE_OK ){ |
| 46499 | rc = pPager->errCode; |
| @@ -46590,10 +46639,11 @@ | |
| 46639 | sqlite3_pcache_page *pPage; |
| 46640 | assert( pPager!=0 ); |
| 46641 | assert( pgno!=0 ); |
| 46642 | assert( pPager->pPCache!=0 ); |
| 46643 | pPage = sqlite3PcacheFetch(pPager->pPCache, pgno, 0); |
| 46644 | assert( pPage==0 || pPager->hasBeenUsed ); |
| 46645 | return sqlite3PcacheFetchFinish(pPager->pPCache, pgno, pPage); |
| 46646 | } |
| 46647 | |
| 46648 | /* |
| 46649 | ** Release a page reference. |
| @@ -47456,10 +47506,11 @@ | |
| 47506 | pPager->eState = PAGER_READER; |
| 47507 | return SQLITE_OK; |
| 47508 | } |
| 47509 | |
| 47510 | PAGERTRACE(("COMMIT %d\n", PAGERID(pPager))); |
| 47511 | pPager->iDataVersion++; |
| 47512 | rc = pager_end_transaction(pPager, pPager->setMaster, 1); |
| 47513 | return pager_error(pPager, rc); |
| 47514 | } |
| 47515 | |
| 47516 | /* |
| @@ -50825,11 +50876,11 @@ | |
| 50876 | } |
| 50877 | nCollide = HASHTABLE_NSLOT; |
| 50878 | for(iKey=walHash(pgno); aHash[iKey]; iKey=walNextHash(iKey)){ |
| 50879 | u32 iFrame = aHash[iKey] + iZero; |
| 50880 | if( iFrame<=iLast && aPgno[aHash[iKey]]==pgno ){ |
| 50881 | assert( iFrame>iRead || CORRUPT_DB ); |
| 50882 | iRead = iFrame; |
| 50883 | } |
| 50884 | if( (nCollide--)==0 ){ |
| 50885 | return SQLITE_CORRUPT_BKPT; |
| 50886 | } |
| @@ -51931,10 +51982,11 @@ | |
| 51982 | u8 inTrans; /* TRANS_NONE, TRANS_READ or TRANS_WRITE */ |
| 51983 | u8 sharable; /* True if we can share pBt with another db */ |
| 51984 | u8 locked; /* True if db currently has pBt locked */ |
| 51985 | int wantToLock; /* Number of nested calls to sqlite3BtreeEnter() */ |
| 51986 | int nBackup; /* Number of backup operations reading this btree */ |
| 51987 | u32 iDataVersion; /* Combines with pBt->pPager->iDataVersion */ |
| 51988 | Btree *pNext; /* List of other sharable Btrees from the same db */ |
| 51989 | Btree *pPrev; /* Back pointer of the same list */ |
| 51990 | #ifndef SQLITE_OMIT_SHARED_CACHE |
| 51991 | BtLock lock; /* Object used to lock page 1 */ |
| 51992 | #endif |
| @@ -56094,10 +56146,11 @@ | |
| 56146 | rc = sqlite3PagerCommitPhaseTwo(pBt->pPager); |
| 56147 | if( rc!=SQLITE_OK && bCleanup==0 ){ |
| 56148 | sqlite3BtreeLeave(p); |
| 56149 | return rc; |
| 56150 | } |
| 56151 | p->iDataVersion--; /* Compensate for pPager->iDataVersion++; */ |
| 56152 | pBt->inTransaction = TRANS_READ; |
| 56153 | btreeClearHasContent(pBt); |
| 56154 | } |
| 56155 | |
| 56156 | btreeEndTransaction(p); |
| @@ -56457,11 +56510,11 @@ | |
| 56510 | } |
| 56511 | for(i=0; i<=pCur->iPage; i++){ |
| 56512 | releasePage(pCur->apPage[i]); |
| 56513 | } |
| 56514 | unlockBtreeIfUnused(pBt); |
| 56515 | sqlite3_free(pCur->aOverflow); |
| 56516 | /* sqlite3_free(pCur); */ |
| 56517 | sqlite3BtreeLeave(pBtree); |
| 56518 | } |
| 56519 | return SQLITE_OK; |
| 56520 | } |
| @@ -56751,10 +56804,11 @@ | |
| 56804 | pBuf += a; |
| 56805 | amt -= a; |
| 56806 | }else{ |
| 56807 | offset -= pCur->info.nLocal; |
| 56808 | } |
| 56809 | |
| 56810 | |
| 56811 | if( rc==SQLITE_OK && amt>0 ){ |
| 56812 | const u32 ovflSize = pBt->usableSize - 4; /* Bytes content per ovfl page */ |
| 56813 | Pgno nextPage; |
| 56814 | |
| @@ -56769,12 +56823,12 @@ | |
| 56823 | ** means "not yet known" (the cache is lazily populated). |
| 56824 | */ |
| 56825 | if( eOp!=2 && (pCur->curFlags & BTCF_ValidOvfl)==0 ){ |
| 56826 | int nOvfl = (pCur->info.nPayload-pCur->info.nLocal+ovflSize-1)/ovflSize; |
| 56827 | if( nOvfl>pCur->nOvflAlloc ){ |
| 56828 | Pgno *aNew = (Pgno*)sqlite3Realloc( |
| 56829 | pCur->aOverflow, nOvfl*2*sizeof(Pgno) |
| 56830 | ); |
| 56831 | if( aNew==0 ){ |
| 56832 | rc = SQLITE_NOMEM; |
| 56833 | }else{ |
| 56834 | pCur->nOvflAlloc = nOvfl*2; |
| @@ -56817,10 +56871,11 @@ | |
| 56871 | ** Note that the aOverflow[] array must be allocated because eOp!=2 |
| 56872 | ** here. If eOp==2, then offset==0 and this branch is never taken. |
| 56873 | */ |
| 56874 | assert( eOp!=2 ); |
| 56875 | assert( pCur->curFlags & BTCF_ValidOvfl ); |
| 56876 | assert( pCur->pBtree->db==pBt->db ); |
| 56877 | if( pCur->aOverflow[iIdx+1] ){ |
| 56878 | nextPage = pCur->aOverflow[iIdx+1]; |
| 56879 | }else{ |
| 56880 | rc = getOverflowPage(pBt, nextPage, 0, &nextPage); |
| 56881 | } |
| @@ -59329,11 +59384,11 @@ | |
| 59384 | + nMaxCells*sizeof(u16) /* szCell */ |
| 59385 | + pBt->pageSize; /* aSpace1 */ |
| 59386 | |
| 59387 | /* EVIDENCE-OF: R-28375-38319 SQLite will never request a scratch buffer |
| 59388 | ** that is more than 6 times the database page size. */ |
| 59389 | assert( szScratch<=6*(int)pBt->pageSize ); |
| 59390 | apCell = sqlite3ScratchMalloc( szScratch ); |
| 59391 | if( apCell==0 ){ |
| 59392 | rc = SQLITE_NOMEM; |
| 59393 | goto balance_cleanup; |
| 59394 | } |
| @@ -59406,12 +59461,12 @@ | |
| 59461 | assert( leafCorrection==4 ); |
| 59462 | if( szCell[nCell]<4 ){ |
| 59463 | /* Do not allow any cells smaller than 4 bytes. If a smaller cell |
| 59464 | ** does exist, pad it with 0x00 bytes. */ |
| 59465 | assert( szCell[nCell]==3 ); |
| 59466 | assert( apCell[nCell]==&aSpace1[iSpace1-3] ); |
| 59467 | aSpace1[iSpace1++] = 0x00; |
| 59468 | szCell[nCell] = 4; |
| 59469 | } |
| 59470 | } |
| 59471 | nCell++; |
| 59472 | } |
| @@ -60719,10 +60774,17 @@ | |
| 60774 | ** is read-only, the others are read/write. |
| 60775 | ** |
| 60776 | ** The schema layer numbers meta values differently. At the schema |
| 60777 | ** layer (and the SetCookie and ReadCookie opcodes) the number of |
| 60778 | ** free pages is not visible. So Cookie[0] is the same as Meta[1]. |
| 60779 | ** |
| 60780 | ** This routine treats Meta[BTREE_DATA_VERSION] as a special case. Instead |
| 60781 | ** of reading the value out of the header, it instead loads the "DataVersion" |
| 60782 | ** from the pager. The BTREE_DATA_VERSION value is not actually stored in the |
| 60783 | ** database file. It is a number computed by the pager. But its access |
| 60784 | ** pattern is the same as header meta values, and so it is convenient to |
| 60785 | ** read it from this routine. |
| 60786 | */ |
| 60787 | SQLITE_PRIVATE void sqlite3BtreeGetMeta(Btree *p, int idx, u32 *pMeta){ |
| 60788 | BtShared *pBt = p->pBt; |
| 60789 | |
| 60790 | sqlite3BtreeEnter(p); |
| @@ -60729,11 +60791,15 @@ | |
| 60791 | assert( p->inTrans>TRANS_NONE ); |
| 60792 | assert( SQLITE_OK==querySharedCacheTableLock(p, MASTER_ROOT, READ_LOCK) ); |
| 60793 | assert( pBt->pPage1 ); |
| 60794 | assert( idx>=0 && idx<=15 ); |
| 60795 | |
| 60796 | if( idx==BTREE_DATA_VERSION ){ |
| 60797 | *pMeta = sqlite3PagerDataVersion(pBt->pPager) + p->iDataVersion; |
| 60798 | }else{ |
| 60799 | *pMeta = get4byte(&pBt->pPage1->aData[36 + idx*4]); |
| 60800 | } |
| 60801 | |
| 60802 | /* If auto-vacuum is disabled in this build and this is an auto-vacuum |
| 60803 | ** database, mark the database as read-only. */ |
| 60804 | #ifdef SQLITE_OMIT_AUTOVACUUM |
| 60805 | if( idx==BTREE_LARGEST_ROOT_PAGE && *pMeta>0 ){ |
| @@ -60820,11 +60886,11 @@ | |
| 60886 | if( pPage->leaf ){ |
| 60887 | do { |
| 60888 | if( pCur->iPage==0 ){ |
| 60889 | /* All pages of the b-tree have been visited. Return successfully. */ |
| 60890 | *pnEntry = nEntry; |
| 60891 | return moveToRoot(pCur); |
| 60892 | } |
| 60893 | moveToParent(pCur); |
| 60894 | }while ( pCur->aiIdx[pCur->iPage]>=pCur->apPage[pCur->iPage]->nCell ); |
| 60895 | |
| 60896 | pCur->aiIdx[pCur->iPage]++; |
| @@ -61676,11 +61742,11 @@ | |
| 61742 | } |
| 61743 | |
| 61744 | /* |
| 61745 | ** Return the size of the header added to each page by this module. |
| 61746 | */ |
| 61747 | SQLITE_PRIVATE int sqlite3HeaderSizeBtree(void){ return ROUND8(sizeof(MemPage)); } |
| 61748 | |
| 61749 | /************** End of btree.c ***********************************************/ |
| 61750 | /************** Begin file backup.c ******************************************/ |
| 61751 | /* |
| 61752 | ** 2009 January 28 |
| @@ -64440,36 +64506,39 @@ | |
| 64506 | ** |
| 64507 | ** assert( sqlite3VdbeAssertMayAbort(pParse->pVdbe, pParse->mayAbort) ); |
| 64508 | */ |
| 64509 | SQLITE_PRIVATE int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){ |
| 64510 | int hasAbort = 0; |
| 64511 | int hasFkCounter = 0; |
| 64512 | Op *pOp; |
| 64513 | VdbeOpIter sIter; |
| 64514 | memset(&sIter, 0, sizeof(sIter)); |
| 64515 | sIter.v = v; |
| 64516 | |
| 64517 | while( (pOp = opIterNext(&sIter))!=0 ){ |
| 64518 | int opcode = pOp->opcode; |
| 64519 | if( opcode==OP_Destroy || opcode==OP_VUpdate || opcode==OP_VRename |
| 64520 | || ((opcode==OP_Halt || opcode==OP_HaltIfNull) |
| 64521 | && ((pOp->p1&0xff)==SQLITE_CONSTRAINT && pOp->p2==OE_Abort)) |
| 64522 | ){ |
| 64523 | hasAbort = 1; |
| 64524 | break; |
| 64525 | } |
| 64526 | #ifndef SQLITE_OMIT_FOREIGN_KEY |
| 64527 | if( opcode==OP_FkCounter && pOp->p1==0 && pOp->p2==1 ){ |
| 64528 | hasFkCounter = 1; |
| 64529 | } |
| 64530 | #endif |
| 64531 | } |
| 64532 | sqlite3DbFree(v->db, sIter.apSub); |
| 64533 | |
| 64534 | /* Return true if hasAbort==mayAbort. Or if a malloc failure occurred. |
| 64535 | ** If malloc failed, then the while() loop above may not have iterated |
| 64536 | ** through all opcodes and hasAbort may be set incorrectly. Return |
| 64537 | ** true for this case to prevent the assert() in the callers frame |
| 64538 | ** from failing. */ |
| 64539 | return ( v->db->mallocFailed || hasAbort==mayAbort || hasFkCounter ); |
| 64540 | } |
| 64541 | #endif /* SQLITE_DEBUG - the sqlite3AssertMayAbort() function */ |
| 64542 | |
| 64543 | /* |
| 64544 | ** Loop through the program looking for P2 values that are negative |
| @@ -68589,11 +68658,14 @@ | |
| 68658 | #ifndef SQLITE_OMIT_WAL |
| 68659 | int i; |
| 68660 | for(i=0; i<db->nDb; i++){ |
| 68661 | Btree *pBt = db->aDb[i].pBt; |
| 68662 | if( pBt ){ |
| 68663 | int nEntry; |
| 68664 | sqlite3BtreeEnter(pBt); |
| 68665 | nEntry = sqlite3PagerWalCallback(sqlite3BtreePager(pBt)); |
| 68666 | sqlite3BtreeLeave(pBt); |
| 68667 | if( db->xWalCallback && nEntry>0 && rc==SQLITE_OK ){ |
| 68668 | rc = db->xWalCallback(db->pWalArg, db, db->aDb[i].zName, nEntry); |
| 68669 | } |
| 68670 | } |
| 68671 | } |
| @@ -68769,11 +68841,10 @@ | |
| 68841 | ** program counter to 0 to ensure that when the statement is |
| 68842 | ** finalized or reset the parser error message is available via |
| 68843 | ** sqlite3_errmsg() and sqlite3_errcode(). |
| 68844 | */ |
| 68845 | const char *zErr = (const char *)sqlite3_value_text(db->pErr); |
| 68846 | sqlite3DbFree(db, v->zErrMsg); |
| 68847 | if( !db->mallocFailed ){ |
| 68848 | v->zErrMsg = sqlite3DbStrDup(db, zErr); |
| 68849 | v->rc = rc2; |
| 68850 | } else { |
| @@ -77131,11 +77202,11 @@ | |
| 77202 | /* |
| 77203 | ** Hard-coded maximum amount of data to accumulate in memory before flushing |
| 77204 | ** to a level 0 PMA. The purpose of this limit is to prevent various integer |
| 77205 | ** overflows. 512MiB. |
| 77206 | */ |
| 77207 | #define SQLITE_MAX_PMASZ (1<<29) |
| 77208 | |
| 77209 | /* |
| 77210 | ** Private objects used by the sorter |
| 77211 | */ |
| 77212 | typedef struct MergeEngine MergeEngine; /* Merge PMAs together */ |
| @@ -77427,13 +77498,10 @@ | |
| 77498 | ** |
| 77499 | ** void *SRVAL(SorterRecord *p) { return (void*)&p[1]; } |
| 77500 | */ |
| 77501 | #define SRVAL(p) ((void*)((SorterRecord*)(p) + 1)) |
| 77502 | |
| 77503 | |
| 77504 | /* Maximum number of PMAs that a single MergeEngine can merge */ |
| 77505 | #define SORTER_MAX_MERGE_COUNT 16 |
| 77506 | |
| 77507 | static int vdbeIncrSwap(IncrMerger*); |
| @@ -77828,14 +77896,15 @@ | |
| 77896 | SortSubtask *pTask = &pSorter->aTask[i]; |
| 77897 | pTask->pSorter = pSorter; |
| 77898 | } |
| 77899 | |
| 77900 | if( !sqlite3TempInMemory(db) ){ |
| 77901 | u32 szPma = sqlite3GlobalConfig.szPma; |
| 77902 | pSorter->mnPmaSize = szPma * pgsz; |
| 77903 | mxCache = db->aDb[0].pSchema->cache_size; |
| 77904 | if( mxCache<(int)szPma ) mxCache = (int)szPma; |
| 77905 | pSorter->mxPmaSize = MIN((i64)mxCache*pgsz, SQLITE_MAX_PMASZ); |
| 77906 | |
| 77907 | /* EVIDENCE-OF: R-26747-61719 When the application provides any amount of |
| 77908 | ** scratch memory using SQLITE_CONFIG_SCRATCH, SQLite avoids unnecessary |
| 77909 | ** large heap allocations. |
| 77910 | */ |
| @@ -78109,16 +78178,16 @@ | |
| 78178 | ** Whether or not the file does end up memory mapped of course depends on |
| 78179 | ** the specific VFS implementation. |
| 78180 | */ |
| 78181 | static void vdbeSorterExtendFile(sqlite3 *db, sqlite3_file *pFd, i64 nByte){ |
| 78182 | if( nByte<=(i64)(db->nMaxSorterMmap) && pFd->pMethods->iVersion>=3 ){ |
| 78183 | void *p = 0; |
| 78184 | int chunksize = 4*1024; |
| 78185 | sqlite3OsFileControlHint(pFd, SQLITE_FCNTL_CHUNK_SIZE, &chunksize); |
| 78186 | sqlite3OsFileControlHint(pFd, SQLITE_FCNTL_SIZE_HINT, &nByte); |
| 78187 | sqlite3OsFetch(pFd, 0, (int)nByte, &p); |
| 78188 | sqlite3OsUnfetch(pFd, 0, p); |
| 78189 | } |
| 78190 | } |
| 78191 | #else |
| 78192 | # define vdbeSorterExtendFile(x,y,z) |
| 78193 | #endif |
| @@ -87296,11 +87365,11 @@ | |
| 87365 | |
| 87366 | p->iGet = -1; |
| 87367 | p->mxSample = mxSample; |
| 87368 | p->nPSample = (tRowcnt)(sqlite3_value_int64(argv[2])/(mxSample/3+1) + 1); |
| 87369 | p->current.anLt = &p->current.anEq[nColUp]; |
| 87370 | p->iPrn = 0x689e962d*(u32)nCol ^ 0xd0944565*(u32)sqlite3_value_int(argv[2]); |
| 87371 | |
| 87372 | /* Set up the Stat4Accum.a[] and aBest[] arrays */ |
| 87373 | p->a = (struct Stat4Sample*)&p->current.anLt[nColUp]; |
| 87374 | p->aBest = &p->a[mxSample]; |
| 87375 | pSpace = (u8*)(&p->a[mxSample+nCol]); |
| @@ -88889,17 +88958,19 @@ | |
| 88958 | }else if( aNew->pSchema->file_format && aNew->pSchema->enc!=ENC(db) ){ |
| 88959 | zErrDyn = sqlite3MPrintf(db, |
| 88960 | "attached databases must use the same text encoding as main database"); |
| 88961 | rc = SQLITE_ERROR; |
| 88962 | } |
| 88963 | sqlite3BtreeEnter(aNew->pBt); |
| 88964 | pPager = sqlite3BtreePager(aNew->pBt); |
| 88965 | sqlite3PagerLockingMode(pPager, db->dfltLockMode); |
| 88966 | sqlite3BtreeSecureDelete(aNew->pBt, |
| 88967 | sqlite3BtreeSecureDelete(db->aDb[0].pBt,-1) ); |
| 88968 | #ifndef SQLITE_OMIT_PAGER_PRAGMAS |
| 88969 | sqlite3BtreeSetPagerFlags(aNew->pBt, 3 | (db->flags & PAGER_FLAGS_MASK)); |
| 88970 | #endif |
| 88971 | sqlite3BtreeLeave(aNew->pBt); |
| 88972 | } |
| 88973 | aNew->safety_level = 3; |
| 88974 | aNew->zName = sqlite3DbStrDup(db, zName); |
| 88975 | if( rc==SQLITE_OK && aNew->zName==0 ){ |
| 88976 | rc = SQLITE_NOMEM; |
| @@ -90021,11 +90092,10 @@ | |
| 90092 | */ |
| 90093 | static void freeIndex(sqlite3 *db, Index *p){ |
| 90094 | #ifndef SQLITE_OMIT_ANALYZE |
| 90095 | sqlite3DeleteIndexSamples(db, p); |
| 90096 | #endif |
| 90097 | sqlite3ExprDelete(db, p->pPartIdxWhere); |
| 90098 | sqlite3DbFree(db, p->zColAff); |
| 90099 | if( p->isResized ) sqlite3DbFree(db, p->azColl); |
| 90100 | #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 |
| 90101 | sqlite3_free(p->aiRowEst); |
| @@ -91300,10 +91370,23 @@ | |
| 91370 | if( pPk==0 ) return; |
| 91371 | pPk->idxType = SQLITE_IDXTYPE_PRIMARYKEY; |
| 91372 | pTab->iPKey = -1; |
| 91373 | }else{ |
| 91374 | pPk = sqlite3PrimaryKeyIndex(pTab); |
| 91375 | /* |
| 91376 | ** Remove all redundant columns from the PRIMARY KEY. For example, change |
| 91377 | ** "PRIMARY KEY(a,b,a,b,c,b,c,d)" into just "PRIMARY KEY(a,b,c,d)". Later |
| 91378 | ** code assumes the PRIMARY KEY contains no repeated columns. |
| 91379 | */ |
| 91380 | for(i=j=1; i<pPk->nKeyCol; i++){ |
| 91381 | if( hasColumn(pPk->aiColumn, j, pPk->aiColumn[i]) ){ |
| 91382 | pPk->nColumn--; |
| 91383 | }else{ |
| 91384 | pPk->aiColumn[j++] = pPk->aiColumn[i]; |
| 91385 | } |
| 91386 | } |
| 91387 | pPk->nKeyCol = j; |
| 91388 | } |
| 91389 | pPk->isCovering = 1; |
| 91390 | assert( pPk!=0 ); |
| 91391 | nPk = pPk->nKeyCol; |
| 91392 | |
| @@ -93776,44 +93859,35 @@ | |
| 93859 | ** |
| 93860 | ** The caller should invoke sqlite3KeyInfoUnref() on the returned object |
| 93861 | ** when it has finished using it. |
| 93862 | */ |
| 93863 | SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoOfIndex(Parse *pParse, Index *pIdx){ |
| 93864 | int i; |
| 93865 | int nCol = pIdx->nColumn; |
| 93866 | int nKey = pIdx->nKeyCol; |
| 93867 | KeyInfo *pKey; |
| 93868 | if( pParse->nErr ) return 0; |
| 93869 | if( pIdx->uniqNotNull ){ |
| 93870 | pKey = sqlite3KeyInfoAlloc(pParse->db, nKey, nCol-nKey); |
| 93871 | }else{ |
| 93872 | pKey = sqlite3KeyInfoAlloc(pParse->db, nCol, 0); |
| 93873 | } |
| 93874 | if( pKey ){ |
| 93875 | assert( sqlite3KeyInfoIsWriteable(pKey) ); |
| 93876 | for(i=0; i<nCol; i++){ |
| 93877 | char *zColl = pIdx->azColl[i]; |
| 93878 | assert( zColl!=0 ); |
| 93879 | pKey->aColl[i] = strcmp(zColl,"BINARY")==0 ? 0 : |
| 93880 | sqlite3LocateCollSeq(pParse, zColl); |
| 93881 | pKey->aSortOrder[i] = pIdx->aSortOrder[i]; |
| 93882 | } |
| 93883 | if( pParse->nErr ){ |
| 93884 | sqlite3KeyInfoUnref(pKey); |
| 93885 | pKey = 0; |
| 93886 | } |
| 93887 | } |
| 93888 | return pKey; |
| 93889 | } |
| 93890 | |
| 93891 | #ifndef SQLITE_OMIT_CTE |
| 93892 | /* |
| 93893 | ** This routine is invoked once per CTE by the parser while parsing a |
| @@ -97430,11 +97504,11 @@ | |
| 97504 | assert( nIncr==1 ); |
| 97505 | sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_FOREIGNKEY, |
| 97506 | OE_Abort, 0, P4_STATIC, P5_ConstraintFK); |
| 97507 | }else{ |
| 97508 | if( nIncr>0 && pFKey->isDeferred==0 ){ |
| 97509 | sqlite3MayAbort(pParse); |
| 97510 | } |
| 97511 | sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr); |
| 97512 | } |
| 97513 | |
| 97514 | sqlite3VdbeResolveLabel(v, iOk); |
| @@ -97501,10 +97575,14 @@ | |
| 97575 | ** This function is called to generate code executed when a row is deleted |
| 97576 | ** from the parent table of foreign key constraint pFKey and, if pFKey is |
| 97577 | ** deferred, when a row is inserted into the same table. When generating |
| 97578 | ** code for an SQL UPDATE operation, this function may be called twice - |
| 97579 | ** once to "delete" the old row and once to "insert" the new row. |
| 97580 | ** |
| 97581 | ** Parameter nIncr is passed -1 when inserting a row (as this may decrease |
| 97582 | ** the number of FK violations in the db) or +1 when deleting one (as this |
| 97583 | ** may increase the number of FK constraint problems). |
| 97584 | ** |
| 97585 | ** The code generated by this function scans through the rows in the child |
| 97586 | ** table that correspond to the parent table row being deleted or inserted. |
| 97587 | ** For each child row found, one of the following actions is taken: |
| 97588 | ** |
| @@ -97618,17 +97696,13 @@ | |
| 97696 | sNameContext.pSrcList = pSrc; |
| 97697 | sNameContext.pParse = pParse; |
| 97698 | sqlite3ResolveExprNames(&sNameContext, pWhere); |
| 97699 | |
| 97700 | /* Create VDBE to loop through the entries in pSrc that match the WHERE |
| 97701 | ** clause. For each row found, increment either the deferred or immediate |
| 97702 | ** foreign key constraint counter. */ |
| 97703 | pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0, 0, 0); |
| 97704 | sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr); |
| 97705 | if( pWInfo ){ |
| 97706 | sqlite3WhereEnd(pWInfo); |
| 97707 | } |
| 97708 | |
| @@ -97802,10 +97876,28 @@ | |
| 97876 | } |
| 97877 | } |
| 97878 | } |
| 97879 | return 0; |
| 97880 | } |
| 97881 | |
| 97882 | /* |
| 97883 | ** Return true if the parser passed as the first argument is being |
| 97884 | ** used to code a trigger that is really a "SET NULL" action belonging |
| 97885 | ** to trigger pFKey. |
| 97886 | */ |
| 97887 | static int isSetNullAction(Parse *pParse, FKey *pFKey){ |
| 97888 | Parse *pTop = sqlite3ParseToplevel(pParse); |
| 97889 | if( pTop->pTriggerPrg ){ |
| 97890 | Trigger *p = pTop->pTriggerPrg->pTrigger; |
| 97891 | if( (p==pFKey->apTrigger[0] && pFKey->aAction[0]==OE_SetNull) |
| 97892 | || (p==pFKey->apTrigger[1] && pFKey->aAction[1]==OE_SetNull) |
| 97893 | ){ |
| 97894 | return 1; |
| 97895 | } |
| 97896 | } |
| 97897 | return 0; |
| 97898 | } |
| 97899 | |
| 97900 | /* |
| 97901 | ** This function is called when inserting, deleting or updating a row of |
| 97902 | ** table pTab to generate VDBE code to perform foreign key constraint |
| 97903 | ** processing for the operation. |
| @@ -97855,11 +97947,11 @@ | |
| 97947 | Index *pIdx = 0; /* Index on key columns in pTo */ |
| 97948 | int *aiFree = 0; |
| 97949 | int *aiCol; |
| 97950 | int iCol; |
| 97951 | int i; |
| 97952 | int bIgnore = 0; |
| 97953 | |
| 97954 | if( aChange |
| 97955 | && sqlite3_stricmp(pTab->zName, pFKey->zTo)!=0 |
| 97956 | && fkChildIsModified(pTab, pFKey, aChange, bChngRowid)==0 |
| 97957 | ){ |
| @@ -97914,11 +98006,11 @@ | |
| 98006 | ** values read from the parent table are NULL. */ |
| 98007 | if( db->xAuth ){ |
| 98008 | int rcauth; |
| 98009 | char *zCol = pTo->aCol[pIdx ? pIdx->aiColumn[i] : pTo->iPKey].zName; |
| 98010 | rcauth = sqlite3AuthReadCol(pParse, pTo->zName, zCol, iDb); |
| 98011 | bIgnore = (rcauth==SQLITE_IGNORE); |
| 98012 | } |
| 98013 | #endif |
| 98014 | } |
| 98015 | |
| 98016 | /* Take a shared-cache advisory read-lock on the parent table. Allocate |
| @@ -97929,16 +98021,22 @@ | |
| 98021 | |
| 98022 | if( regOld!=0 ){ |
| 98023 | /* A row is being removed from the child table. Search for the parent. |
| 98024 | ** If the parent does not exist, removing the child row resolves an |
| 98025 | ** outstanding foreign key constraint violation. */ |
| 98026 | fkLookupParent(pParse, iDb, pTo, pIdx, pFKey, aiCol, regOld, -1, bIgnore); |
| 98027 | } |
| 98028 | if( regNew!=0 && !isSetNullAction(pParse, pFKey) ){ |
| 98029 | /* A row is being added to the child table. If a parent row cannot |
| 98030 | ** be found, adding the child row has violated the FK constraint. |
| 98031 | ** |
| 98032 | ** If this operation is being performed as part of a trigger program |
| 98033 | ** that is actually a "SET NULL" action belonging to this very |
| 98034 | ** foreign key, then omit this scan altogether. As all child key |
| 98035 | ** values are guaranteed to be NULL, it is not possible for adding |
| 98036 | ** this row to cause an FK violation. */ |
| 98037 | fkLookupParent(pParse, iDb, pTo, pIdx, pFKey, aiCol, regNew, +1, bIgnore); |
| 98038 | } |
| 98039 | |
| 98040 | sqlite3DbFree(db, aiFree); |
| 98041 | } |
| 98042 | |
| @@ -97955,12 +98053,12 @@ | |
| 98053 | |
| 98054 | if( !pFKey->isDeferred && !(db->flags & SQLITE_DeferFKs) |
| 98055 | && !pParse->pToplevel && !pParse->isMultiWrite |
| 98056 | ){ |
| 98057 | assert( regOld==0 && regNew!=0 ); |
| 98058 | /* Inserting a single row into a parent table cannot cause (or fix) |
| 98059 | ** an immediate foreign key violation. So do nothing in this case. */ |
| 98060 | continue; |
| 98061 | } |
| 98062 | |
| 98063 | if( sqlite3FkLocateIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ){ |
| 98064 | if( !isIgnoreErrors || db->mallocFailed ) return; |
| @@ -97980,17 +98078,32 @@ | |
| 98078 | |
| 98079 | if( regNew!=0 ){ |
| 98080 | fkScanChildren(pParse, pSrc, pTab, pIdx, pFKey, aiCol, regNew, -1); |
| 98081 | } |
| 98082 | if( regOld!=0 ){ |
| 98083 | int eAction = pFKey->aAction[aChange!=0]; |
| 98084 | fkScanChildren(pParse, pSrc, pTab, pIdx, pFKey, aiCol, regOld, 1); |
| 98085 | /* If this is a deferred FK constraint, or a CASCADE or SET NULL |
| 98086 | ** action applies, then any foreign key violations caused by |
| 98087 | ** removing the parent key will be rectified by the action trigger. |
| 98088 | ** So do not set the "may-abort" flag in this case. |
| 98089 | ** |
| 98090 | ** Note 1: If the FK is declared "ON UPDATE CASCADE", then the |
| 98091 | ** may-abort flag will eventually be set on this statement anyway |
| 98092 | ** (when this function is called as part of processing the UPDATE |
| 98093 | ** within the action trigger). |
| 98094 | ** |
| 98095 | ** Note 2: At first glance it may seem like SQLite could simply omit |
| 98096 | ** all OP_FkCounter related scans when either CASCADE or SET NULL |
| 98097 | ** applies. The trouble starts if the CASCADE or SET NULL action |
| 98098 | ** trigger causes other triggers or action rules attached to the |
| 98099 | ** child table to fire. In these cases the fk constraint counters |
| 98100 | ** might be set incorrectly if any OP_FkCounter related scans are |
| 98101 | ** omitted. */ |
| 98102 | if( !pFKey->isDeferred && eAction!=OE_Cascade && eAction!=OE_SetNull ){ |
| 98103 | sqlite3MayAbort(pParse); |
| 98104 | } |
| 98105 | } |
| 98106 | pItem->zName = 0; |
| 98107 | sqlite3SrcListDelete(db, pSrc); |
| 98108 | } |
| 98109 | sqlite3DbFree(db, aiCol); |
| @@ -101080,11 +101193,10 @@ | |
| 101193 | # define sqlite3_column_database_name16 0 |
| 101194 | # define sqlite3_column_table_name 0 |
| 101195 | # define sqlite3_column_table_name16 0 |
| 101196 | # define sqlite3_column_origin_name 0 |
| 101197 | # define sqlite3_column_origin_name16 0 |
| 101198 | #endif |
| 101199 | |
| 101200 | #ifdef SQLITE_OMIT_AUTHORIZATION |
| 101201 | # define sqlite3_set_authorizer 0 |
| 101202 | #endif |
| @@ -101890,10 +102002,11 @@ | |
| 102002 | #define PragTyp_KEY 38 |
| 102003 | #define PragTyp_REKEY 39 |
| 102004 | #define PragTyp_LOCK_STATUS 40 |
| 102005 | #define PragTyp_PARSER_TRACE 41 |
| 102006 | #define PragFlag_NeedSchema 0x01 |
| 102007 | #define PragFlag_ReadOnly 0x02 |
| 102008 | static const struct sPragmaNames { |
| 102009 | const char *const zName; /* Name of pragma */ |
| 102010 | u8 ePragTyp; /* PragTyp_XXX value */ |
| 102011 | u8 mPragFlag; /* Zero or more PragFlag_XXX values */ |
| 102012 | u32 iArg; /* Extra argument */ |
| @@ -101906,11 +102019,11 @@ | |
| 102019 | #endif |
| 102020 | #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) |
| 102021 | { /* zName: */ "application_id", |
| 102022 | /* ePragTyp: */ PragTyp_HEADER_VALUE, |
| 102023 | /* ePragFlag: */ 0, |
| 102024 | /* iArg: */ BTREE_APPLICATION_ID }, |
| 102025 | #endif |
| 102026 | #if !defined(SQLITE_OMIT_AUTOVACUUM) |
| 102027 | { /* zName: */ "auto_vacuum", |
| 102028 | /* ePragTyp: */ PragTyp_AUTO_VACUUM, |
| 102029 | /* ePragFlag: */ PragFlag_NeedSchema, |
| @@ -101972,10 +102085,16 @@ | |
| 102085 | { /* zName: */ "data_store_directory", |
| 102086 | /* ePragTyp: */ PragTyp_DATA_STORE_DIRECTORY, |
| 102087 | /* ePragFlag: */ 0, |
| 102088 | /* iArg: */ 0 }, |
| 102089 | #endif |
| 102090 | #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) |
| 102091 | { /* zName: */ "data_version", |
| 102092 | /* ePragTyp: */ PragTyp_HEADER_VALUE, |
| 102093 | /* ePragFlag: */ PragFlag_ReadOnly, |
| 102094 | /* iArg: */ BTREE_DATA_VERSION }, |
| 102095 | #endif |
| 102096 | #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) |
| 102097 | { /* zName: */ "database_list", |
| 102098 | /* ePragTyp: */ PragTyp_DATABASE_LIST, |
| 102099 | /* ePragFlag: */ PragFlag_NeedSchema, |
| 102100 | /* iArg: */ 0 }, |
| @@ -102027,12 +102146,12 @@ | |
| 102146 | #endif |
| 102147 | #endif |
| 102148 | #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) |
| 102149 | { /* zName: */ "freelist_count", |
| 102150 | /* ePragTyp: */ PragTyp_HEADER_VALUE, |
| 102151 | /* ePragFlag: */ PragFlag_ReadOnly, |
| 102152 | /* iArg: */ BTREE_FREE_PAGE_COUNT }, |
| 102153 | #endif |
| 102154 | #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) |
| 102155 | { /* zName: */ "full_column_names", |
| 102156 | /* ePragTyp: */ PragTyp_FLAG, |
| 102157 | /* ePragFlag: */ 0, |
| @@ -102180,11 +102299,11 @@ | |
| 102299 | #endif |
| 102300 | #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) |
| 102301 | { /* zName: */ "schema_version", |
| 102302 | /* ePragTyp: */ PragTyp_HEADER_VALUE, |
| 102303 | /* ePragFlag: */ 0, |
| 102304 | /* iArg: */ BTREE_SCHEMA_VERSION }, |
| 102305 | #endif |
| 102306 | #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) |
| 102307 | { /* zName: */ "secure_delete", |
| 102308 | /* ePragTyp: */ PragTyp_SECURE_DELETE, |
| 102309 | /* ePragFlag: */ 0, |
| @@ -102246,11 +102365,11 @@ | |
| 102365 | /* iArg: */ 0 }, |
| 102366 | #if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS) |
| 102367 | { /* zName: */ "user_version", |
| 102368 | /* ePragTyp: */ PragTyp_HEADER_VALUE, |
| 102369 | /* ePragFlag: */ 0, |
| 102370 | /* iArg: */ BTREE_USER_VERSION }, |
| 102371 | #endif |
| 102372 | #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) |
| 102373 | #if defined(SQLITE_DEBUG) |
| 102374 | { /* zName: */ "vdbe_addoptrace", |
| 102375 | /* ePragTyp: */ PragTyp_FLAG, |
| @@ -102289,11 +102408,11 @@ | |
| 102408 | /* ePragTyp: */ PragTyp_FLAG, |
| 102409 | /* ePragFlag: */ 0, |
| 102410 | /* iArg: */ SQLITE_WriteSchema|SQLITE_RecoveryMode }, |
| 102411 | #endif |
| 102412 | }; |
| 102413 | /* Number of pragmas: 58 on by default, 71 total. */ |
| 102414 | /* End of the automatically generated pragma table. |
| 102415 | ***************************************************************************/ |
| 102416 | |
| 102417 | /* |
| 102418 | ** Interpret the given string as a safety level. Return 0 for OFF, |
| @@ -103899,11 +104018,12 @@ | |
| 104018 | !(DbHasProperty(db, 0, DB_SchemaLoaded)) || |
| 104019 | DbHasProperty(db, 0, DB_Empty) |
| 104020 | ){ |
| 104021 | for(pEnc=&encnames[0]; pEnc->zName; pEnc++){ |
| 104022 | if( 0==sqlite3StrICmp(zRight, pEnc->zName) ){ |
| 104023 | SCHEMA_ENC(db) = ENC(db) = |
| 104024 | pEnc->enc ? pEnc->enc : SQLITE_UTF16NATIVE; |
| 104025 | break; |
| 104026 | } |
| 104027 | } |
| 104028 | if( !pEnc->zName ){ |
| 104029 | sqlite3ErrorMsg(pParse, "unsupported encoding: %s", zRight); |
| @@ -103944,28 +104064,13 @@ | |
| 104064 | ** |
| 104065 | ** The user-version is not used internally by SQLite. It may be used by |
| 104066 | ** applications for any purpose. |
| 104067 | */ |
| 104068 | case PragTyp_HEADER_VALUE: { |
| 104069 | int iCookie = aPragmaNames[mid].iArg; /* Which cookie to read or write */ |
| 104070 | sqlite3VdbeUsesBtree(v, iDb); |
| 104071 | if( zRight && (aPragmaNames[mid].mPragFlag & PragFlag_ReadOnly)==0 ){ |
| 104072 | /* Write the specified cookie value */ |
| 104073 | static const VdbeOpList setCookie[] = { |
| 104074 | { OP_Transaction, 0, 1, 0}, /* 0 */ |
| 104075 | { OP_Integer, 0, 1, 0}, /* 1 */ |
| 104076 | { OP_SetCookie, 0, 0, 1}, /* 2 */ |
| @@ -104607,13 +104712,15 @@ | |
| 104712 | SQLITE_PRIVATE int sqlite3Init(sqlite3 *db, char **pzErrMsg){ |
| 104713 | int i, rc; |
| 104714 | int commit_internal = !(db->flags&SQLITE_InternChanges); |
| 104715 | |
| 104716 | assert( sqlite3_mutex_held(db->mutex) ); |
| 104717 | assert( sqlite3BtreeHoldsMutex(db->aDb[0].pBt) ); |
| 104718 | assert( db->init.busy==0 ); |
| 104719 | rc = SQLITE_OK; |
| 104720 | db->init.busy = 1; |
| 104721 | ENC(db) = SCHEMA_ENC(db); |
| 104722 | for(i=0; rc==SQLITE_OK && i<db->nDb; i++){ |
| 104723 | if( DbHasProperty(db, i, DB_SchemaLoaded) || i==1 ) continue; |
| 104724 | rc = sqlite3InitOne(db, i, pzErrMsg); |
| 104725 | if( rc ){ |
| 104726 | sqlite3ResetOneSchema(db, i); |
| @@ -110751,11 +110858,11 @@ | |
| 110858 | ){ |
| 110859 | int rc; |
| 110860 | TabResult res; |
| 110861 | |
| 110862 | #ifdef SQLITE_ENABLE_API_ARMOR |
| 110863 | if( !sqlite3SafetyCheckOk(db) || pazResult==0 ) return SQLITE_MISUSE_BKPT; |
| 110864 | #endif |
| 110865 | *pazResult = 0; |
| 110866 | if( pnColumn ) *pnColumn = 0; |
| 110867 | if( pnRow ) *pnRow = 0; |
| 110868 | if( pzErrMsg ) *pzErrMsg = 0; |
| @@ -118621,11 +118728,10 @@ | |
| 118728 | sqlite3_free(p->u.vtab.idxStr); |
| 118729 | p->u.vtab.needFree = 0; |
| 118730 | p->u.vtab.idxStr = 0; |
| 118731 | }else if( (p->wsFlags & WHERE_AUTO_INDEX)!=0 && p->u.btree.pIndex!=0 ){ |
| 118732 | sqlite3DbFree(db, p->u.btree.pIndex->zColAff); |
| 118733 | sqlite3DbFree(db, p->u.btree.pIndex); |
| 118734 | p->u.btree.pIndex = 0; |
| 118735 | } |
| 118736 | } |
| 118737 | } |
| @@ -125628,10 +125734,13 @@ | |
| 125734 | u8 enableLookaside; /* Saved value of db->lookaside.bEnabled */ |
| 125735 | sqlite3 *db = pParse->db; /* The database connection */ |
| 125736 | int mxSqlLen; /* Max length of an SQL string */ |
| 125737 | |
| 125738 | |
| 125739 | #ifdef SQLITE_ENABLE_API_ARMOR |
| 125740 | if( zSql==0 || pzErrMsg==0 ) return SQLITE_MISUSE_BKPT; |
| 125741 | #endif |
| 125742 | mxSqlLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH]; |
| 125743 | if( db->nVdbeActive==0 ){ |
| 125744 | db->u1.isInterrupted = 0; |
| 125745 | } |
| 125746 | pParse->rc = SQLITE_OK; |
| @@ -125866,17 +125975,10 @@ | |
| 125975 | */ |
| 125976 | SQLITE_API int sqlite3_complete(const char *zSql){ |
| 125977 | u8 state = 0; /* Current state, using numbers defined in header comment */ |
| 125978 | u8 token; /* Value of the next token */ |
| 125979 | |
| 125980 | #ifndef SQLITE_OMIT_TRIGGER |
| 125981 | /* A complex statement machine used to detect the end of a CREATE TRIGGER |
| 125982 | ** statement. This is the normal case. |
| 125983 | */ |
| 125984 | static const u8 trans[8][8] = { |
| @@ -125901,10 +126003,17 @@ | |
| 126003 | /* 0 INVALID: */ { 1, 0, 2, }, |
| 126004 | /* 1 START: */ { 1, 1, 2, }, |
| 126005 | /* 2 NORMAL: */ { 1, 2, 2, }, |
| 126006 | }; |
| 126007 | #endif /* SQLITE_OMIT_TRIGGER */ |
| 126008 | |
| 126009 | #ifdef SQLITE_ENABLE_API_ARMOR |
| 126010 | if( zSql==0 ){ |
| 126011 | (void)SQLITE_MISUSE_BKPT; |
| 126012 | return 0; |
| 126013 | } |
| 126014 | #endif |
| 126015 | |
| 126016 | while( *zSql ){ |
| 126017 | switch( *zSql ){ |
| 126018 | case ';': { /* A semicolon */ |
| 126019 | token = tkSEMI; |
| @@ -126203,11 +126312,11 @@ | |
| 126312 | ** If the following function pointer is not NULL and if |
| 126313 | ** SQLITE_ENABLE_IOTRACE is enabled, then messages describing |
| 126314 | ** I/O active are written using this function. These messages |
| 126315 | ** are intended for debugging activity only. |
| 126316 | */ |
| 126317 | /* not-private */ void (*sqlite3IoTrace)(const char*, ...) = 0; |
| 126318 | #endif |
| 126319 | |
| 126320 | /* |
| 126321 | ** If the following global variable points to a string which is the |
| 126322 | ** name of a directory, then that directory will be used to store |
| @@ -126412,10 +126521,17 @@ | |
| 126521 | ** routine is not threadsafe. But it is safe to invoke this routine |
| 126522 | ** on when SQLite is already shut down. If SQLite is already shut down |
| 126523 | ** when this routine is invoked, then this routine is a harmless no-op. |
| 126524 | */ |
| 126525 | SQLITE_API int sqlite3_shutdown(void){ |
| 126526 | #ifdef SQLITE_OMIT_WSD |
| 126527 | int rc = sqlite3_wsd_init(4096, 24); |
| 126528 | if( rc!=SQLITE_OK ){ |
| 126529 | return rc; |
| 126530 | } |
| 126531 | #endif |
| 126532 | |
| 126533 | if( sqlite3GlobalConfig.isInit ){ |
| 126534 | #ifdef SQLITE_EXTRA_SHUTDOWN |
| 126535 | void SQLITE_EXTRA_SHUTDOWN(void); |
| 126536 | SQLITE_EXTRA_SHUTDOWN(); |
| 126537 | #endif |
| @@ -126727,10 +126843,15 @@ | |
| 126843 | ** heap. */ |
| 126844 | sqlite3GlobalConfig.nHeap = va_arg(ap, int); |
| 126845 | break; |
| 126846 | } |
| 126847 | #endif |
| 126848 | |
| 126849 | case SQLITE_CONFIG_PMASZ: { |
| 126850 | sqlite3GlobalConfig.szPma = va_arg(ap, unsigned int); |
| 126851 | break; |
| 126852 | } |
| 126853 | |
| 126854 | default: { |
| 126855 | rc = SQLITE_ERROR; |
| 126856 | break; |
| 126857 | } |
| @@ -127173,18 +127294,10 @@ | |
| 127294 | |
| 127295 | /* Close all database connections */ |
| 127296 | for(j=0; j<db->nDb; j++){ |
| 127297 | struct Db *pDb = &db->aDb[j]; |
| 127298 | if( pDb->pBt ){ |
| 127299 | sqlite3BtreeClose(pDb->pBt); |
| 127300 | pDb->pBt = 0; |
| 127301 | if( j!=1 ){ |
| 127302 | pDb->pSchema = 0; |
| 127303 | } |
| @@ -128308,36 +128421,10 @@ | |
| 128421 | */ |
| 128422 | SQLITE_API const char *sqlite3_errstr(int rc){ |
| 128423 | return sqlite3ErrStr(rc); |
| 128424 | } |
| 128425 | |
| 128426 | /* |
| 128427 | ** Create a new collating function for database "db". The name is zName |
| 128428 | ** and the encoding is enc. |
| 128429 | */ |
| 128430 | static int createCollation( |
| @@ -128377,11 +128464,10 @@ | |
| 128464 | sqlite3ErrorWithMsg(db, SQLITE_BUSY, |
| 128465 | "unable to delete/modify collation sequence due to active statements"); |
| 128466 | return SQLITE_BUSY; |
| 128467 | } |
| 128468 | sqlite3ExpirePreparedStatements(db); |
| 128469 | |
| 128470 | /* If collation sequence pColl was created directly by a call to |
| 128471 | ** sqlite3_create_collation, and not generated by synthCollSeq(), |
| 128472 | ** then any copies made by synthCollSeq() need to be invalidated. |
| 128473 | ** Also, collation destructor - CollSeq.xDel() - function may need |
| @@ -128882,10 +128968,13 @@ | |
| 128968 | | SQLITE_RecTriggers |
| 128969 | #endif |
| 128970 | #if defined(SQLITE_DEFAULT_FOREIGN_KEYS) && SQLITE_DEFAULT_FOREIGN_KEYS |
| 128971 | | SQLITE_ForeignKeys |
| 128972 | #endif |
| 128973 | #if defined(SQLITE_REVERSE_UNORDERED_SELECTS) |
| 128974 | | SQLITE_ReverseOrder |
| 128975 | #endif |
| 128976 | ; |
| 128977 | sqlite3HashInit(&db->aCollSeq); |
| 128978 | #ifndef SQLITE_OMIT_VIRTUALTABLE |
| 128979 | sqlite3HashInit(&db->aModule); |
| 128980 | #endif |
| @@ -128929,11 +129018,14 @@ | |
| 129018 | rc = SQLITE_NOMEM; |
| 129019 | } |
| 129020 | sqlite3Error(db, rc); |
| 129021 | goto opendb_out; |
| 129022 | } |
| 129023 | sqlite3BtreeEnter(db->aDb[0].pBt); |
| 129024 | db->aDb[0].pSchema = sqlite3SchemaGet(db, db->aDb[0].pBt); |
| 129025 | if( !db->mallocFailed ) ENC(db) = SCHEMA_ENC(db); |
| 129026 | sqlite3BtreeLeave(db->aDb[0].pBt); |
| 129027 | db->aDb[1].pSchema = sqlite3SchemaGet(db, 0); |
| 129028 | |
| 129029 | /* The default safety_level for the main database is 'full'; for the temp |
| 129030 | ** database it is 'NONE'. This matches the pager layer defaults. |
| 129031 | */ |
| @@ -129087,11 +129179,11 @@ | |
| 129179 | if( zFilename8 ){ |
| 129180 | rc = openDatabase(zFilename8, ppDb, |
| 129181 | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0); |
| 129182 | assert( *ppDb || rc==SQLITE_NOMEM ); |
| 129183 | if( rc==SQLITE_OK && !DbHasProperty(*ppDb, 0, DB_SchemaLoaded) ){ |
| 129184 | SCHEMA_ENC(*ppDb) = ENC(*ppDb) = SQLITE_UTF16NATIVE; |
| 129185 | } |
| 129186 | }else{ |
| 129187 | rc = SQLITE_NOMEM; |
| 129188 | } |
| 129189 | sqlite3ValueFree(pVal); |
| @@ -129283,11 +129375,10 @@ | |
| 129375 | |
| 129376 | /* |
| 129377 | ** Return meta information about a specific column of a database table. |
| 129378 | ** See comment in sqlite3.h (sqlite.h.in) for details. |
| 129379 | */ |
| 129380 | SQLITE_API int sqlite3_table_column_metadata( |
| 129381 | sqlite3 *db, /* Connection handle */ |
| 129382 | const char *zDbName, /* Database name or NULL */ |
| 129383 | const char *zTableName, /* Table name */ |
| 129384 | const char *zColumnName, /* Column name */ |
| @@ -129323,25 +129414,27 @@ | |
| 129414 | pTab = 0; |
| 129415 | goto error_out; |
| 129416 | } |
| 129417 | |
| 129418 | /* Find the column for which info is requested */ |
| 129419 | if( zColumnName==0 ){ |
| 129420 | /* Query for existance of table only */ |
| 129421 | }else{ |
| 129422 | for(iCol=0; iCol<pTab->nCol; iCol++){ |
| 129423 | pCol = &pTab->aCol[iCol]; |
| 129424 | if( 0==sqlite3StrICmp(pCol->zName, zColumnName) ){ |
| 129425 | break; |
| 129426 | } |
| 129427 | } |
| 129428 | if( iCol==pTab->nCol ){ |
| 129429 | if( HasRowid(pTab) && sqlite3IsRowid(zColumnName) ){ |
| 129430 | iCol = pTab->iPKey; |
| 129431 | pCol = iCol>=0 ? &pTab->aCol[iCol] : 0; |
| 129432 | }else{ |
| 129433 | pTab = 0; |
| 129434 | goto error_out; |
| 129435 | } |
| 129436 | } |
| 129437 | } |
| 129438 | |
| 129439 | /* The following block stores the meta information that will be returned |
| 129440 | ** to the caller in local variables zDataType, zCollSeq, notnull, primarykey |
| @@ -129390,11 +129483,10 @@ | |
| 129483 | sqlite3DbFree(db, zErrMsg); |
| 129484 | rc = sqlite3ApiExit(db, rc); |
| 129485 | sqlite3_mutex_leave(db->mutex); |
| 129486 | return rc; |
| 129487 | } |
| 129488 | |
| 129489 | /* |
| 129490 | ** Sleep for a little while. Return the amount of time slept. |
| 129491 | */ |
| 129492 | SQLITE_API int sqlite3_sleep(int ms){ |
| @@ -129829,32 +129921,34 @@ | |
| 129921 | /* |
| 129922 | ** Return the filename of the database associated with a database |
| 129923 | ** connection. |
| 129924 | */ |
| 129925 | SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName){ |
| 129926 | Btree *pBt; |
| 129927 | #ifdef SQLITE_ENABLE_API_ARMOR |
| 129928 | if( !sqlite3SafetyCheckOk(db) ){ |
| 129929 | (void)SQLITE_MISUSE_BKPT; |
| 129930 | return 0; |
| 129931 | } |
| 129932 | #endif |
| 129933 | pBt = sqlite3DbNameToBtree(db, zDbName); |
| 129934 | return pBt ? sqlite3BtreeGetFilename(pBt) : 0; |
| 129935 | } |
| 129936 | |
| 129937 | /* |
| 129938 | ** Return 1 if database is read-only or 0 if read/write. Return -1 if |
| 129939 | ** no such database exists. |
| 129940 | */ |
| 129941 | SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName){ |
| 129942 | Btree *pBt; |
| 129943 | #ifdef SQLITE_ENABLE_API_ARMOR |
| 129944 | if( !sqlite3SafetyCheckOk(db) ){ |
| 129945 | (void)SQLITE_MISUSE_BKPT; |
| 129946 | return -1; |
| 129947 | } |
| 129948 | #endif |
| 129949 | pBt = sqlite3DbNameToBtree(db, zDbName); |
| 129950 | return pBt ? sqlite3BtreeIsReadonly(pBt) : -1; |
| 129951 | } |
| 129952 | |
| 129953 | /************** End of main.c ************************************************/ |
| 129954 | /************** Begin file notify.c ******************************************/ |
| @@ -150061,11 +150155,11 @@ | |
| 150155 | } |
| 150156 | i = pCur->nPoint++; |
| 150157 | pNew = pCur->aPoint + i; |
| 150158 | pNew->rScore = rScore; |
| 150159 | pNew->iLevel = iLevel; |
| 150160 | assert( iLevel<=RTREE_MAX_DEPTH ); |
| 150161 | while( i>0 ){ |
| 150162 | RtreeSearchPoint *pParent; |
| 150163 | j = (i-1)/2; |
| 150164 | pParent = pCur->aPoint + j; |
| 150165 | if( rtreeSearchPointCompare(pNew, pParent)>=0 ) break; |
| 150166 |
+40
-26
| --- src/sqlite3.h | ||
| +++ src/sqlite3.h | ||
| @@ -107,11 +107,11 @@ | ||
| 107 | 107 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 108 | 108 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 109 | 109 | */ |
| 110 | 110 | #define SQLITE_VERSION "3.8.8" |
| 111 | 111 | #define SQLITE_VERSION_NUMBER 3008008 |
| 112 | -#define SQLITE_SOURCE_ID "2014-12-06 14:56:49 6aeece19a235344be2537e66a3fe08b1febfb5a0" | |
| 112 | +#define SQLITE_SOURCE_ID "2015-01-03 18:59:17 23d4c07eb81db5a5c6beb56b5820f0b6501f1fb6" | |
| 113 | 113 | |
| 114 | 114 | /* |
| 115 | 115 | ** CAPI3REF: Run-Time Library Version Numbers |
| 116 | 116 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 117 | 117 | ** |
| @@ -199,11 +199,11 @@ | ||
| 199 | 199 | ** This interface only reports on the compile-time mutex setting |
| 200 | 200 | ** of the [SQLITE_THREADSAFE] flag. If SQLite is compiled with |
| 201 | 201 | ** SQLITE_THREADSAFE=1 or =2 then mutexes are enabled by default but |
| 202 | 202 | ** can be fully or partially disabled using a call to [sqlite3_config()] |
| 203 | 203 | ** with the verbs [SQLITE_CONFIG_SINGLETHREAD], [SQLITE_CONFIG_MULTITHREAD], |
| 204 | -** or [SQLITE_CONFIG_MUTEX]. ^(The return value of the | |
| 204 | +** or [SQLITE_CONFIG_SERIALIZED]. ^(The return value of the | |
| 205 | 205 | ** sqlite3_threadsafe() function shows only the compile-time setting of |
| 206 | 206 | ** thread safety, not any run-time changes to that setting made by |
| 207 | 207 | ** sqlite3_config(). In other words, the return value from sqlite3_threadsafe() |
| 208 | 208 | ** is unchanged by calls to sqlite3_config().)^ |
| 209 | 209 | ** |
| @@ -1568,11 +1568,11 @@ | ||
| 1568 | 1568 | ** configuration option. |
| 1569 | 1569 | ** ^There are three arguments to SQLITE_CONFIG_PAGECACHE: A pointer to |
| 1570 | 1570 | ** 8-byte aligned |
| 1571 | 1571 | ** memory, the size of each page buffer (sz), and the number of pages (N). |
| 1572 | 1572 | ** The sz argument should be the size of the largest database page |
| 1573 | -** (a power of two between 512 and 32768) plus some extra bytes for each | |
| 1573 | +** (a power of two between 512 and 65536) plus some extra bytes for each | |
| 1574 | 1574 | ** page header. ^The number of extra bytes needed by the page header |
| 1575 | 1575 | ** can be determined using the [SQLITE_CONFIG_PCACHE_HDRSZ] option |
| 1576 | 1576 | ** to [sqlite3_config()]. |
| 1577 | 1577 | ** ^It is harmless, apart from the wasted memory, |
| 1578 | 1578 | ** for the sz parameter to be larger than necessary. The first |
| @@ -1748,10 +1748,21 @@ | ||
| 1748 | 1748 | ** <dd>^The SQLITE_CONFIG_PCACHE_HDRSZ option takes a single parameter which |
| 1749 | 1749 | ** is a pointer to an integer and writes into that integer the number of extra |
| 1750 | 1750 | ** bytes per page required for each page in [SQLITE_CONFIG_PAGECACHE]. |
| 1751 | 1751 | ** The amount of extra space required can change depending on the compiler, |
| 1752 | 1752 | ** target platform, and SQLite version. |
| 1753 | +** | |
| 1754 | +** [[SQLITE_CONFIG_PMASZ]] | |
| 1755 | +** <dt>SQLITE_CONFIG_PMASZ | |
| 1756 | +** <dd>^The SQLITE_CONFIG_PMASZ option takes a single parameter which | |
| 1757 | +** is an unsigned integer and sets the "Minimum PMA Size" for the multithreaded | |
| 1758 | +** sorter to that integer. The default minimum PMA Size is set by the | |
| 1759 | +** [SQLITE_SORTER_PMASZ] compile-time option. New threads are launched | |
| 1760 | +** to help with sort operations when multithreaded sorting | |
| 1761 | +** is enabled (using the [PRAGMA threads] command) and the amount of content | |
| 1762 | +** to be sorted exceeds the page size times the minimum of the | |
| 1763 | +** [PRAGMA cache_size] setting and this value. | |
| 1753 | 1764 | ** </dl> |
| 1754 | 1765 | */ |
| 1755 | 1766 | #define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */ |
| 1756 | 1767 | #define SQLITE_CONFIG_MULTITHREAD 2 /* nil */ |
| 1757 | 1768 | #define SQLITE_CONFIG_SERIALIZED 3 /* nil */ |
| @@ -1774,10 +1785,11 @@ | ||
| 1774 | 1785 | #define SQLITE_CONFIG_COVERING_INDEX_SCAN 20 /* int */ |
| 1775 | 1786 | #define SQLITE_CONFIG_SQLLOG 21 /* xSqllog, void* */ |
| 1776 | 1787 | #define SQLITE_CONFIG_MMAP_SIZE 22 /* sqlite3_int64, sqlite3_int64 */ |
| 1777 | 1788 | #define SQLITE_CONFIG_WIN32_HEAPSIZE 23 /* int nByte */ |
| 1778 | 1789 | #define SQLITE_CONFIG_PCACHE_HDRSZ 24 /* int *psz */ |
| 1790 | +#define SQLITE_CONFIG_PMASZ 25 /* unsigned int szPma */ | |
| 1779 | 1791 | |
| 1780 | 1792 | /* |
| 1781 | 1793 | ** CAPI3REF: Database Connection Configuration Options |
| 1782 | 1794 | ** |
| 1783 | 1795 | ** These constants are the available integer configuration options that |
| @@ -5155,24 +5167,31 @@ | ||
| 5155 | 5167 | |
| 5156 | 5168 | |
| 5157 | 5169 | /* |
| 5158 | 5170 | ** CAPI3REF: Extract Metadata About A Column Of A Table |
| 5159 | 5171 | ** |
| 5160 | -** ^This routine returns metadata about a specific column of a specific | |
| 5161 | -** database table accessible using the [database connection] handle | |
| 5162 | -** passed as the first function argument. | |
| 5172 | +** ^(The sqlite3_table_column_metadata(X,D,T,C,....) routine returns | |
| 5173 | +** information about column C of table T in database D | |
| 5174 | +** on [database connection] X.)^ ^The sqlite3_table_column_metadata() | |
| 5175 | +** interface returns SQLITE_OK and fills in the non-NULL pointers in | |
| 5176 | +** the final five arguments with appropriate values if the specified | |
| 5177 | +** column exists. ^The sqlite3_table_column_metadata() interface returns | |
| 5178 | +** SQLITE_ERROR and if the specified column does not exist. | |
| 5179 | +** ^If the column-name parameter to sqlite3_table_column_metadata() is a | |
| 5180 | +** NULL pointer, then this routine simply checks for the existance of the | |
| 5181 | +** table and returns SQLITE_OK if the table exists and SQLITE_ERROR if it | |
| 5182 | +** does not. | |
| 5163 | 5183 | ** |
| 5164 | 5184 | ** ^The column is identified by the second, third and fourth parameters to |
| 5165 | -** this function. ^The second parameter is either the name of the database | |
| 5185 | +** this function. ^(The second parameter is either the name of the database | |
| 5166 | 5186 | ** (i.e. "main", "temp", or an attached database) containing the specified |
| 5167 | -** table or NULL. ^If it is NULL, then all attached databases are searched | |
| 5187 | +** table or NULL.)^ ^If it is NULL, then all attached databases are searched | |
| 5168 | 5188 | ** for the table using the same algorithm used by the database engine to |
| 5169 | 5189 | ** resolve unqualified table references. |
| 5170 | 5190 | ** |
| 5171 | 5191 | ** ^The third and fourth parameters to this function are the table and column |
| 5172 | -** name of the desired column, respectively. Neither of these parameters | |
| 5173 | -** may be NULL. | |
| 5192 | +** name of the desired column, respectively. | |
| 5174 | 5193 | ** |
| 5175 | 5194 | ** ^Metadata is returned by writing to the memory locations passed as the 5th |
| 5176 | 5195 | ** and subsequent parameters to this function. ^Any of these arguments may be |
| 5177 | 5196 | ** NULL, in which case the corresponding element of metadata is omitted. |
| 5178 | 5197 | ** |
| @@ -5187,36 +5206,33 @@ | ||
| 5187 | 5206 | ** <tr><td> 9th <td> int <td> True if column is [AUTOINCREMENT] |
| 5188 | 5207 | ** </table> |
| 5189 | 5208 | ** </blockquote>)^ |
| 5190 | 5209 | ** |
| 5191 | 5210 | ** ^The memory pointed to by the character pointers returned for the |
| 5192 | -** declaration type and collation sequence is valid only until the next | |
| 5211 | +** declaration type and collation sequence is valid until the next | |
| 5193 | 5212 | ** call to any SQLite API function. |
| 5194 | 5213 | ** |
| 5195 | 5214 | ** ^If the specified table is actually a view, an [error code] is returned. |
| 5196 | 5215 | ** |
| 5197 | -** ^If the specified column is "rowid", "oid" or "_rowid_" and an | |
| 5216 | +** ^If the specified column is "rowid", "oid" or "_rowid_" and the table | |
| 5217 | +** is not a [WITHOUT ROWID] table and an | |
| 5198 | 5218 | ** [INTEGER PRIMARY KEY] column has been explicitly declared, then the output |
| 5199 | 5219 | ** parameters are set for the explicitly declared column. ^(If there is no |
| 5200 | -** explicitly declared [INTEGER PRIMARY KEY] column, then the output | |
| 5201 | -** parameters are set as follows: | |
| 5220 | +** [INTEGER PRIMARY KEY] column, then the outputs | |
| 5221 | +** for the [rowid] are set as follows: | |
| 5202 | 5222 | ** |
| 5203 | 5223 | ** <pre> |
| 5204 | 5224 | ** data type: "INTEGER" |
| 5205 | 5225 | ** collation sequence: "BINARY" |
| 5206 | 5226 | ** not null: 0 |
| 5207 | 5227 | ** primary key: 1 |
| 5208 | 5228 | ** auto increment: 0 |
| 5209 | 5229 | ** </pre>)^ |
| 5210 | 5230 | ** |
| 5211 | -** ^(This function may load one or more schemas from database files. If an | |
| 5212 | -** error occurs during this process, or if the requested table or column | |
| 5213 | -** cannot be found, an [error code] is returned and an error message left | |
| 5214 | -** in the [database connection] (to be retrieved using sqlite3_errmsg()).)^ | |
| 5215 | -** | |
| 5216 | -** ^This API is only available if the library was compiled with the | |
| 5217 | -** [SQLITE_ENABLE_COLUMN_METADATA] C-preprocessor symbol defined. | |
| 5231 | +** ^This function causes all database schemas to be read from disk and | |
| 5232 | +** parsed, if that has not already been done, and returns an error if | |
| 5233 | +** any errors are encountered while loading the schema. | |
| 5218 | 5234 | */ |
| 5219 | 5235 | SQLITE_API int sqlite3_table_column_metadata( |
| 5220 | 5236 | sqlite3 *db, /* Connection handle */ |
| 5221 | 5237 | const char *zDbName, /* Database name or NULL */ |
| 5222 | 5238 | const char *zTableName, /* Table name */ |
| @@ -7179,16 +7195,14 @@ | ||
| 7179 | 7195 | |
| 7180 | 7196 | /* |
| 7181 | 7197 | ** CAPI3REF: Write-Ahead Log Commit Hook |
| 7182 | 7198 | ** |
| 7183 | 7199 | ** ^The [sqlite3_wal_hook()] function is used to register a callback that |
| 7184 | -** will be invoked each time a database connection commits data to a | |
| 7185 | -** [write-ahead log] (i.e. whenever a transaction is committed in | |
| 7186 | -** [journal_mode | journal_mode=WAL mode]). | |
| 7200 | +** is invoked each time data is committed to a database in wal mode. | |
| 7187 | 7201 | ** |
| 7188 | -** ^The callback is invoked by SQLite after the commit has taken place and | |
| 7189 | -** the associated write-lock on the database released, so the implementation | |
| 7202 | +** ^(The callback is invoked by SQLite after the commit has taken place and | |
| 7203 | +** the associated write-lock on the database released)^, so the implementation | |
| 7190 | 7204 | ** may read, write or [checkpoint] the database as required. |
| 7191 | 7205 | ** |
| 7192 | 7206 | ** ^The first parameter passed to the callback function when it is invoked |
| 7193 | 7207 | ** is a copy of the third parameter passed to sqlite3_wal_hook() when |
| 7194 | 7208 | ** registering the callback. ^The second is a copy of the database handle. |
| 7195 | 7209 |
| --- src/sqlite3.h | |
| +++ src/sqlite3.h | |
| @@ -107,11 +107,11 @@ | |
| 107 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 108 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 109 | */ |
| 110 | #define SQLITE_VERSION "3.8.8" |
| 111 | #define SQLITE_VERSION_NUMBER 3008008 |
| 112 | #define SQLITE_SOURCE_ID "2014-12-06 14:56:49 6aeece19a235344be2537e66a3fe08b1febfb5a0" |
| 113 | |
| 114 | /* |
| 115 | ** CAPI3REF: Run-Time Library Version Numbers |
| 116 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 117 | ** |
| @@ -199,11 +199,11 @@ | |
| 199 | ** This interface only reports on the compile-time mutex setting |
| 200 | ** of the [SQLITE_THREADSAFE] flag. If SQLite is compiled with |
| 201 | ** SQLITE_THREADSAFE=1 or =2 then mutexes are enabled by default but |
| 202 | ** can be fully or partially disabled using a call to [sqlite3_config()] |
| 203 | ** with the verbs [SQLITE_CONFIG_SINGLETHREAD], [SQLITE_CONFIG_MULTITHREAD], |
| 204 | ** or [SQLITE_CONFIG_MUTEX]. ^(The return value of the |
| 205 | ** sqlite3_threadsafe() function shows only the compile-time setting of |
| 206 | ** thread safety, not any run-time changes to that setting made by |
| 207 | ** sqlite3_config(). In other words, the return value from sqlite3_threadsafe() |
| 208 | ** is unchanged by calls to sqlite3_config().)^ |
| 209 | ** |
| @@ -1568,11 +1568,11 @@ | |
| 1568 | ** configuration option. |
| 1569 | ** ^There are three arguments to SQLITE_CONFIG_PAGECACHE: A pointer to |
| 1570 | ** 8-byte aligned |
| 1571 | ** memory, the size of each page buffer (sz), and the number of pages (N). |
| 1572 | ** The sz argument should be the size of the largest database page |
| 1573 | ** (a power of two between 512 and 32768) plus some extra bytes for each |
| 1574 | ** page header. ^The number of extra bytes needed by the page header |
| 1575 | ** can be determined using the [SQLITE_CONFIG_PCACHE_HDRSZ] option |
| 1576 | ** to [sqlite3_config()]. |
| 1577 | ** ^It is harmless, apart from the wasted memory, |
| 1578 | ** for the sz parameter to be larger than necessary. The first |
| @@ -1748,10 +1748,21 @@ | |
| 1748 | ** <dd>^The SQLITE_CONFIG_PCACHE_HDRSZ option takes a single parameter which |
| 1749 | ** is a pointer to an integer and writes into that integer the number of extra |
| 1750 | ** bytes per page required for each page in [SQLITE_CONFIG_PAGECACHE]. |
| 1751 | ** The amount of extra space required can change depending on the compiler, |
| 1752 | ** target platform, and SQLite version. |
| 1753 | ** </dl> |
| 1754 | */ |
| 1755 | #define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */ |
| 1756 | #define SQLITE_CONFIG_MULTITHREAD 2 /* nil */ |
| 1757 | #define SQLITE_CONFIG_SERIALIZED 3 /* nil */ |
| @@ -1774,10 +1785,11 @@ | |
| 1774 | #define SQLITE_CONFIG_COVERING_INDEX_SCAN 20 /* int */ |
| 1775 | #define SQLITE_CONFIG_SQLLOG 21 /* xSqllog, void* */ |
| 1776 | #define SQLITE_CONFIG_MMAP_SIZE 22 /* sqlite3_int64, sqlite3_int64 */ |
| 1777 | #define SQLITE_CONFIG_WIN32_HEAPSIZE 23 /* int nByte */ |
| 1778 | #define SQLITE_CONFIG_PCACHE_HDRSZ 24 /* int *psz */ |
| 1779 | |
| 1780 | /* |
| 1781 | ** CAPI3REF: Database Connection Configuration Options |
| 1782 | ** |
| 1783 | ** These constants are the available integer configuration options that |
| @@ -5155,24 +5167,31 @@ | |
| 5155 | |
| 5156 | |
| 5157 | /* |
| 5158 | ** CAPI3REF: Extract Metadata About A Column Of A Table |
| 5159 | ** |
| 5160 | ** ^This routine returns metadata about a specific column of a specific |
| 5161 | ** database table accessible using the [database connection] handle |
| 5162 | ** passed as the first function argument. |
| 5163 | ** |
| 5164 | ** ^The column is identified by the second, third and fourth parameters to |
| 5165 | ** this function. ^The second parameter is either the name of the database |
| 5166 | ** (i.e. "main", "temp", or an attached database) containing the specified |
| 5167 | ** table or NULL. ^If it is NULL, then all attached databases are searched |
| 5168 | ** for the table using the same algorithm used by the database engine to |
| 5169 | ** resolve unqualified table references. |
| 5170 | ** |
| 5171 | ** ^The third and fourth parameters to this function are the table and column |
| 5172 | ** name of the desired column, respectively. Neither of these parameters |
| 5173 | ** may be NULL. |
| 5174 | ** |
| 5175 | ** ^Metadata is returned by writing to the memory locations passed as the 5th |
| 5176 | ** and subsequent parameters to this function. ^Any of these arguments may be |
| 5177 | ** NULL, in which case the corresponding element of metadata is omitted. |
| 5178 | ** |
| @@ -5187,36 +5206,33 @@ | |
| 5187 | ** <tr><td> 9th <td> int <td> True if column is [AUTOINCREMENT] |
| 5188 | ** </table> |
| 5189 | ** </blockquote>)^ |
| 5190 | ** |
| 5191 | ** ^The memory pointed to by the character pointers returned for the |
| 5192 | ** declaration type and collation sequence is valid only until the next |
| 5193 | ** call to any SQLite API function. |
| 5194 | ** |
| 5195 | ** ^If the specified table is actually a view, an [error code] is returned. |
| 5196 | ** |
| 5197 | ** ^If the specified column is "rowid", "oid" or "_rowid_" and an |
| 5198 | ** [INTEGER PRIMARY KEY] column has been explicitly declared, then the output |
| 5199 | ** parameters are set for the explicitly declared column. ^(If there is no |
| 5200 | ** explicitly declared [INTEGER PRIMARY KEY] column, then the output |
| 5201 | ** parameters are set as follows: |
| 5202 | ** |
| 5203 | ** <pre> |
| 5204 | ** data type: "INTEGER" |
| 5205 | ** collation sequence: "BINARY" |
| 5206 | ** not null: 0 |
| 5207 | ** primary key: 1 |
| 5208 | ** auto increment: 0 |
| 5209 | ** </pre>)^ |
| 5210 | ** |
| 5211 | ** ^(This function may load one or more schemas from database files. If an |
| 5212 | ** error occurs during this process, or if the requested table or column |
| 5213 | ** cannot be found, an [error code] is returned and an error message left |
| 5214 | ** in the [database connection] (to be retrieved using sqlite3_errmsg()).)^ |
| 5215 | ** |
| 5216 | ** ^This API is only available if the library was compiled with the |
| 5217 | ** [SQLITE_ENABLE_COLUMN_METADATA] C-preprocessor symbol defined. |
| 5218 | */ |
| 5219 | SQLITE_API int sqlite3_table_column_metadata( |
| 5220 | sqlite3 *db, /* Connection handle */ |
| 5221 | const char *zDbName, /* Database name or NULL */ |
| 5222 | const char *zTableName, /* Table name */ |
| @@ -7179,16 +7195,14 @@ | |
| 7179 | |
| 7180 | /* |
| 7181 | ** CAPI3REF: Write-Ahead Log Commit Hook |
| 7182 | ** |
| 7183 | ** ^The [sqlite3_wal_hook()] function is used to register a callback that |
| 7184 | ** will be invoked each time a database connection commits data to a |
| 7185 | ** [write-ahead log] (i.e. whenever a transaction is committed in |
| 7186 | ** [journal_mode | journal_mode=WAL mode]). |
| 7187 | ** |
| 7188 | ** ^The callback is invoked by SQLite after the commit has taken place and |
| 7189 | ** the associated write-lock on the database released, so the implementation |
| 7190 | ** may read, write or [checkpoint] the database as required. |
| 7191 | ** |
| 7192 | ** ^The first parameter passed to the callback function when it is invoked |
| 7193 | ** is a copy of the third parameter passed to sqlite3_wal_hook() when |
| 7194 | ** registering the callback. ^The second is a copy of the database handle. |
| 7195 |
| --- src/sqlite3.h | |
| +++ src/sqlite3.h | |
| @@ -107,11 +107,11 @@ | |
| 107 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 108 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 109 | */ |
| 110 | #define SQLITE_VERSION "3.8.8" |
| 111 | #define SQLITE_VERSION_NUMBER 3008008 |
| 112 | #define SQLITE_SOURCE_ID "2015-01-03 18:59:17 23d4c07eb81db5a5c6beb56b5820f0b6501f1fb6" |
| 113 | |
| 114 | /* |
| 115 | ** CAPI3REF: Run-Time Library Version Numbers |
| 116 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 117 | ** |
| @@ -199,11 +199,11 @@ | |
| 199 | ** This interface only reports on the compile-time mutex setting |
| 200 | ** of the [SQLITE_THREADSAFE] flag. If SQLite is compiled with |
| 201 | ** SQLITE_THREADSAFE=1 or =2 then mutexes are enabled by default but |
| 202 | ** can be fully or partially disabled using a call to [sqlite3_config()] |
| 203 | ** with the verbs [SQLITE_CONFIG_SINGLETHREAD], [SQLITE_CONFIG_MULTITHREAD], |
| 204 | ** or [SQLITE_CONFIG_SERIALIZED]. ^(The return value of the |
| 205 | ** sqlite3_threadsafe() function shows only the compile-time setting of |
| 206 | ** thread safety, not any run-time changes to that setting made by |
| 207 | ** sqlite3_config(). In other words, the return value from sqlite3_threadsafe() |
| 208 | ** is unchanged by calls to sqlite3_config().)^ |
| 209 | ** |
| @@ -1568,11 +1568,11 @@ | |
| 1568 | ** configuration option. |
| 1569 | ** ^There are three arguments to SQLITE_CONFIG_PAGECACHE: A pointer to |
| 1570 | ** 8-byte aligned |
| 1571 | ** memory, the size of each page buffer (sz), and the number of pages (N). |
| 1572 | ** The sz argument should be the size of the largest database page |
| 1573 | ** (a power of two between 512 and 65536) plus some extra bytes for each |
| 1574 | ** page header. ^The number of extra bytes needed by the page header |
| 1575 | ** can be determined using the [SQLITE_CONFIG_PCACHE_HDRSZ] option |
| 1576 | ** to [sqlite3_config()]. |
| 1577 | ** ^It is harmless, apart from the wasted memory, |
| 1578 | ** for the sz parameter to be larger than necessary. The first |
| @@ -1748,10 +1748,21 @@ | |
| 1748 | ** <dd>^The SQLITE_CONFIG_PCACHE_HDRSZ option takes a single parameter which |
| 1749 | ** is a pointer to an integer and writes into that integer the number of extra |
| 1750 | ** bytes per page required for each page in [SQLITE_CONFIG_PAGECACHE]. |
| 1751 | ** The amount of extra space required can change depending on the compiler, |
| 1752 | ** target platform, and SQLite version. |
| 1753 | ** |
| 1754 | ** [[SQLITE_CONFIG_PMASZ]] |
| 1755 | ** <dt>SQLITE_CONFIG_PMASZ |
| 1756 | ** <dd>^The SQLITE_CONFIG_PMASZ option takes a single parameter which |
| 1757 | ** is an unsigned integer and sets the "Minimum PMA Size" for the multithreaded |
| 1758 | ** sorter to that integer. The default minimum PMA Size is set by the |
| 1759 | ** [SQLITE_SORTER_PMASZ] compile-time option. New threads are launched |
| 1760 | ** to help with sort operations when multithreaded sorting |
| 1761 | ** is enabled (using the [PRAGMA threads] command) and the amount of content |
| 1762 | ** to be sorted exceeds the page size times the minimum of the |
| 1763 | ** [PRAGMA cache_size] setting and this value. |
| 1764 | ** </dl> |
| 1765 | */ |
| 1766 | #define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */ |
| 1767 | #define SQLITE_CONFIG_MULTITHREAD 2 /* nil */ |
| 1768 | #define SQLITE_CONFIG_SERIALIZED 3 /* nil */ |
| @@ -1774,10 +1785,11 @@ | |
| 1785 | #define SQLITE_CONFIG_COVERING_INDEX_SCAN 20 /* int */ |
| 1786 | #define SQLITE_CONFIG_SQLLOG 21 /* xSqllog, void* */ |
| 1787 | #define SQLITE_CONFIG_MMAP_SIZE 22 /* sqlite3_int64, sqlite3_int64 */ |
| 1788 | #define SQLITE_CONFIG_WIN32_HEAPSIZE 23 /* int nByte */ |
| 1789 | #define SQLITE_CONFIG_PCACHE_HDRSZ 24 /* int *psz */ |
| 1790 | #define SQLITE_CONFIG_PMASZ 25 /* unsigned int szPma */ |
| 1791 | |
| 1792 | /* |
| 1793 | ** CAPI3REF: Database Connection Configuration Options |
| 1794 | ** |
| 1795 | ** These constants are the available integer configuration options that |
| @@ -5155,24 +5167,31 @@ | |
| 5167 | |
| 5168 | |
| 5169 | /* |
| 5170 | ** CAPI3REF: Extract Metadata About A Column Of A Table |
| 5171 | ** |
| 5172 | ** ^(The sqlite3_table_column_metadata(X,D,T,C,....) routine returns |
| 5173 | ** information about column C of table T in database D |
| 5174 | ** on [database connection] X.)^ ^The sqlite3_table_column_metadata() |
| 5175 | ** interface returns SQLITE_OK and fills in the non-NULL pointers in |
| 5176 | ** the final five arguments with appropriate values if the specified |
| 5177 | ** column exists. ^The sqlite3_table_column_metadata() interface returns |
| 5178 | ** SQLITE_ERROR and if the specified column does not exist. |
| 5179 | ** ^If the column-name parameter to sqlite3_table_column_metadata() is a |
| 5180 | ** NULL pointer, then this routine simply checks for the existance of the |
| 5181 | ** table and returns SQLITE_OK if the table exists and SQLITE_ERROR if it |
| 5182 | ** does not. |
| 5183 | ** |
| 5184 | ** ^The column is identified by the second, third and fourth parameters to |
| 5185 | ** this function. ^(The second parameter is either the name of the database |
| 5186 | ** (i.e. "main", "temp", or an attached database) containing the specified |
| 5187 | ** table or NULL.)^ ^If it is NULL, then all attached databases are searched |
| 5188 | ** for the table using the same algorithm used by the database engine to |
| 5189 | ** resolve unqualified table references. |
| 5190 | ** |
| 5191 | ** ^The third and fourth parameters to this function are the table and column |
| 5192 | ** name of the desired column, respectively. |
| 5193 | ** |
| 5194 | ** ^Metadata is returned by writing to the memory locations passed as the 5th |
| 5195 | ** and subsequent parameters to this function. ^Any of these arguments may be |
| 5196 | ** NULL, in which case the corresponding element of metadata is omitted. |
| 5197 | ** |
| @@ -5187,36 +5206,33 @@ | |
| 5206 | ** <tr><td> 9th <td> int <td> True if column is [AUTOINCREMENT] |
| 5207 | ** </table> |
| 5208 | ** </blockquote>)^ |
| 5209 | ** |
| 5210 | ** ^The memory pointed to by the character pointers returned for the |
| 5211 | ** declaration type and collation sequence is valid until the next |
| 5212 | ** call to any SQLite API function. |
| 5213 | ** |
| 5214 | ** ^If the specified table is actually a view, an [error code] is returned. |
| 5215 | ** |
| 5216 | ** ^If the specified column is "rowid", "oid" or "_rowid_" and the table |
| 5217 | ** is not a [WITHOUT ROWID] table and an |
| 5218 | ** [INTEGER PRIMARY KEY] column has been explicitly declared, then the output |
| 5219 | ** parameters are set for the explicitly declared column. ^(If there is no |
| 5220 | ** [INTEGER PRIMARY KEY] column, then the outputs |
| 5221 | ** for the [rowid] are set as follows: |
| 5222 | ** |
| 5223 | ** <pre> |
| 5224 | ** data type: "INTEGER" |
| 5225 | ** collation sequence: "BINARY" |
| 5226 | ** not null: 0 |
| 5227 | ** primary key: 1 |
| 5228 | ** auto increment: 0 |
| 5229 | ** </pre>)^ |
| 5230 | ** |
| 5231 | ** ^This function causes all database schemas to be read from disk and |
| 5232 | ** parsed, if that has not already been done, and returns an error if |
| 5233 | ** any errors are encountered while loading the schema. |
| 5234 | */ |
| 5235 | SQLITE_API int sqlite3_table_column_metadata( |
| 5236 | sqlite3 *db, /* Connection handle */ |
| 5237 | const char *zDbName, /* Database name or NULL */ |
| 5238 | const char *zTableName, /* Table name */ |
| @@ -7179,16 +7195,14 @@ | |
| 7195 | |
| 7196 | /* |
| 7197 | ** CAPI3REF: Write-Ahead Log Commit Hook |
| 7198 | ** |
| 7199 | ** ^The [sqlite3_wal_hook()] function is used to register a callback that |
| 7200 | ** is invoked each time data is committed to a database in wal mode. |
| 7201 | ** |
| 7202 | ** ^(The callback is invoked by SQLite after the commit has taken place and |
| 7203 | ** the associated write-lock on the database released)^, so the implementation |
| 7204 | ** may read, write or [checkpoint] the database as required. |
| 7205 | ** |
| 7206 | ** ^The first parameter passed to the callback function when it is invoked |
| 7207 | ** is a copy of the third parameter passed to sqlite3_wal_hook() when |
| 7208 | ** registering the callback. ^The second is a copy of the database handle. |
| 7209 |
+1
-1
| --- src/stat.c | ||
| +++ src/stat.c | ||
| @@ -77,11 +77,11 @@ | ||
| 77 | 77 | if( n>0 ){ |
| 78 | 78 | int a, b; |
| 79 | 79 | Stmt q; |
| 80 | 80 | @ <tr><th>Uncompressed Artifact Size:</th><td> |
| 81 | 81 | db_prepare(&q, "SELECT total(size), avg(size), max(size)" |
| 82 | - " FROM blob WHERE size>0"); | |
| 82 | + " FROM blob WHERE size>0 /*scan*/"); | |
| 83 | 83 | db_step(&q); |
| 84 | 84 | t = db_column_int64(&q, 0); |
| 85 | 85 | szAvg = db_column_int(&q, 1); |
| 86 | 86 | szMax = db_column_int(&q, 2); |
| 87 | 87 | db_finalize(&q); |
| 88 | 88 |
| --- src/stat.c | |
| +++ src/stat.c | |
| @@ -77,11 +77,11 @@ | |
| 77 | if( n>0 ){ |
| 78 | int a, b; |
| 79 | Stmt q; |
| 80 | @ <tr><th>Uncompressed Artifact Size:</th><td> |
| 81 | db_prepare(&q, "SELECT total(size), avg(size), max(size)" |
| 82 | " FROM blob WHERE size>0"); |
| 83 | db_step(&q); |
| 84 | t = db_column_int64(&q, 0); |
| 85 | szAvg = db_column_int(&q, 1); |
| 86 | szMax = db_column_int(&q, 2); |
| 87 | db_finalize(&q); |
| 88 |
| --- src/stat.c | |
| +++ src/stat.c | |
| @@ -77,11 +77,11 @@ | |
| 77 | if( n>0 ){ |
| 78 | int a, b; |
| 79 | Stmt q; |
| 80 | @ <tr><th>Uncompressed Artifact Size:</th><td> |
| 81 | db_prepare(&q, "SELECT total(size), avg(size), max(size)" |
| 82 | " FROM blob WHERE size>0 /*scan*/"); |
| 83 | db_step(&q); |
| 84 | t = db_column_int64(&q, 0); |
| 85 | szAvg = db_column_int(&q, 1); |
| 86 | szMax = db_column_int(&q, 2); |
| 87 | db_finalize(&q); |
| 88 |
+79
-4
| --- src/style.c | ||
| +++ src/style.c | ||
| @@ -783,10 +783,15 @@ | ||
| 783 | 783 | { ".filetree", |
| 784 | 784 | "tree-view file browser", |
| 785 | 785 | @ margin: 1em 0; |
| 786 | 786 | @ line-height: 1.5; |
| 787 | 787 | }, |
| 788 | + { | |
| 789 | + ".filetree > ul", | |
| 790 | + "tree-view top-level list", | |
| 791 | + @ display: inline-block; | |
| 792 | + }, | |
| 788 | 793 | { ".filetree ul", |
| 789 | 794 | "tree-view lists", |
| 790 | 795 | @ margin: 0; |
| 791 | 796 | @ padding: 0; |
| 792 | 797 | @ list-style: none; |
| @@ -832,21 +837,37 @@ | ||
| 832 | 837 | }, |
| 833 | 838 | { ".filetree a", |
| 834 | 839 | "tree-view links", |
| 835 | 840 | @ position: relative; |
| 836 | 841 | @ z-index: 1; |
| 837 | - @ display: inline-block; | |
| 842 | + @ display: table-cell; | |
| 838 | 843 | @ min-height: 16px; |
| 839 | 844 | @ padding-left: 21px; |
| 840 | 845 | @ background-image: url(data:image/gif;base64,R0lGODlhEAAQAJEAAP\/\/\/yEhIf\/\/\/wAAACH5BAEHAAIALAAAAAAQABAAAAIvlIKpxqcfmgOUvoaqDSCxrEEfF14GqFXImJZsu73wepJzVMNxrtNTj3NATMKhpwAAOw==); |
| 841 | 846 | @ background-position: center left; |
| 842 | 847 | @ background-repeat: no-repeat; |
| 843 | 848 | }, |
| 844 | - { ".filetree .dir > a", | |
| 849 | + { "div.filetreeline", | |
| 850 | + "line of a file tree", | |
| 851 | + @ display: table; | |
| 852 | + @ width: 100%; | |
| 853 | + @ white-space: nowrap; | |
| 854 | + }, | |
| 855 | + { ".filetree .dir > div.filetreeline > a", | |
| 845 | 856 | "tree-view directory links", |
| 846 | 857 | @ background-image: url(data:image/gif;base64,R0lGODlhEAAQAJEAAP/WVCIiIv\/\/\/wAAACH5BAEHAAIALAAAAAAQABAAAAInlI9pwa3XYniCgQtkrAFfLXkiFo1jaXpo+jUs6b5Z/K4siDu5RPUFADs=); |
| 847 | 858 | }, |
| 859 | + { "div.filetreeage", | |
| 860 | + "Last change floating display on the right", | |
| 861 | + @ display: table-cell; | |
| 862 | + @ padding-left: 3em; | |
| 863 | + @ text-align: right; | |
| 864 | + }, | |
| 865 | + { "div.filetreeline:hover", | |
| 866 | + "Highlight the line of a file tree", | |
| 867 | + @ background-color: #eee; | |
| 868 | + }, | |
| 848 | 869 | { "table.login_out", |
| 849 | 870 | "table format for login/out label/input table", |
| 850 | 871 | @ text-align: left; |
| 851 | 872 | @ margin-right: 10px; |
| 852 | 873 | @ margin-left: 10px; |
| @@ -1211,17 +1232,71 @@ | ||
| 1211 | 1232 | @ color: black; |
| 1212 | 1233 | @ background-color: white; |
| 1213 | 1234 | }, |
| 1214 | 1235 | { "table.adminLogTable", |
| 1215 | 1236 | "Class for the /admin_log table", |
| 1216 | - @ text-align: left | |
| 1237 | + @ text-align: left; | |
| 1217 | 1238 | }, |
| 1218 | 1239 | { ".adminLogTable .adminTime", |
| 1219 | 1240 | "Class for the /admin_log table", |
| 1220 | - @ text-align: left | |
| 1241 | + @ text-align: left; | |
| 1242 | + @ vertical-align: top; | |
| 1243 | + @ white-space: nowrap; | |
| 1244 | + }, | |
| 1245 | + { ".fileage table", | |
| 1246 | + "The fileage table", | |
| 1247 | + @ border-spacing: 0; | |
| 1248 | + }, | |
| 1249 | + { ".fileage tr:hover", | |
| 1250 | + "Mouse-over effects for the file-age table", | |
| 1251 | + @ background-color: #eee; | |
| 1252 | + }, | |
| 1253 | + { ".fileage td", | |
| 1254 | + "fileage table cells", | |
| 1221 | 1255 | @ vertical-align: top; |
| 1256 | + @ text-align: left; | |
| 1257 | + @ border-top: 1px solid #ddd; | |
| 1258 | + @ padding-top: 3px; | |
| 1259 | + }, | |
| 1260 | + { ".fileage td:first-child", | |
| 1261 | + "fileage first column (the age)", | |
| 1222 | 1262 | @ white-space: nowrap; |
| 1263 | + }, | |
| 1264 | + { ".fileage td:nth-child(2)", | |
| 1265 | + "fileage second column (the filename)", | |
| 1266 | + @ padding-left: 1em; | |
| 1267 | + @ padding-right: 1em; | |
| 1268 | + }, | |
| 1269 | + { ".fileage td:nth-child(3)", | |
| 1270 | + "fileage third column (the check-in comment)", | |
| 1271 | + @ word-break: break-all; | |
| 1272 | + @ word-wrap: break-word; | |
| 1273 | + @ max-width: 50%; | |
| 1274 | + }, | |
| 1275 | + { ".brlist table", "The list of branches", | |
| 1276 | + @ border-spacing: 0; | |
| 1277 | + }, | |
| 1278 | + { ".brlist table th", "Branch list table headers", | |
| 1279 | + @ text-align: left; | |
| 1280 | + @ padding: 0px 1em 0.5ex 0px; | |
| 1281 | + }, | |
| 1282 | + { ".brlist table td", "Branch list table headers", | |
| 1283 | + @ padding: 0px 2em 0px 0px; | |
| 1284 | + }, | |
| 1285 | + { "th.sort:after", | |
| 1286 | + "General styles for sortable column marker", | |
| 1287 | + @ margin-left: .4em; | |
| 1288 | + @ cursor: pointer; | |
| 1289 | + @ text-shadow: 0 0 0 #000; /* Makes arrow darker */ | |
| 1290 | + }, | |
| 1291 | + { "th.sort.asc:after", | |
| 1292 | + "Ascending sort column marker", | |
| 1293 | + @ content: '\2193'; | |
| 1294 | + }, | |
| 1295 | + { "th.sort.desc:after", | |
| 1296 | + "Descending sort column marker", | |
| 1297 | + @ content: '\2191'; | |
| 1223 | 1298 | }, |
| 1224 | 1299 | { 0, |
| 1225 | 1300 | 0, |
| 1226 | 1301 | 0 |
| 1227 | 1302 | } |
| 1228 | 1303 |
| --- src/style.c | |
| +++ src/style.c | |
| @@ -783,10 +783,15 @@ | |
| 783 | { ".filetree", |
| 784 | "tree-view file browser", |
| 785 | @ margin: 1em 0; |
| 786 | @ line-height: 1.5; |
| 787 | }, |
| 788 | { ".filetree ul", |
| 789 | "tree-view lists", |
| 790 | @ margin: 0; |
| 791 | @ padding: 0; |
| 792 | @ list-style: none; |
| @@ -832,21 +837,37 @@ | |
| 832 | }, |
| 833 | { ".filetree a", |
| 834 | "tree-view links", |
| 835 | @ position: relative; |
| 836 | @ z-index: 1; |
| 837 | @ display: inline-block; |
| 838 | @ min-height: 16px; |
| 839 | @ padding-left: 21px; |
| 840 | @ background-image: url(data:image/gif;base64,R0lGODlhEAAQAJEAAP\/\/\/yEhIf\/\/\/wAAACH5BAEHAAIALAAAAAAQABAAAAIvlIKpxqcfmgOUvoaqDSCxrEEfF14GqFXImJZsu73wepJzVMNxrtNTj3NATMKhpwAAOw==); |
| 841 | @ background-position: center left; |
| 842 | @ background-repeat: no-repeat; |
| 843 | }, |
| 844 | { ".filetree .dir > a", |
| 845 | "tree-view directory links", |
| 846 | @ background-image: url(data:image/gif;base64,R0lGODlhEAAQAJEAAP/WVCIiIv\/\/\/wAAACH5BAEHAAIALAAAAAAQABAAAAInlI9pwa3XYniCgQtkrAFfLXkiFo1jaXpo+jUs6b5Z/K4siDu5RPUFADs=); |
| 847 | }, |
| 848 | { "table.login_out", |
| 849 | "table format for login/out label/input table", |
| 850 | @ text-align: left; |
| 851 | @ margin-right: 10px; |
| 852 | @ margin-left: 10px; |
| @@ -1211,17 +1232,71 @@ | |
| 1211 | @ color: black; |
| 1212 | @ background-color: white; |
| 1213 | }, |
| 1214 | { "table.adminLogTable", |
| 1215 | "Class for the /admin_log table", |
| 1216 | @ text-align: left |
| 1217 | }, |
| 1218 | { ".adminLogTable .adminTime", |
| 1219 | "Class for the /admin_log table", |
| 1220 | @ text-align: left |
| 1221 | @ vertical-align: top; |
| 1222 | @ white-space: nowrap; |
| 1223 | }, |
| 1224 | { 0, |
| 1225 | 0, |
| 1226 | 0 |
| 1227 | } |
| 1228 |
| --- src/style.c | |
| +++ src/style.c | |
| @@ -783,10 +783,15 @@ | |
| 783 | { ".filetree", |
| 784 | "tree-view file browser", |
| 785 | @ margin: 1em 0; |
| 786 | @ line-height: 1.5; |
| 787 | }, |
| 788 | { |
| 789 | ".filetree > ul", |
| 790 | "tree-view top-level list", |
| 791 | @ display: inline-block; |
| 792 | }, |
| 793 | { ".filetree ul", |
| 794 | "tree-view lists", |
| 795 | @ margin: 0; |
| 796 | @ padding: 0; |
| 797 | @ list-style: none; |
| @@ -832,21 +837,37 @@ | |
| 837 | }, |
| 838 | { ".filetree a", |
| 839 | "tree-view links", |
| 840 | @ position: relative; |
| 841 | @ z-index: 1; |
| 842 | @ display: table-cell; |
| 843 | @ min-height: 16px; |
| 844 | @ padding-left: 21px; |
| 845 | @ background-image: url(data:image/gif;base64,R0lGODlhEAAQAJEAAP\/\/\/yEhIf\/\/\/wAAACH5BAEHAAIALAAAAAAQABAAAAIvlIKpxqcfmgOUvoaqDSCxrEEfF14GqFXImJZsu73wepJzVMNxrtNTj3NATMKhpwAAOw==); |
| 846 | @ background-position: center left; |
| 847 | @ background-repeat: no-repeat; |
| 848 | }, |
| 849 | { "div.filetreeline", |
| 850 | "line of a file tree", |
| 851 | @ display: table; |
| 852 | @ width: 100%; |
| 853 | @ white-space: nowrap; |
| 854 | }, |
| 855 | { ".filetree .dir > div.filetreeline > a", |
| 856 | "tree-view directory links", |
| 857 | @ background-image: url(data:image/gif;base64,R0lGODlhEAAQAJEAAP/WVCIiIv\/\/\/wAAACH5BAEHAAIALAAAAAAQABAAAAInlI9pwa3XYniCgQtkrAFfLXkiFo1jaXpo+jUs6b5Z/K4siDu5RPUFADs=); |
| 858 | }, |
| 859 | { "div.filetreeage", |
| 860 | "Last change floating display on the right", |
| 861 | @ display: table-cell; |
| 862 | @ padding-left: 3em; |
| 863 | @ text-align: right; |
| 864 | }, |
| 865 | { "div.filetreeline:hover", |
| 866 | "Highlight the line of a file tree", |
| 867 | @ background-color: #eee; |
| 868 | }, |
| 869 | { "table.login_out", |
| 870 | "table format for login/out label/input table", |
| 871 | @ text-align: left; |
| 872 | @ margin-right: 10px; |
| 873 | @ margin-left: 10px; |
| @@ -1211,17 +1232,71 @@ | |
| 1232 | @ color: black; |
| 1233 | @ background-color: white; |
| 1234 | }, |
| 1235 | { "table.adminLogTable", |
| 1236 | "Class for the /admin_log table", |
| 1237 | @ text-align: left; |
| 1238 | }, |
| 1239 | { ".adminLogTable .adminTime", |
| 1240 | "Class for the /admin_log table", |
| 1241 | @ text-align: left; |
| 1242 | @ vertical-align: top; |
| 1243 | @ white-space: nowrap; |
| 1244 | }, |
| 1245 | { ".fileage table", |
| 1246 | "The fileage table", |
| 1247 | @ border-spacing: 0; |
| 1248 | }, |
| 1249 | { ".fileage tr:hover", |
| 1250 | "Mouse-over effects for the file-age table", |
| 1251 | @ background-color: #eee; |
| 1252 | }, |
| 1253 | { ".fileage td", |
| 1254 | "fileage table cells", |
| 1255 | @ vertical-align: top; |
| 1256 | @ text-align: left; |
| 1257 | @ border-top: 1px solid #ddd; |
| 1258 | @ padding-top: 3px; |
| 1259 | }, |
| 1260 | { ".fileage td:first-child", |
| 1261 | "fileage first column (the age)", |
| 1262 | @ white-space: nowrap; |
| 1263 | }, |
| 1264 | { ".fileage td:nth-child(2)", |
| 1265 | "fileage second column (the filename)", |
| 1266 | @ padding-left: 1em; |
| 1267 | @ padding-right: 1em; |
| 1268 | }, |
| 1269 | { ".fileage td:nth-child(3)", |
| 1270 | "fileage third column (the check-in comment)", |
| 1271 | @ word-break: break-all; |
| 1272 | @ word-wrap: break-word; |
| 1273 | @ max-width: 50%; |
| 1274 | }, |
| 1275 | { ".brlist table", "The list of branches", |
| 1276 | @ border-spacing: 0; |
| 1277 | }, |
| 1278 | { ".brlist table th", "Branch list table headers", |
| 1279 | @ text-align: left; |
| 1280 | @ padding: 0px 1em 0.5ex 0px; |
| 1281 | }, |
| 1282 | { ".brlist table td", "Branch list table headers", |
| 1283 | @ padding: 0px 2em 0px 0px; |
| 1284 | }, |
| 1285 | { "th.sort:after", |
| 1286 | "General styles for sortable column marker", |
| 1287 | @ margin-left: .4em; |
| 1288 | @ cursor: pointer; |
| 1289 | @ text-shadow: 0 0 0 #000; /* Makes arrow darker */ |
| 1290 | }, |
| 1291 | { "th.sort.asc:after", |
| 1292 | "Ascending sort column marker", |
| 1293 | @ content: '\2193'; |
| 1294 | }, |
| 1295 | { "th.sort.desc:after", |
| 1296 | "Descending sort column marker", |
| 1297 | @ content: '\2191'; |
| 1298 | }, |
| 1299 | { 0, |
| 1300 | 0, |
| 1301 | 0 |
| 1302 | } |
| 1303 |
+18
-12
| --- src/timeline.c | ||
| +++ src/timeline.c | ||
| @@ -87,10 +87,11 @@ | ||
| 87 | 87 | #define TIMELINE_FCHANGES 0x0020 /* Detail file changes */ |
| 88 | 88 | #define TIMELINE_BRCOLOR 0x0040 /* Background color by branch name */ |
| 89 | 89 | #define TIMELINE_UCOLOR 0x0080 /* Background color by user */ |
| 90 | 90 | #define TIMELINE_FRENAMES 0x0100 /* Detail only file name changes */ |
| 91 | 91 | #define TIMELINE_UNHIDE 0x0200 /* Unhide check-ins with "hidden" tag */ |
| 92 | +#define TIMELINE_SHOWRID 0x0400 /* Show RID values in addition to UUIDs */ | |
| 92 | 93 | #endif |
| 93 | 94 | |
| 94 | 95 | /* |
| 95 | 96 | ** Hash a string and use the hash to determine a background color. |
| 96 | 97 | */ |
| @@ -404,10 +405,13 @@ | ||
| 404 | 405 | } |
| 405 | 406 | }else if( zType[0]=='e' && tagid ){ |
| 406 | 407 | hyperlink_to_event_tagid(tagid<0?-tagid:tagid); |
| 407 | 408 | }else if( (tmFlags & TIMELINE_ARTID)!=0 ){ |
| 408 | 409 | hyperlink_to_uuid(zUuid); |
| 410 | + } | |
| 411 | + if( tmFlags & TIMELINE_SHOWRID ){ | |
| 412 | + @ (%d(rid)) | |
| 409 | 413 | } |
| 410 | 414 | db_column_blob(pQuery, commentColumn, &comment); |
| 411 | 415 | if( zType[0]!='c' ){ |
| 412 | 416 | /* Comments for anything other than a check-in are generated by |
| 413 | 417 | ** "fossil rebuild" and expect to be rendered as text/x-fossil-wiki */ |
| @@ -604,12 +608,12 @@ | ||
| 604 | 608 | ** for the upward portion of a merge arrow. The merge arrow goes up |
| 605 | 609 | ** to the row identified by mu:. If this value is zero then |
| 606 | 610 | ** node has no merge children and no merge-out line is drawn. |
| 607 | 611 | ** mu: The id of the row which is the top of the merge-out arrow. |
| 608 | 612 | ** u: Draw a thick child-line out of the top of this node and up to |
| 609 | - ** the node with an id equal to this value. 0 if there is no | |
| 610 | - ** thick-line riser. | |
| 613 | + ** the node with an id equal to this value. 0 if it is straight to | |
| 614 | + ** the top of the page, -1 if there is no thick-line riser. | |
| 611 | 615 | ** f: 0x01: a leaf node. |
| 612 | 616 | ** au: An array of integers that define thick-line risers for branches. |
| 613 | 617 | ** The integers are in pairs. For each pair, the first integer is |
| 614 | 618 | ** is the rail on which the riser should run and the second integer |
| 615 | 619 | ** is the id of the node upto which the riser should run. |
| @@ -1070,11 +1074,11 @@ | ||
| 1070 | 1074 | const char *zYearMonth = P("ym"); /* Show checkins for the given YYYY-MM */ |
| 1071 | 1075 | const char *zYearWeek = P("yw"); /* Show checkins for the given YYYY-WW (week-of-year)*/ |
| 1072 | 1076 | int useDividers = P("nd")==0; /* Show dividers if "nd" is missing */ |
| 1073 | 1077 | int renameOnly = P("namechng")!=0; /* Show only checkins that rename files */ |
| 1074 | 1078 | int tagid; /* Tag ID */ |
| 1075 | - int tmFlags; /* Timeline flags */ | |
| 1079 | + int tmFlags = 0; /* Timeline flags */ | |
| 1076 | 1080 | const char *zThisTag = 0; /* Suppress links to this tag */ |
| 1077 | 1081 | const char *zThisUser = 0; /* Suppress links to this user */ |
| 1078 | 1082 | HQuery url; /* URL for various branch links */ |
| 1079 | 1083 | int from_rid = name_to_typed_rid(P("from"),"ci"); /* from= for paths */ |
| 1080 | 1084 | int to_rid = name_to_typed_rid(P("to"),"ci"); /* to= for path timelines */ |
| @@ -1110,13 +1114,13 @@ | ||
| 1110 | 1114 | ){ |
| 1111 | 1115 | zCirca = zBefore = zAfter = 0; |
| 1112 | 1116 | nEntry = -1; |
| 1113 | 1117 | } |
| 1114 | 1118 | if( zType[0]=='a' ){ |
| 1115 | - tmFlags = TIMELINE_BRIEF | TIMELINE_GRAPH; | |
| 1119 | + tmFlags |= TIMELINE_BRIEF | TIMELINE_GRAPH; | |
| 1116 | 1120 | }else{ |
| 1117 | - tmFlags = TIMELINE_GRAPH; | |
| 1121 | + tmFlags |= TIMELINE_GRAPH; | |
| 1118 | 1122 | } |
| 1119 | 1123 | if( nEntry>0 ) url_add_parameter(&url, "n", mprintf("%d", nEntry)); |
| 1120 | 1124 | if( P("ng")!=0 || zSearch!=0 ){ |
| 1121 | 1125 | tmFlags &= ~TIMELINE_GRAPH; |
| 1122 | 1126 | url_add_parameter(&url, "ng", 0); |
| @@ -1206,10 +1210,11 @@ | ||
| 1206 | 1210 | }else if( (p_rid || d_rid) && g.perm.Read ){ |
| 1207 | 1211 | /* If p= or d= is present, ignore all other parameters other than n= */ |
| 1208 | 1212 | char *zUuid; |
| 1209 | 1213 | int np, nd; |
| 1210 | 1214 | |
| 1215 | + tmFlags |= TIMELINE_DISJOINT; | |
| 1211 | 1216 | if( p_rid && d_rid ){ |
| 1212 | 1217 | if( p_rid!=d_rid ) p_rid = d_rid; |
| 1213 | 1218 | if( P("n")==0 ) nEntry = 10; |
| 1214 | 1219 | } |
| 1215 | 1220 | db_multi_exec( |
| @@ -1460,11 +1465,11 @@ | ||
| 1460 | 1465 | n = db_int(0, "SELECT count(*) FROM timeline WHERE etype!='div' /*scan*/"); |
| 1461 | 1466 | if( zYearMonth ){ |
| 1462 | 1467 | blob_appendf(&desc, "%s events for %h", zEType, zYearMonth); |
| 1463 | 1468 | }else if( zYearWeek ){ |
| 1464 | 1469 | blob_appendf(&desc, "%s events for year/week %h", zEType, zYearWeek); |
| 1465 | - }else if( zAfter==0 && zBefore==0 && zCirca==0 && nEntry>0 ){ | |
| 1470 | + }else if( zAfter==0 && zBefore==0 && zCirca==0 && n>=nEntry && nEntry>0 ){ | |
| 1466 | 1471 | blob_appendf(&desc, "%d most recent %ss", n, zEType); |
| 1467 | 1472 | }else{ |
| 1468 | 1473 | blob_appendf(&desc, "%d %ss", n, zEType); |
| 1469 | 1474 | } |
| 1470 | 1475 | if( zUses ){ |
| @@ -1511,11 +1516,11 @@ | ||
| 1511 | 1516 | } |
| 1512 | 1517 | if( zBefore || (zAfter && n==nEntry) ){ |
| 1513 | 1518 | zDate = db_text(0, "SELECT max(timestamp) FROM timeline /*scan*/"); |
| 1514 | 1519 | timeline_submenu(&url, "Newer", "a", zDate, "b"); |
| 1515 | 1520 | free(zDate); |
| 1516 | - }else if( tagid==0 ){ | |
| 1521 | + }else if( tagid==0 && zUses==0 ){ | |
| 1517 | 1522 | if( zType[0]!='a' ){ |
| 1518 | 1523 | timeline_submenu(&url, "All Types", "y", "all", 0); |
| 1519 | 1524 | } |
| 1520 | 1525 | if( zType[0]!='w' && g.perm.RdWiki ){ |
| 1521 | 1526 | timeline_submenu(&url, "Wiki Only", "y", "w", 0); |
| @@ -1552,10 +1557,11 @@ | ||
| 1552 | 1557 | } |
| 1553 | 1558 | } |
| 1554 | 1559 | if( P("showsql") ){ |
| 1555 | 1560 | @ <blockquote>%h(blob_sql_text(&sql))</blockquote> |
| 1556 | 1561 | } |
| 1562 | + if( P("showrid") ) tmFlags |= TIMELINE_SHOWRID; | |
| 1557 | 1563 | blob_zero(&sql); |
| 1558 | 1564 | db_prepare(&q, "SELECT * FROM timeline ORDER BY sortby DESC /*scan*/"); |
| 1559 | 1565 | @ <h2>%b(&desc)</h2> |
| 1560 | 1566 | blob_reset(&desc); |
| 1561 | 1567 | www_print_timeline(&q, tmFlags, zThisUser, zThisTag, 0); |
| @@ -2393,11 +2399,11 @@ | ||
| 2393 | 2399 | @ <br><div>Total events: %d(nEventTotal) |
| 2394 | 2400 | @ <br>Average per active %s(zAvgLabel): %d(nAvg) |
| 2395 | 2401 | @ </div> |
| 2396 | 2402 | } |
| 2397 | 2403 | if( !includeMonth ){ |
| 2398 | - output_table_sorting_javascript("statsTable","tnx"); | |
| 2404 | + output_table_sorting_javascript("statsTable","tnx",-1); | |
| 2399 | 2405 | } |
| 2400 | 2406 | } |
| 2401 | 2407 | |
| 2402 | 2408 | /* |
| 2403 | 2409 | ** Implements the "byuser" view for /reports. |
| @@ -2444,11 +2450,11 @@ | ||
| 2444 | 2450 | rowClass = ++nRowNumber % 2; |
| 2445 | 2451 | nEventTotal += nCount; |
| 2446 | 2452 | @<tr class='row%d(rowClass)'> |
| 2447 | 2453 | @ <td> |
| 2448 | 2454 | @ <a href="?view=bymonth&user=%h(zUser)&type=%c((char)statsReportType)">%h(zUser)</a> |
| 2449 | - @ </td><td>%d(nCount)</td> | |
| 2455 | + @ </td><td data-sortkey='%08x(-nCount)'>%d(nCount)</td> | |
| 2450 | 2456 | @ <td> |
| 2451 | 2457 | @ <div class='statistics-report-graph-line' |
| 2452 | 2458 | @ style='width:%d(nSize)%%;'> </div> |
| 2453 | 2459 | @ </td> |
| 2454 | 2460 | @</tr> |
| @@ -2457,11 +2463,11 @@ | ||
| 2457 | 2463 | use percent-based graph bars. |
| 2458 | 2464 | */ |
| 2459 | 2465 | } |
| 2460 | 2466 | @ </tbody></table> |
| 2461 | 2467 | db_finalize(&query); |
| 2462 | - output_table_sorting_javascript("statsTable","tnx"); | |
| 2468 | + output_table_sorting_javascript("statsTable","tkx",2); | |
| 2463 | 2469 | } |
| 2464 | 2470 | |
| 2465 | 2471 | /* |
| 2466 | 2472 | ** Implements the "byweekday" view for /reports. |
| 2467 | 2473 | */ |
| @@ -2522,11 +2528,11 @@ | ||
| 2522 | 2528 | @ </td> |
| 2523 | 2529 | @</tr> |
| 2524 | 2530 | } |
| 2525 | 2531 | @ </tbody></table> |
| 2526 | 2532 | db_finalize(&query); |
| 2527 | - output_table_sorting_javascript("statsTable","ntnx"); | |
| 2533 | + output_table_sorting_javascript("statsTable","ntnx",1); | |
| 2528 | 2534 | } |
| 2529 | 2535 | |
| 2530 | 2536 | |
| 2531 | 2537 | /* |
| 2532 | 2538 | ** Helper for stats_report_by_month_year(), which generates a list of |
| @@ -2655,11 +2661,11 @@ | ||
| 2655 | 2661 | int nAvg = iterations ? (total/iterations) : 0; |
| 2656 | 2662 | cgi_printf("<br><div>Total events: %d<br>" |
| 2657 | 2663 | "Average per active week: %d</div>", |
| 2658 | 2664 | total, nAvg); |
| 2659 | 2665 | } |
| 2660 | - output_table_sorting_javascript("statsTable","tnx"); | |
| 2666 | + output_table_sorting_javascript("statsTable","tnx",-1); | |
| 2661 | 2667 | } |
| 2662 | 2668 | } |
| 2663 | 2669 | |
| 2664 | 2670 | /* |
| 2665 | 2671 | ** WEBPAGE: reports |
| 2666 | 2672 |
| --- src/timeline.c | |
| +++ src/timeline.c | |
| @@ -87,10 +87,11 @@ | |
| 87 | #define TIMELINE_FCHANGES 0x0020 /* Detail file changes */ |
| 88 | #define TIMELINE_BRCOLOR 0x0040 /* Background color by branch name */ |
| 89 | #define TIMELINE_UCOLOR 0x0080 /* Background color by user */ |
| 90 | #define TIMELINE_FRENAMES 0x0100 /* Detail only file name changes */ |
| 91 | #define TIMELINE_UNHIDE 0x0200 /* Unhide check-ins with "hidden" tag */ |
| 92 | #endif |
| 93 | |
| 94 | /* |
| 95 | ** Hash a string and use the hash to determine a background color. |
| 96 | */ |
| @@ -404,10 +405,13 @@ | |
| 404 | } |
| 405 | }else if( zType[0]=='e' && tagid ){ |
| 406 | hyperlink_to_event_tagid(tagid<0?-tagid:tagid); |
| 407 | }else if( (tmFlags & TIMELINE_ARTID)!=0 ){ |
| 408 | hyperlink_to_uuid(zUuid); |
| 409 | } |
| 410 | db_column_blob(pQuery, commentColumn, &comment); |
| 411 | if( zType[0]!='c' ){ |
| 412 | /* Comments for anything other than a check-in are generated by |
| 413 | ** "fossil rebuild" and expect to be rendered as text/x-fossil-wiki */ |
| @@ -604,12 +608,12 @@ | |
| 604 | ** for the upward portion of a merge arrow. The merge arrow goes up |
| 605 | ** to the row identified by mu:. If this value is zero then |
| 606 | ** node has no merge children and no merge-out line is drawn. |
| 607 | ** mu: The id of the row which is the top of the merge-out arrow. |
| 608 | ** u: Draw a thick child-line out of the top of this node and up to |
| 609 | ** the node with an id equal to this value. 0 if there is no |
| 610 | ** thick-line riser. |
| 611 | ** f: 0x01: a leaf node. |
| 612 | ** au: An array of integers that define thick-line risers for branches. |
| 613 | ** The integers are in pairs. For each pair, the first integer is |
| 614 | ** is the rail on which the riser should run and the second integer |
| 615 | ** is the id of the node upto which the riser should run. |
| @@ -1070,11 +1074,11 @@ | |
| 1070 | const char *zYearMonth = P("ym"); /* Show checkins for the given YYYY-MM */ |
| 1071 | const char *zYearWeek = P("yw"); /* Show checkins for the given YYYY-WW (week-of-year)*/ |
| 1072 | int useDividers = P("nd")==0; /* Show dividers if "nd" is missing */ |
| 1073 | int renameOnly = P("namechng")!=0; /* Show only checkins that rename files */ |
| 1074 | int tagid; /* Tag ID */ |
| 1075 | int tmFlags; /* Timeline flags */ |
| 1076 | const char *zThisTag = 0; /* Suppress links to this tag */ |
| 1077 | const char *zThisUser = 0; /* Suppress links to this user */ |
| 1078 | HQuery url; /* URL for various branch links */ |
| 1079 | int from_rid = name_to_typed_rid(P("from"),"ci"); /* from= for paths */ |
| 1080 | int to_rid = name_to_typed_rid(P("to"),"ci"); /* to= for path timelines */ |
| @@ -1110,13 +1114,13 @@ | |
| 1110 | ){ |
| 1111 | zCirca = zBefore = zAfter = 0; |
| 1112 | nEntry = -1; |
| 1113 | } |
| 1114 | if( zType[0]=='a' ){ |
| 1115 | tmFlags = TIMELINE_BRIEF | TIMELINE_GRAPH; |
| 1116 | }else{ |
| 1117 | tmFlags = TIMELINE_GRAPH; |
| 1118 | } |
| 1119 | if( nEntry>0 ) url_add_parameter(&url, "n", mprintf("%d", nEntry)); |
| 1120 | if( P("ng")!=0 || zSearch!=0 ){ |
| 1121 | tmFlags &= ~TIMELINE_GRAPH; |
| 1122 | url_add_parameter(&url, "ng", 0); |
| @@ -1206,10 +1210,11 @@ | |
| 1206 | }else if( (p_rid || d_rid) && g.perm.Read ){ |
| 1207 | /* If p= or d= is present, ignore all other parameters other than n= */ |
| 1208 | char *zUuid; |
| 1209 | int np, nd; |
| 1210 | |
| 1211 | if( p_rid && d_rid ){ |
| 1212 | if( p_rid!=d_rid ) p_rid = d_rid; |
| 1213 | if( P("n")==0 ) nEntry = 10; |
| 1214 | } |
| 1215 | db_multi_exec( |
| @@ -1460,11 +1465,11 @@ | |
| 1460 | n = db_int(0, "SELECT count(*) FROM timeline WHERE etype!='div' /*scan*/"); |
| 1461 | if( zYearMonth ){ |
| 1462 | blob_appendf(&desc, "%s events for %h", zEType, zYearMonth); |
| 1463 | }else if( zYearWeek ){ |
| 1464 | blob_appendf(&desc, "%s events for year/week %h", zEType, zYearWeek); |
| 1465 | }else if( zAfter==0 && zBefore==0 && zCirca==0 && nEntry>0 ){ |
| 1466 | blob_appendf(&desc, "%d most recent %ss", n, zEType); |
| 1467 | }else{ |
| 1468 | blob_appendf(&desc, "%d %ss", n, zEType); |
| 1469 | } |
| 1470 | if( zUses ){ |
| @@ -1511,11 +1516,11 @@ | |
| 1511 | } |
| 1512 | if( zBefore || (zAfter && n==nEntry) ){ |
| 1513 | zDate = db_text(0, "SELECT max(timestamp) FROM timeline /*scan*/"); |
| 1514 | timeline_submenu(&url, "Newer", "a", zDate, "b"); |
| 1515 | free(zDate); |
| 1516 | }else if( tagid==0 ){ |
| 1517 | if( zType[0]!='a' ){ |
| 1518 | timeline_submenu(&url, "All Types", "y", "all", 0); |
| 1519 | } |
| 1520 | if( zType[0]!='w' && g.perm.RdWiki ){ |
| 1521 | timeline_submenu(&url, "Wiki Only", "y", "w", 0); |
| @@ -1552,10 +1557,11 @@ | |
| 1552 | } |
| 1553 | } |
| 1554 | if( P("showsql") ){ |
| 1555 | @ <blockquote>%h(blob_sql_text(&sql))</blockquote> |
| 1556 | } |
| 1557 | blob_zero(&sql); |
| 1558 | db_prepare(&q, "SELECT * FROM timeline ORDER BY sortby DESC /*scan*/"); |
| 1559 | @ <h2>%b(&desc)</h2> |
| 1560 | blob_reset(&desc); |
| 1561 | www_print_timeline(&q, tmFlags, zThisUser, zThisTag, 0); |
| @@ -2393,11 +2399,11 @@ | |
| 2393 | @ <br><div>Total events: %d(nEventTotal) |
| 2394 | @ <br>Average per active %s(zAvgLabel): %d(nAvg) |
| 2395 | @ </div> |
| 2396 | } |
| 2397 | if( !includeMonth ){ |
| 2398 | output_table_sorting_javascript("statsTable","tnx"); |
| 2399 | } |
| 2400 | } |
| 2401 | |
| 2402 | /* |
| 2403 | ** Implements the "byuser" view for /reports. |
| @@ -2444,11 +2450,11 @@ | |
| 2444 | rowClass = ++nRowNumber % 2; |
| 2445 | nEventTotal += nCount; |
| 2446 | @<tr class='row%d(rowClass)'> |
| 2447 | @ <td> |
| 2448 | @ <a href="?view=bymonth&user=%h(zUser)&type=%c((char)statsReportType)">%h(zUser)</a> |
| 2449 | @ </td><td>%d(nCount)</td> |
| 2450 | @ <td> |
| 2451 | @ <div class='statistics-report-graph-line' |
| 2452 | @ style='width:%d(nSize)%%;'> </div> |
| 2453 | @ </td> |
| 2454 | @</tr> |
| @@ -2457,11 +2463,11 @@ | |
| 2457 | use percent-based graph bars. |
| 2458 | */ |
| 2459 | } |
| 2460 | @ </tbody></table> |
| 2461 | db_finalize(&query); |
| 2462 | output_table_sorting_javascript("statsTable","tnx"); |
| 2463 | } |
| 2464 | |
| 2465 | /* |
| 2466 | ** Implements the "byweekday" view for /reports. |
| 2467 | */ |
| @@ -2522,11 +2528,11 @@ | |
| 2522 | @ </td> |
| 2523 | @</tr> |
| 2524 | } |
| 2525 | @ </tbody></table> |
| 2526 | db_finalize(&query); |
| 2527 | output_table_sorting_javascript("statsTable","ntnx"); |
| 2528 | } |
| 2529 | |
| 2530 | |
| 2531 | /* |
| 2532 | ** Helper for stats_report_by_month_year(), which generates a list of |
| @@ -2655,11 +2661,11 @@ | |
| 2655 | int nAvg = iterations ? (total/iterations) : 0; |
| 2656 | cgi_printf("<br><div>Total events: %d<br>" |
| 2657 | "Average per active week: %d</div>", |
| 2658 | total, nAvg); |
| 2659 | } |
| 2660 | output_table_sorting_javascript("statsTable","tnx"); |
| 2661 | } |
| 2662 | } |
| 2663 | |
| 2664 | /* |
| 2665 | ** WEBPAGE: reports |
| 2666 |
| --- src/timeline.c | |
| +++ src/timeline.c | |
| @@ -87,10 +87,11 @@ | |
| 87 | #define TIMELINE_FCHANGES 0x0020 /* Detail file changes */ |
| 88 | #define TIMELINE_BRCOLOR 0x0040 /* Background color by branch name */ |
| 89 | #define TIMELINE_UCOLOR 0x0080 /* Background color by user */ |
| 90 | #define TIMELINE_FRENAMES 0x0100 /* Detail only file name changes */ |
| 91 | #define TIMELINE_UNHIDE 0x0200 /* Unhide check-ins with "hidden" tag */ |
| 92 | #define TIMELINE_SHOWRID 0x0400 /* Show RID values in addition to UUIDs */ |
| 93 | #endif |
| 94 | |
| 95 | /* |
| 96 | ** Hash a string and use the hash to determine a background color. |
| 97 | */ |
| @@ -404,10 +405,13 @@ | |
| 405 | } |
| 406 | }else if( zType[0]=='e' && tagid ){ |
| 407 | hyperlink_to_event_tagid(tagid<0?-tagid:tagid); |
| 408 | }else if( (tmFlags & TIMELINE_ARTID)!=0 ){ |
| 409 | hyperlink_to_uuid(zUuid); |
| 410 | } |
| 411 | if( tmFlags & TIMELINE_SHOWRID ){ |
| 412 | @ (%d(rid)) |
| 413 | } |
| 414 | db_column_blob(pQuery, commentColumn, &comment); |
| 415 | if( zType[0]!='c' ){ |
| 416 | /* Comments for anything other than a check-in are generated by |
| 417 | ** "fossil rebuild" and expect to be rendered as text/x-fossil-wiki */ |
| @@ -604,12 +608,12 @@ | |
| 608 | ** for the upward portion of a merge arrow. The merge arrow goes up |
| 609 | ** to the row identified by mu:. If this value is zero then |
| 610 | ** node has no merge children and no merge-out line is drawn. |
| 611 | ** mu: The id of the row which is the top of the merge-out arrow. |
| 612 | ** u: Draw a thick child-line out of the top of this node and up to |
| 613 | ** the node with an id equal to this value. 0 if it is straight to |
| 614 | ** the top of the page, -1 if there is no thick-line riser. |
| 615 | ** f: 0x01: a leaf node. |
| 616 | ** au: An array of integers that define thick-line risers for branches. |
| 617 | ** The integers are in pairs. For each pair, the first integer is |
| 618 | ** is the rail on which the riser should run and the second integer |
| 619 | ** is the id of the node upto which the riser should run. |
| @@ -1070,11 +1074,11 @@ | |
| 1074 | const char *zYearMonth = P("ym"); /* Show checkins for the given YYYY-MM */ |
| 1075 | const char *zYearWeek = P("yw"); /* Show checkins for the given YYYY-WW (week-of-year)*/ |
| 1076 | int useDividers = P("nd")==0; /* Show dividers if "nd" is missing */ |
| 1077 | int renameOnly = P("namechng")!=0; /* Show only checkins that rename files */ |
| 1078 | int tagid; /* Tag ID */ |
| 1079 | int tmFlags = 0; /* Timeline flags */ |
| 1080 | const char *zThisTag = 0; /* Suppress links to this tag */ |
| 1081 | const char *zThisUser = 0; /* Suppress links to this user */ |
| 1082 | HQuery url; /* URL for various branch links */ |
| 1083 | int from_rid = name_to_typed_rid(P("from"),"ci"); /* from= for paths */ |
| 1084 | int to_rid = name_to_typed_rid(P("to"),"ci"); /* to= for path timelines */ |
| @@ -1110,13 +1114,13 @@ | |
| 1114 | ){ |
| 1115 | zCirca = zBefore = zAfter = 0; |
| 1116 | nEntry = -1; |
| 1117 | } |
| 1118 | if( zType[0]=='a' ){ |
| 1119 | tmFlags |= TIMELINE_BRIEF | TIMELINE_GRAPH; |
| 1120 | }else{ |
| 1121 | tmFlags |= TIMELINE_GRAPH; |
| 1122 | } |
| 1123 | if( nEntry>0 ) url_add_parameter(&url, "n", mprintf("%d", nEntry)); |
| 1124 | if( P("ng")!=0 || zSearch!=0 ){ |
| 1125 | tmFlags &= ~TIMELINE_GRAPH; |
| 1126 | url_add_parameter(&url, "ng", 0); |
| @@ -1206,10 +1210,11 @@ | |
| 1210 | }else if( (p_rid || d_rid) && g.perm.Read ){ |
| 1211 | /* If p= or d= is present, ignore all other parameters other than n= */ |
| 1212 | char *zUuid; |
| 1213 | int np, nd; |
| 1214 | |
| 1215 | tmFlags |= TIMELINE_DISJOINT; |
| 1216 | if( p_rid && d_rid ){ |
| 1217 | if( p_rid!=d_rid ) p_rid = d_rid; |
| 1218 | if( P("n")==0 ) nEntry = 10; |
| 1219 | } |
| 1220 | db_multi_exec( |
| @@ -1460,11 +1465,11 @@ | |
| 1465 | n = db_int(0, "SELECT count(*) FROM timeline WHERE etype!='div' /*scan*/"); |
| 1466 | if( zYearMonth ){ |
| 1467 | blob_appendf(&desc, "%s events for %h", zEType, zYearMonth); |
| 1468 | }else if( zYearWeek ){ |
| 1469 | blob_appendf(&desc, "%s events for year/week %h", zEType, zYearWeek); |
| 1470 | }else if( zAfter==0 && zBefore==0 && zCirca==0 && n>=nEntry && nEntry>0 ){ |
| 1471 | blob_appendf(&desc, "%d most recent %ss", n, zEType); |
| 1472 | }else{ |
| 1473 | blob_appendf(&desc, "%d %ss", n, zEType); |
| 1474 | } |
| 1475 | if( zUses ){ |
| @@ -1511,11 +1516,11 @@ | |
| 1516 | } |
| 1517 | if( zBefore || (zAfter && n==nEntry) ){ |
| 1518 | zDate = db_text(0, "SELECT max(timestamp) FROM timeline /*scan*/"); |
| 1519 | timeline_submenu(&url, "Newer", "a", zDate, "b"); |
| 1520 | free(zDate); |
| 1521 | }else if( tagid==0 && zUses==0 ){ |
| 1522 | if( zType[0]!='a' ){ |
| 1523 | timeline_submenu(&url, "All Types", "y", "all", 0); |
| 1524 | } |
| 1525 | if( zType[0]!='w' && g.perm.RdWiki ){ |
| 1526 | timeline_submenu(&url, "Wiki Only", "y", "w", 0); |
| @@ -1552,10 +1557,11 @@ | |
| 1557 | } |
| 1558 | } |
| 1559 | if( P("showsql") ){ |
| 1560 | @ <blockquote>%h(blob_sql_text(&sql))</blockquote> |
| 1561 | } |
| 1562 | if( P("showrid") ) tmFlags |= TIMELINE_SHOWRID; |
| 1563 | blob_zero(&sql); |
| 1564 | db_prepare(&q, "SELECT * FROM timeline ORDER BY sortby DESC /*scan*/"); |
| 1565 | @ <h2>%b(&desc)</h2> |
| 1566 | blob_reset(&desc); |
| 1567 | www_print_timeline(&q, tmFlags, zThisUser, zThisTag, 0); |
| @@ -2393,11 +2399,11 @@ | |
| 2399 | @ <br><div>Total events: %d(nEventTotal) |
| 2400 | @ <br>Average per active %s(zAvgLabel): %d(nAvg) |
| 2401 | @ </div> |
| 2402 | } |
| 2403 | if( !includeMonth ){ |
| 2404 | output_table_sorting_javascript("statsTable","tnx",-1); |
| 2405 | } |
| 2406 | } |
| 2407 | |
| 2408 | /* |
| 2409 | ** Implements the "byuser" view for /reports. |
| @@ -2444,11 +2450,11 @@ | |
| 2450 | rowClass = ++nRowNumber % 2; |
| 2451 | nEventTotal += nCount; |
| 2452 | @<tr class='row%d(rowClass)'> |
| 2453 | @ <td> |
| 2454 | @ <a href="?view=bymonth&user=%h(zUser)&type=%c((char)statsReportType)">%h(zUser)</a> |
| 2455 | @ </td><td data-sortkey='%08x(-nCount)'>%d(nCount)</td> |
| 2456 | @ <td> |
| 2457 | @ <div class='statistics-report-graph-line' |
| 2458 | @ style='width:%d(nSize)%%;'> </div> |
| 2459 | @ </td> |
| 2460 | @</tr> |
| @@ -2457,11 +2463,11 @@ | |
| 2463 | use percent-based graph bars. |
| 2464 | */ |
| 2465 | } |
| 2466 | @ </tbody></table> |
| 2467 | db_finalize(&query); |
| 2468 | output_table_sorting_javascript("statsTable","tkx",2); |
| 2469 | } |
| 2470 | |
| 2471 | /* |
| 2472 | ** Implements the "byweekday" view for /reports. |
| 2473 | */ |
| @@ -2522,11 +2528,11 @@ | |
| 2528 | @ </td> |
| 2529 | @</tr> |
| 2530 | } |
| 2531 | @ </tbody></table> |
| 2532 | db_finalize(&query); |
| 2533 | output_table_sorting_javascript("statsTable","ntnx",1); |
| 2534 | } |
| 2535 | |
| 2536 | |
| 2537 | /* |
| 2538 | ** Helper for stats_report_by_month_year(), which generates a list of |
| @@ -2655,11 +2661,11 @@ | |
| 2661 | int nAvg = iterations ? (total/iterations) : 0; |
| 2662 | cgi_printf("<br><div>Total events: %d<br>" |
| 2663 | "Average per active week: %d</div>", |
| 2664 | total, nAvg); |
| 2665 | } |
| 2666 | output_table_sorting_javascript("statsTable","tnx",-1); |
| 2667 | } |
| 2668 | } |
| 2669 | |
| 2670 | /* |
| 2671 | ** WEBPAGE: reports |
| 2672 |
+1
-3
| --- src/undo.c | ||
| +++ src/undo.c | ||
| @@ -127,11 +127,10 @@ | ||
| 127 | 127 | ** Undo or redo all undoable or redoable changes. |
| 128 | 128 | */ |
| 129 | 129 | static void undo_all(int redoFlag){ |
| 130 | 130 | int ucid; |
| 131 | 131 | int ncid; |
| 132 | - const char *zDb = db_name("localdb"); | |
| 133 | 132 | undo_all_filesystem(redoFlag); |
| 134 | 133 | db_multi_exec( |
| 135 | 134 | "CREATE TEMP TABLE undo_vfile_2 AS SELECT * FROM vfile;" |
| 136 | 135 | "DELETE FROM vfile;" |
| 137 | 136 | "INSERT INTO vfile SELECT * FROM undo_vfile;" |
| @@ -143,12 +142,11 @@ | ||
| 143 | 142 | "INSERT INTO vmerge SELECT * FROM undo_vmerge;" |
| 144 | 143 | "DELETE FROM undo_vmerge;" |
| 145 | 144 | "INSERT INTO undo_vmerge SELECT * FROM undo_vmerge_2;" |
| 146 | 145 | "DROP TABLE undo_vmerge_2;" |
| 147 | 146 | ); |
| 148 | - if(db_exists("SELECT 1 FROM \"%w\".sqlite_master" | |
| 149 | - " WHERE name='undo_stash'", zDb) ){ | |
| 147 | + if( db_table_exists("localdb", "undo_stash") ){ | |
| 150 | 148 | if( redoFlag ){ |
| 151 | 149 | db_multi_exec( |
| 152 | 150 | "DELETE FROM stash WHERE stashid IN (SELECT stashid FROM undo_stash);" |
| 153 | 151 | "DELETE FROM stashfile" |
| 154 | 152 | " WHERE stashid NOT IN (SELECT stashid FROM stash);" |
| 155 | 153 |
| --- src/undo.c | |
| +++ src/undo.c | |
| @@ -127,11 +127,10 @@ | |
| 127 | ** Undo or redo all undoable or redoable changes. |
| 128 | */ |
| 129 | static void undo_all(int redoFlag){ |
| 130 | int ucid; |
| 131 | int ncid; |
| 132 | const char *zDb = db_name("localdb"); |
| 133 | undo_all_filesystem(redoFlag); |
| 134 | db_multi_exec( |
| 135 | "CREATE TEMP TABLE undo_vfile_2 AS SELECT * FROM vfile;" |
| 136 | "DELETE FROM vfile;" |
| 137 | "INSERT INTO vfile SELECT * FROM undo_vfile;" |
| @@ -143,12 +142,11 @@ | |
| 143 | "INSERT INTO vmerge SELECT * FROM undo_vmerge;" |
| 144 | "DELETE FROM undo_vmerge;" |
| 145 | "INSERT INTO undo_vmerge SELECT * FROM undo_vmerge_2;" |
| 146 | "DROP TABLE undo_vmerge_2;" |
| 147 | ); |
| 148 | if(db_exists("SELECT 1 FROM \"%w\".sqlite_master" |
| 149 | " WHERE name='undo_stash'", zDb) ){ |
| 150 | if( redoFlag ){ |
| 151 | db_multi_exec( |
| 152 | "DELETE FROM stash WHERE stashid IN (SELECT stashid FROM undo_stash);" |
| 153 | "DELETE FROM stashfile" |
| 154 | " WHERE stashid NOT IN (SELECT stashid FROM stash);" |
| 155 |
| --- src/undo.c | |
| +++ src/undo.c | |
| @@ -127,11 +127,10 @@ | |
| 127 | ** Undo or redo all undoable or redoable changes. |
| 128 | */ |
| 129 | static void undo_all(int redoFlag){ |
| 130 | int ucid; |
| 131 | int ncid; |
| 132 | undo_all_filesystem(redoFlag); |
| 133 | db_multi_exec( |
| 134 | "CREATE TEMP TABLE undo_vfile_2 AS SELECT * FROM vfile;" |
| 135 | "DELETE FROM vfile;" |
| 136 | "INSERT INTO vfile SELECT * FROM undo_vfile;" |
| @@ -143,12 +142,11 @@ | |
| 142 | "INSERT INTO vmerge SELECT * FROM undo_vmerge;" |
| 143 | "DELETE FROM undo_vmerge;" |
| 144 | "INSERT INTO undo_vmerge SELECT * FROM undo_vmerge_2;" |
| 145 | "DROP TABLE undo_vmerge_2;" |
| 146 | ); |
| 147 | if( db_table_exists("localdb", "undo_stash") ){ |
| 148 | if( redoFlag ){ |
| 149 | db_multi_exec( |
| 150 | "DELETE FROM stash WHERE stashid IN (SELECT stashid FROM undo_stash);" |
| 151 | "DELETE FROM stashfile" |
| 152 | " WHERE stashid NOT IN (SELECT stashid FROM stash);" |
| 153 |
+1
-1
| --- src/xfer.c | ||
| +++ src/xfer.c | ||
| @@ -532,11 +532,11 @@ | ||
| 532 | 532 | ** private artifacts if we are not doing a private transfer. |
| 533 | 533 | */ |
| 534 | 534 | static void request_phantoms(Xfer *pXfer, int maxReq){ |
| 535 | 535 | Stmt q; |
| 536 | 536 | db_prepare(&q, |
| 537 | - "SELECT uuid FROM phantom JOIN blob USING(rid)" | |
| 537 | + "SELECT uuid FROM phantom CROSS JOIN blob USING(rid) /*scan*/" | |
| 538 | 538 | " WHERE NOT EXISTS(SELECT 1 FROM shun WHERE uuid=blob.uuid) %s", |
| 539 | 539 | (pXfer->syncPrivate ? "" : |
| 540 | 540 | " AND NOT EXISTS(SELECT 1 FROM private WHERE rid=blob.rid)") |
| 541 | 541 | ); |
| 542 | 542 | while( db_step(&q)==SQLITE_ROW && maxReq-- > 0 ){ |
| 543 | 543 |
| --- src/xfer.c | |
| +++ src/xfer.c | |
| @@ -532,11 +532,11 @@ | |
| 532 | ** private artifacts if we are not doing a private transfer. |
| 533 | */ |
| 534 | static void request_phantoms(Xfer *pXfer, int maxReq){ |
| 535 | Stmt q; |
| 536 | db_prepare(&q, |
| 537 | "SELECT uuid FROM phantom JOIN blob USING(rid)" |
| 538 | " WHERE NOT EXISTS(SELECT 1 FROM shun WHERE uuid=blob.uuid) %s", |
| 539 | (pXfer->syncPrivate ? "" : |
| 540 | " AND NOT EXISTS(SELECT 1 FROM private WHERE rid=blob.rid)") |
| 541 | ); |
| 542 | while( db_step(&q)==SQLITE_ROW && maxReq-- > 0 ){ |
| 543 |
| --- src/xfer.c | |
| +++ src/xfer.c | |
| @@ -532,11 +532,11 @@ | |
| 532 | ** private artifacts if we are not doing a private transfer. |
| 533 | */ |
| 534 | static void request_phantoms(Xfer *pXfer, int maxReq){ |
| 535 | Stmt q; |
| 536 | db_prepare(&q, |
| 537 | "SELECT uuid FROM phantom CROSS JOIN blob USING(rid) /*scan*/" |
| 538 | " WHERE NOT EXISTS(SELECT 1 FROM shun WHERE uuid=blob.uuid) %s", |
| 539 | (pXfer->syncPrivate ? "" : |
| 540 | " AND NOT EXISTS(SELECT 1 FROM private WHERE rid=blob.rid)") |
| 541 | ); |
| 542 | while( db_step(&q)==SQLITE_ROW && maxReq-- > 0 ){ |
| 543 |
+2
-2
| --- test/valgrind-www.tcl | ||
| +++ test/valgrind-www.tcl | ||
| @@ -1,10 +1,10 @@ | ||
| 1 | 1 | #!/usr/bin/tclsh |
| 2 | 2 | # |
| 3 | -# Run this script in an open Fossil checkout at the top-level with a | |
| 3 | +# Run this script in an open Fossil checkout at the top-level with a | |
| 4 | 4 | # fresh build of Fossil itself. This script will run fossil on hundreds |
| 5 | -# of different web-pages looking for memory allocation problems using | |
| 5 | +# of different web-pages looking for memory allocation problems using | |
| 6 | 6 | # valgrind. Valgrind output appears on stderr. Suggested test scenario: |
| 7 | 7 | # |
| 8 | 8 | # make |
| 9 | 9 | # tclsh valgrind-www.tcl 2>&1 | tee valgrind-out.txt |
| 10 | 10 | # |
| 11 | 11 |
| --- test/valgrind-www.tcl | |
| +++ test/valgrind-www.tcl | |
| @@ -1,10 +1,10 @@ | |
| 1 | #!/usr/bin/tclsh |
| 2 | # |
| 3 | # Run this script in an open Fossil checkout at the top-level with a |
| 4 | # fresh build of Fossil itself. This script will run fossil on hundreds |
| 5 | # of different web-pages looking for memory allocation problems using |
| 6 | # valgrind. Valgrind output appears on stderr. Suggested test scenario: |
| 7 | # |
| 8 | # make |
| 9 | # tclsh valgrind-www.tcl 2>&1 | tee valgrind-out.txt |
| 10 | # |
| 11 |
| --- test/valgrind-www.tcl | |
| +++ test/valgrind-www.tcl | |
| @@ -1,10 +1,10 @@ | |
| 1 | #!/usr/bin/tclsh |
| 2 | # |
| 3 | # Run this script in an open Fossil checkout at the top-level with a |
| 4 | # fresh build of Fossil itself. This script will run fossil on hundreds |
| 5 | # of different web-pages looking for memory allocation problems using |
| 6 | # valgrind. Valgrind output appears on stderr. Suggested test scenario: |
| 7 | # |
| 8 | # make |
| 9 | # tclsh valgrind-www.tcl 2>&1 | tee valgrind-out.txt |
| 10 | # |
| 11 |
+4
-4
| --- tools/fossil_chat.tcl | ||
| +++ tools/fossil_chat.tcl | ||
| @@ -84,11 +84,11 @@ | ||
| 84 | 84 | catch {close $SOCKET} |
| 85 | 85 | if {[catch { |
| 86 | 86 | if {$::PROXYHOST ne {}} { |
| 87 | 87 | set SOCKET [socket $::PROXYHOST $::PROXYPORT] |
| 88 | 88 | puts $SOCKET "CONNECT $::SERVERHOST:$::SERVERPORT HTTP/1.1" |
| 89 | - puts $SOCKET "Host: $::SERVERHOST:$::SERVERPORT" | |
| 89 | + puts $SOCKET "Host: $::SERVERHOST:$::SERVERPORT" | |
| 90 | 90 | puts $SOCKET "" |
| 91 | 91 | } else { |
| 92 | 92 | set SOCKET [socket $::SERVERHOST $::SERVERPORT] |
| 93 | 93 | } |
| 94 | 94 | fconfigure $SOCKET -translation binary -blocking 0 |
| @@ -142,11 +142,11 @@ | ||
| 142 | 142 | # |
| 143 | 143 | proc delete_files {} { |
| 144 | 144 | global FILES |
| 145 | 145 | .mb.files delete 3 end |
| 146 | 146 | array unset FILES |
| 147 | - .mb.files entryconfigure 1 -state disabled | |
| 147 | + .mb.files entryconfigure 1 -state disabled | |
| 148 | 148 | } |
| 149 | 149 | |
| 150 | 150 | # Prompt the user to select a file from the disk. Then send that |
| 151 | 151 | # file to all chat participants. |
| 152 | 152 | # |
| @@ -188,11 +188,11 @@ | ||
| 188 | 188 | if {![info exists prior] || $filename!=$prior} { |
| 189 | 189 | .mb.files add command -label "Save \"$filename\"" \ |
| 190 | 190 | -command [list save_file $filename] |
| 191 | 191 | } |
| 192 | 192 | set FILES($filename) $data |
| 193 | - .mb.files entryconfigure 1 -state active | |
| 193 | + .mb.files entryconfigure 1 -state active | |
| 194 | 194 | set time [clock format [clock seconds] -format {%H:%M} -gmt 1] |
| 195 | 195 | .msg.t insert end "\[$time $from\] " meta "File: \"$filename\"\n" norm |
| 196 | 196 | .msg.t see end |
| 197 | 197 | } |
| 198 | 198 | |
| @@ -232,11 +232,11 @@ | ||
| 232 | 232 | } elseif {$cmd=="file"} { |
| 233 | 233 | if {[info commands handle_file]=="handle_file"} { |
| 234 | 234 | handle_file [lindex $line 1] [lindex $line 2] [lindex $line 3] |
| 235 | 235 | } |
| 236 | 236 | } |
| 237 | -} | |
| 237 | +} | |
| 238 | 238 | |
| 239 | 239 | # Handle a broken socket connection |
| 240 | 240 | # |
| 241 | 241 | proc disconnect {} { |
| 242 | 242 | global SOCKET |
| 243 | 243 |
| --- tools/fossil_chat.tcl | |
| +++ tools/fossil_chat.tcl | |
| @@ -84,11 +84,11 @@ | |
| 84 | catch {close $SOCKET} |
| 85 | if {[catch { |
| 86 | if {$::PROXYHOST ne {}} { |
| 87 | set SOCKET [socket $::PROXYHOST $::PROXYPORT] |
| 88 | puts $SOCKET "CONNECT $::SERVERHOST:$::SERVERPORT HTTP/1.1" |
| 89 | puts $SOCKET "Host: $::SERVERHOST:$::SERVERPORT" |
| 90 | puts $SOCKET "" |
| 91 | } else { |
| 92 | set SOCKET [socket $::SERVERHOST $::SERVERPORT] |
| 93 | } |
| 94 | fconfigure $SOCKET -translation binary -blocking 0 |
| @@ -142,11 +142,11 @@ | |
| 142 | # |
| 143 | proc delete_files {} { |
| 144 | global FILES |
| 145 | .mb.files delete 3 end |
| 146 | array unset FILES |
| 147 | .mb.files entryconfigure 1 -state disabled |
| 148 | } |
| 149 | |
| 150 | # Prompt the user to select a file from the disk. Then send that |
| 151 | # file to all chat participants. |
| 152 | # |
| @@ -188,11 +188,11 @@ | |
| 188 | if {![info exists prior] || $filename!=$prior} { |
| 189 | .mb.files add command -label "Save \"$filename\"" \ |
| 190 | -command [list save_file $filename] |
| 191 | } |
| 192 | set FILES($filename) $data |
| 193 | .mb.files entryconfigure 1 -state active |
| 194 | set time [clock format [clock seconds] -format {%H:%M} -gmt 1] |
| 195 | .msg.t insert end "\[$time $from\] " meta "File: \"$filename\"\n" norm |
| 196 | .msg.t see end |
| 197 | } |
| 198 | |
| @@ -232,11 +232,11 @@ | |
| 232 | } elseif {$cmd=="file"} { |
| 233 | if {[info commands handle_file]=="handle_file"} { |
| 234 | handle_file [lindex $line 1] [lindex $line 2] [lindex $line 3] |
| 235 | } |
| 236 | } |
| 237 | } |
| 238 | |
| 239 | # Handle a broken socket connection |
| 240 | # |
| 241 | proc disconnect {} { |
| 242 | global SOCKET |
| 243 |
| --- tools/fossil_chat.tcl | |
| +++ tools/fossil_chat.tcl | |
| @@ -84,11 +84,11 @@ | |
| 84 | catch {close $SOCKET} |
| 85 | if {[catch { |
| 86 | if {$::PROXYHOST ne {}} { |
| 87 | set SOCKET [socket $::PROXYHOST $::PROXYPORT] |
| 88 | puts $SOCKET "CONNECT $::SERVERHOST:$::SERVERPORT HTTP/1.1" |
| 89 | puts $SOCKET "Host: $::SERVERHOST:$::SERVERPORT" |
| 90 | puts $SOCKET "" |
| 91 | } else { |
| 92 | set SOCKET [socket $::SERVERHOST $::SERVERPORT] |
| 93 | } |
| 94 | fconfigure $SOCKET -translation binary -blocking 0 |
| @@ -142,11 +142,11 @@ | |
| 142 | # |
| 143 | proc delete_files {} { |
| 144 | global FILES |
| 145 | .mb.files delete 3 end |
| 146 | array unset FILES |
| 147 | .mb.files entryconfigure 1 -state disabled |
| 148 | } |
| 149 | |
| 150 | # Prompt the user to select a file from the disk. Then send that |
| 151 | # file to all chat participants. |
| 152 | # |
| @@ -188,11 +188,11 @@ | |
| 188 | if {![info exists prior] || $filename!=$prior} { |
| 189 | .mb.files add command -label "Save \"$filename\"" \ |
| 190 | -command [list save_file $filename] |
| 191 | } |
| 192 | set FILES($filename) $data |
| 193 | .mb.files entryconfigure 1 -state active |
| 194 | set time [clock format [clock seconds] -format {%H:%M} -gmt 1] |
| 195 | .msg.t insert end "\[$time $from\] " meta "File: \"$filename\"\n" norm |
| 196 | .msg.t see end |
| 197 | } |
| 198 | |
| @@ -232,11 +232,11 @@ | |
| 232 | } elseif {$cmd=="file"} { |
| 233 | if {[info commands handle_file]=="handle_file"} { |
| 234 | handle_file [lindex $line 1] [lindex $line 2] [lindex $line 3] |
| 235 | } |
| 236 | } |
| 237 | } |
| 238 | |
| 239 | # Handle a broken socket connection |
| 240 | # |
| 241 | proc disconnect {} { |
| 242 | global SOCKET |
| 243 |
+10
-4
| --- win/Makefile.dmc | ||
| +++ win/Makefile.dmc | ||
| @@ -28,13 +28,13 @@ | ||
| 28 | 28 | |
| 29 | 29 | SQLITE_OPTIONS = -DNDEBUG=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_OMIT_DEPRECATED -DSQLITE_ENABLE_EXPLAIN_COMMENTS |
| 30 | 30 | |
| 31 | 31 | SHELL_OPTIONS = -Dmain=sqlite3_shell -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=fossil_open -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen |
| 32 | 32 | |
| 33 | -SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c builtin_.c bundle_.c cache_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c foci_.c fusefs_.c glob_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_status_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c loadctrl_.c login_.c lookslike_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c publish_.c purge_.c rebuild_.c regexp_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c sqlcmd_.c stash_.c stat_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c update_.c url_.c user_.c utf8_.c util_.c verify_.c vfile_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c | |
| 33 | +SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c builtin_.c bundle_.c cache_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c foci_.c fusefs_.c glob_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_status_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c loadctrl_.c login_.c lookslike_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c publish_.c purge_.c rebuild_.c regexp_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c sitemap_.c skins_.c sqlcmd_.c stash_.c stat_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c update_.c url_.c user_.c utf8_.c util_.c verify_.c vfile_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c | |
| 34 | 34 | |
| 35 | -OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\builtin$O $(OBJDIR)\bundle$O $(OBJDIR)\cache$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\foci$O $(OBJDIR)\fusefs$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\json$O $(OBJDIR)\json_artifact$O $(OBJDIR)\json_branch$O $(OBJDIR)\json_config$O $(OBJDIR)\json_diff$O $(OBJDIR)\json_dir$O $(OBJDIR)\json_finfo$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_status$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\loadctrl$O $(OBJDIR)\login$O $(OBJDIR)\lookslike$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\markdown$O $(OBJDIR)\markdown_html$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\moderate$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\publish$O $(OBJDIR)\purge$O $(OBJDIR)\rebuild$O $(OBJDIR)\regexp$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\skins$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\unicode$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\util$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winfile$O $(OBJDIR)\winhttp$O $(OBJDIR)\wysiwyg$O $(OBJDIR)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O | |
| 35 | +OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\builtin$O $(OBJDIR)\bundle$O $(OBJDIR)\cache$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\foci$O $(OBJDIR)\fusefs$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\json$O $(OBJDIR)\json_artifact$O $(OBJDIR)\json_branch$O $(OBJDIR)\json_config$O $(OBJDIR)\json_diff$O $(OBJDIR)\json_dir$O $(OBJDIR)\json_finfo$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_status$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\loadctrl$O $(OBJDIR)\login$O $(OBJDIR)\lookslike$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\markdown$O $(OBJDIR)\markdown_html$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\moderate$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\publish$O $(OBJDIR)\purge$O $(OBJDIR)\rebuild$O $(OBJDIR)\regexp$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\sitemap$O $(OBJDIR)\skins$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\unicode$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\util$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winfile$O $(OBJDIR)\winhttp$O $(OBJDIR)\wysiwyg$O $(OBJDIR)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O | |
| 36 | 36 | |
| 37 | 37 | |
| 38 | 38 | RC=$(DMDIR)\bin\rcc |
| 39 | 39 | RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__ |
| 40 | 40 | |
| @@ -49,11 +49,11 @@ | ||
| 49 | 49 | |
| 50 | 50 | $(OBJDIR)\fossil.res: $B\win\fossil.rc |
| 51 | 51 | $(RC) $(RCFLAGS) -o$@ $** |
| 52 | 52 | |
| 53 | 53 | $(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res |
| 54 | - +echo add allrepo attach bag bisect blob branch browse builtin bundle cache captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode event export file finfo foci fusefs glob graph gzip http http_socket http_ssl http_transport import info json json_artifact json_branch json_config json_diff json_dir json_finfo json_login json_query json_report json_status json_tag json_timeline json_user json_wiki leaf loadctrl login lookslike main manifest markdown markdown_html md5 merge merge3 moderate name path pivot popen pqueue printf publish purge rebuild regexp report rss schema search setup sha1 shun skins sqlcmd stash stat style sync tag tar th_main timeline tkt tktsetup undo unicode update url user utf8 util verify vfile wiki wikiformat winfile winhttp wysiwyg xfer xfersetup zip shell sqlite3 th th_lang > $@ | |
| 54 | + +echo add allrepo attach bag bisect blob branch browse builtin bundle cache captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode event export file finfo foci fusefs glob graph gzip http http_socket http_ssl http_transport import info json json_artifact json_branch json_config json_diff json_dir json_finfo json_login json_query json_report json_status json_tag json_timeline json_user json_wiki leaf loadctrl login lookslike main manifest markdown markdown_html md5 merge merge3 moderate name path pivot popen pqueue printf publish purge rebuild regexp report rss schema search setup sha1 shun sitemap skins sqlcmd stash stat style sync tag tar th_main timeline tkt tktsetup undo unicode update url user utf8 util verify vfile wiki wikiformat winfile winhttp wysiwyg xfer xfersetup zip shell sqlite3 th th_lang > $@ | |
| 55 | 55 | +echo fossil >> $@ |
| 56 | 56 | +echo fossil >> $@ |
| 57 | 57 | +echo $(LIBS) >> $@ |
| 58 | 58 | +echo. >> $@ |
| 59 | 59 | +echo fossil >> $@ |
| @@ -644,10 +644,16 @@ | ||
| 644 | 644 | $(OBJDIR)\shun$O : shun_.c shun.h |
| 645 | 645 | $(TCC) -o$@ -c shun_.c |
| 646 | 646 | |
| 647 | 647 | shun_.c : $(SRCDIR)\shun.c |
| 648 | 648 | +translate$E $** > $@ |
| 649 | + | |
| 650 | +$(OBJDIR)\sitemap$O : sitemap_.c sitemap.h | |
| 651 | + $(TCC) -o$@ -c sitemap_.c | |
| 652 | + | |
| 653 | +sitemap_.c : $(SRCDIR)\sitemap.c | |
| 654 | + +translate$E $** > $@ | |
| 649 | 655 | |
| 650 | 656 | $(OBJDIR)\skins$O : skins_.c skins.h |
| 651 | 657 | $(TCC) -o$@ -c skins_.c |
| 652 | 658 | |
| 653 | 659 | skins_.c : $(SRCDIR)\skins.c |
| @@ -820,7 +826,7 @@ | ||
| 820 | 826 | |
| 821 | 827 | zip_.c : $(SRCDIR)\zip.c |
| 822 | 828 | +translate$E $** > $@ |
| 823 | 829 | |
| 824 | 830 | headers: makeheaders$E page_index.h builtin_data.h VERSION.h |
| 825 | - +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h builtin_.c:builtin.h bundle_.c:bundle.h cache_.c:cache.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h foci_.c:foci.h fusefs_.c:fusefs.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_config_.c:json_config.h json_diff_.c:json_diff.h json_dir_.c:json_dir.h json_finfo_.c:json_finfo.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_status_.c:json_status.h json_tag_.c:json_tag.h json_timeline_.c:json_timeline.h json_user_.c:json_user.h json_wiki_.c:json_wiki.h leaf_.c:leaf.h loadctrl_.c:loadctrl.h login_.c:login.h lookslike_.c:lookslike.h main_.c:main.h manifest_.c:manifest.h markdown_.c:markdown.h markdown_html_.c:markdown_html.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h moderate_.c:moderate.h name_.c:name.h path_.c:path.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h publish_.c:publish.h purge_.c:purge.h rebuild_.c:rebuild.h regexp_.c:regexp.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h unicode_.c:unicode.h update_.c:update.h url_.c:url.h user_.c:user.h utf8_.c:utf8.h util_.c:util.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winfile_.c:winfile.h winhttp_.c:winhttp.h wysiwyg_.c:wysiwyg.h xfer_.c:xfer.h xfersetup_.c:xfersetup.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h $(SRCDIR)\cson_amalgamation.h | |
| 831 | + +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h builtin_.c:builtin.h bundle_.c:bundle.h cache_.c:cache.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h foci_.c:foci.h fusefs_.c:fusefs.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_config_.c:json_config.h json_diff_.c:json_diff.h json_dir_.c:json_dir.h json_finfo_.c:json_finfo.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_status_.c:json_status.h json_tag_.c:json_tag.h json_timeline_.c:json_timeline.h json_user_.c:json_user.h json_wiki_.c:json_wiki.h leaf_.c:leaf.h loadctrl_.c:loadctrl.h login_.c:login.h lookslike_.c:lookslike.h main_.c:main.h manifest_.c:manifest.h markdown_.c:markdown.h markdown_html_.c:markdown_html.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h moderate_.c:moderate.h name_.c:name.h path_.c:path.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h publish_.c:publish.h purge_.c:purge.h rebuild_.c:rebuild.h regexp_.c:regexp.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h sitemap_.c:sitemap.h skins_.c:skins.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h unicode_.c:unicode.h update_.c:update.h url_.c:url.h user_.c:user.h utf8_.c:utf8.h util_.c:util.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winfile_.c:winfile.h winhttp_.c:winhttp.h wysiwyg_.c:wysiwyg.h xfer_.c:xfer.h xfersetup_.c:xfersetup.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h $(SRCDIR)\cson_amalgamation.h | |
| 826 | 832 | @copy /Y nul: headers |
| 827 | 833 |
| --- win/Makefile.dmc | |
| +++ win/Makefile.dmc | |
| @@ -28,13 +28,13 @@ | |
| 28 | |
| 29 | SQLITE_OPTIONS = -DNDEBUG=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_OMIT_DEPRECATED -DSQLITE_ENABLE_EXPLAIN_COMMENTS |
| 30 | |
| 31 | SHELL_OPTIONS = -Dmain=sqlite3_shell -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=fossil_open -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen |
| 32 | |
| 33 | SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c builtin_.c bundle_.c cache_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c foci_.c fusefs_.c glob_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_status_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c loadctrl_.c login_.c lookslike_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c publish_.c purge_.c rebuild_.c regexp_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c sqlcmd_.c stash_.c stat_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c update_.c url_.c user_.c utf8_.c util_.c verify_.c vfile_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c |
| 34 | |
| 35 | OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\builtin$O $(OBJDIR)\bundle$O $(OBJDIR)\cache$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\foci$O $(OBJDIR)\fusefs$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\json$O $(OBJDIR)\json_artifact$O $(OBJDIR)\json_branch$O $(OBJDIR)\json_config$O $(OBJDIR)\json_diff$O $(OBJDIR)\json_dir$O $(OBJDIR)\json_finfo$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_status$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\loadctrl$O $(OBJDIR)\login$O $(OBJDIR)\lookslike$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\markdown$O $(OBJDIR)\markdown_html$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\moderate$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\publish$O $(OBJDIR)\purge$O $(OBJDIR)\rebuild$O $(OBJDIR)\regexp$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\skins$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\unicode$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\util$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winfile$O $(OBJDIR)\winhttp$O $(OBJDIR)\wysiwyg$O $(OBJDIR)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O |
| 36 | |
| 37 | |
| 38 | RC=$(DMDIR)\bin\rcc |
| 39 | RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__ |
| 40 | |
| @@ -49,11 +49,11 @@ | |
| 49 | |
| 50 | $(OBJDIR)\fossil.res: $B\win\fossil.rc |
| 51 | $(RC) $(RCFLAGS) -o$@ $** |
| 52 | |
| 53 | $(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res |
| 54 | +echo add allrepo attach bag bisect blob branch browse builtin bundle cache captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode event export file finfo foci fusefs glob graph gzip http http_socket http_ssl http_transport import info json json_artifact json_branch json_config json_diff json_dir json_finfo json_login json_query json_report json_status json_tag json_timeline json_user json_wiki leaf loadctrl login lookslike main manifest markdown markdown_html md5 merge merge3 moderate name path pivot popen pqueue printf publish purge rebuild regexp report rss schema search setup sha1 shun skins sqlcmd stash stat style sync tag tar th_main timeline tkt tktsetup undo unicode update url user utf8 util verify vfile wiki wikiformat winfile winhttp wysiwyg xfer xfersetup zip shell sqlite3 th th_lang > $@ |
| 55 | +echo fossil >> $@ |
| 56 | +echo fossil >> $@ |
| 57 | +echo $(LIBS) >> $@ |
| 58 | +echo. >> $@ |
| 59 | +echo fossil >> $@ |
| @@ -644,10 +644,16 @@ | |
| 644 | $(OBJDIR)\shun$O : shun_.c shun.h |
| 645 | $(TCC) -o$@ -c shun_.c |
| 646 | |
| 647 | shun_.c : $(SRCDIR)\shun.c |
| 648 | +translate$E $** > $@ |
| 649 | |
| 650 | $(OBJDIR)\skins$O : skins_.c skins.h |
| 651 | $(TCC) -o$@ -c skins_.c |
| 652 | |
| 653 | skins_.c : $(SRCDIR)\skins.c |
| @@ -820,7 +826,7 @@ | |
| 820 | |
| 821 | zip_.c : $(SRCDIR)\zip.c |
| 822 | +translate$E $** > $@ |
| 823 | |
| 824 | headers: makeheaders$E page_index.h builtin_data.h VERSION.h |
| 825 | +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h builtin_.c:builtin.h bundle_.c:bundle.h cache_.c:cache.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h foci_.c:foci.h fusefs_.c:fusefs.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_config_.c:json_config.h json_diff_.c:json_diff.h json_dir_.c:json_dir.h json_finfo_.c:json_finfo.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_status_.c:json_status.h json_tag_.c:json_tag.h json_timeline_.c:json_timeline.h json_user_.c:json_user.h json_wiki_.c:json_wiki.h leaf_.c:leaf.h loadctrl_.c:loadctrl.h login_.c:login.h lookslike_.c:lookslike.h main_.c:main.h manifest_.c:manifest.h markdown_.c:markdown.h markdown_html_.c:markdown_html.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h moderate_.c:moderate.h name_.c:name.h path_.c:path.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h publish_.c:publish.h purge_.c:purge.h rebuild_.c:rebuild.h regexp_.c:regexp.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h unicode_.c:unicode.h update_.c:update.h url_.c:url.h user_.c:user.h utf8_.c:utf8.h util_.c:util.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winfile_.c:winfile.h winhttp_.c:winhttp.h wysiwyg_.c:wysiwyg.h xfer_.c:xfer.h xfersetup_.c:xfersetup.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h $(SRCDIR)\cson_amalgamation.h |
| 826 | @copy /Y nul: headers |
| 827 |
| --- win/Makefile.dmc | |
| +++ win/Makefile.dmc | |
| @@ -28,13 +28,13 @@ | |
| 28 | |
| 29 | SQLITE_OPTIONS = -DNDEBUG=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_OMIT_DEPRECATED -DSQLITE_ENABLE_EXPLAIN_COMMENTS |
| 30 | |
| 31 | SHELL_OPTIONS = -Dmain=sqlite3_shell -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=fossil_open -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen |
| 32 | |
| 33 | SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c builtin_.c bundle_.c cache_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c foci_.c fusefs_.c glob_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_status_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c loadctrl_.c login_.c lookslike_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c publish_.c purge_.c rebuild_.c regexp_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c sitemap_.c skins_.c sqlcmd_.c stash_.c stat_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c update_.c url_.c user_.c utf8_.c util_.c verify_.c vfile_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c |
| 34 | |
| 35 | OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\builtin$O $(OBJDIR)\bundle$O $(OBJDIR)\cache$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\foci$O $(OBJDIR)\fusefs$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\json$O $(OBJDIR)\json_artifact$O $(OBJDIR)\json_branch$O $(OBJDIR)\json_config$O $(OBJDIR)\json_diff$O $(OBJDIR)\json_dir$O $(OBJDIR)\json_finfo$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_status$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\loadctrl$O $(OBJDIR)\login$O $(OBJDIR)\lookslike$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\markdown$O $(OBJDIR)\markdown_html$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\moderate$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\publish$O $(OBJDIR)\purge$O $(OBJDIR)\rebuild$O $(OBJDIR)\regexp$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\sitemap$O $(OBJDIR)\skins$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\unicode$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\util$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winfile$O $(OBJDIR)\winhttp$O $(OBJDIR)\wysiwyg$O $(OBJDIR)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O |
| 36 | |
| 37 | |
| 38 | RC=$(DMDIR)\bin\rcc |
| 39 | RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__ |
| 40 | |
| @@ -49,11 +49,11 @@ | |
| 49 | |
| 50 | $(OBJDIR)\fossil.res: $B\win\fossil.rc |
| 51 | $(RC) $(RCFLAGS) -o$@ $** |
| 52 | |
| 53 | $(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res |
| 54 | +echo add allrepo attach bag bisect blob branch browse builtin bundle cache captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode event export file finfo foci fusefs glob graph gzip http http_socket http_ssl http_transport import info json json_artifact json_branch json_config json_diff json_dir json_finfo json_login json_query json_report json_status json_tag json_timeline json_user json_wiki leaf loadctrl login lookslike main manifest markdown markdown_html md5 merge merge3 moderate name path pivot popen pqueue printf publish purge rebuild regexp report rss schema search setup sha1 shun sitemap skins sqlcmd stash stat style sync tag tar th_main timeline tkt tktsetup undo unicode update url user utf8 util verify vfile wiki wikiformat winfile winhttp wysiwyg xfer xfersetup zip shell sqlite3 th th_lang > $@ |
| 55 | +echo fossil >> $@ |
| 56 | +echo fossil >> $@ |
| 57 | +echo $(LIBS) >> $@ |
| 58 | +echo. >> $@ |
| 59 | +echo fossil >> $@ |
| @@ -644,10 +644,16 @@ | |
| 644 | $(OBJDIR)\shun$O : shun_.c shun.h |
| 645 | $(TCC) -o$@ -c shun_.c |
| 646 | |
| 647 | shun_.c : $(SRCDIR)\shun.c |
| 648 | +translate$E $** > $@ |
| 649 | |
| 650 | $(OBJDIR)\sitemap$O : sitemap_.c sitemap.h |
| 651 | $(TCC) -o$@ -c sitemap_.c |
| 652 | |
| 653 | sitemap_.c : $(SRCDIR)\sitemap.c |
| 654 | +translate$E $** > $@ |
| 655 | |
| 656 | $(OBJDIR)\skins$O : skins_.c skins.h |
| 657 | $(TCC) -o$@ -c skins_.c |
| 658 | |
| 659 | skins_.c : $(SRCDIR)\skins.c |
| @@ -820,7 +826,7 @@ | |
| 826 | |
| 827 | zip_.c : $(SRCDIR)\zip.c |
| 828 | +translate$E $** > $@ |
| 829 | |
| 830 | headers: makeheaders$E page_index.h builtin_data.h VERSION.h |
| 831 | +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h builtin_.c:builtin.h bundle_.c:bundle.h cache_.c:cache.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h foci_.c:foci.h fusefs_.c:fusefs.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_config_.c:json_config.h json_diff_.c:json_diff.h json_dir_.c:json_dir.h json_finfo_.c:json_finfo.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_status_.c:json_status.h json_tag_.c:json_tag.h json_timeline_.c:json_timeline.h json_user_.c:json_user.h json_wiki_.c:json_wiki.h leaf_.c:leaf.h loadctrl_.c:loadctrl.h login_.c:login.h lookslike_.c:lookslike.h main_.c:main.h manifest_.c:manifest.h markdown_.c:markdown.h markdown_html_.c:markdown_html.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h moderate_.c:moderate.h name_.c:name.h path_.c:path.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h publish_.c:publish.h purge_.c:purge.h rebuild_.c:rebuild.h regexp_.c:regexp.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h sitemap_.c:sitemap.h skins_.c:skins.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h unicode_.c:unicode.h update_.c:update.h url_.c:url.h user_.c:user.h utf8_.c:utf8.h util_.c:util.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winfile_.c:winfile.h winhttp_.c:winhttp.h wysiwyg_.c:wysiwyg.h xfer_.c:xfer.h xfersetup_.c:xfersetup.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h $(SRCDIR)\cson_amalgamation.h |
| 832 | @copy /Y nul: headers |
| 833 |
+31
-3
| --- win/Makefile.mingw | ||
| +++ win/Makefile.mingw | ||
| @@ -87,11 +87,12 @@ | ||
| 87 | 87 | # This is useful when Tcl has been compiled statically with MinGW. |
| 88 | 88 | # |
| 89 | 89 | FOSSIL_TCL_SOURCE = 1 |
| 90 | 90 | |
| 91 | 91 | #### Check if the workaround for the MinGW command line handling needs to |
| 92 | -# be enabled by default. | |
| 92 | +# be enabled by default. This check may be somewhat fragile due to the | |
| 93 | +# use of "findstring". | |
| 93 | 94 | # |
| 94 | 95 | ifndef MINGW_IS_32BIT_ONLY |
| 95 | 96 | ifeq (,$(findstring w64-mingw32,$(PREFIX))) |
| 96 | 97 | MINGW_IS_32BIT_ONLY = 1 |
| 97 | 98 | endif |
| @@ -100,31 +101,46 @@ | ||
| 100 | 101 | #### The directories where the zlib include and library files are located. |
| 101 | 102 | # |
| 102 | 103 | ZINCDIR = $(SRCDIR)/../compat/zlib |
| 103 | 104 | ZLIBDIR = $(SRCDIR)/../compat/zlib |
| 104 | 105 | |
| 106 | +#### Make an attempt to detect if Fossil is being built for the x64 processor | |
| 107 | +# architecture. This check may be somewhat fragile due to "findstring". | |
| 108 | +# | |
| 105 | 109 | ifndef X64 |
| 106 | 110 | ifneq (,$(findstring x86_64-w64-mingw32,$(PREFIX))) |
| 107 | 111 | X64 = 1 |
| 108 | 112 | endif |
| 109 | 113 | endif |
| 110 | 114 | |
| 115 | +#### Determine if the optimized assembly routines provided with zlib should be | |
| 116 | +# used, taking into account whether zlib is actually enabled and the target | |
| 117 | +# processor architecture. | |
| 118 | +# | |
| 111 | 119 | ifndef X64 |
| 112 | 120 | SSLCONFIG = mingw |
| 113 | 121 | ifndef FOSSIL_ENABLE_MINIZ |
| 114 | 122 | ZLIBCONFIG = LOC="-DASMV -DASMINF" OBJA="inffas86.o match.o" |
| 115 | 123 | LIBTARGETS = $(ZLIBDIR)/inffas86.o $(ZLIBDIR)/match.o |
| 116 | 124 | else |
| 117 | -ZLIBCONFIG = | |
| 125 | +ZLIBCONFIG = | |
| 118 | 126 | LIBTARGETS = |
| 119 | 127 | endif |
| 120 | 128 | else |
| 121 | 129 | SSLCONFIG = mingw64 |
| 122 | -ZLIBCONFIG = | |
| 130 | +ZLIBCONFIG = | |
| 123 | 131 | LIBTARGETS = |
| 124 | 132 | endif |
| 125 | 133 | |
| 134 | +#### Disable creation of the OpenSSL shared libraries. Also, disable support | |
| 135 | +# for both SSLv2 and SSLv3 (i.e. thereby forcing the use of TLS). | |
| 136 | +# | |
| 137 | +SSLCONFIG += no-ssl2 no-ssl3 no-shared | |
| 138 | + | |
| 139 | +#### When using zlib, make sure that OpenSSL is configured to use the zlib | |
| 140 | +# that Fossil knows about (i.e. the one within the source tree). | |
| 141 | +# | |
| 126 | 142 | ifndef FOSSIL_ENABLE_MINIZ |
| 127 | 143 | SSLCONFIG += --with-zlib-lib=$(PWD)/$(ZLIBDIR) --with-zlib-include=$(PWD)/$(ZLIBDIR) zlib |
| 128 | 144 | endif |
| 129 | 145 | |
| 130 | 146 | #### The directories where the OpenSSL include and library files are located. |
| @@ -435,10 +451,11 @@ | ||
| 435 | 451 | $(SRCDIR)/schema.c \ |
| 436 | 452 | $(SRCDIR)/search.c \ |
| 437 | 453 | $(SRCDIR)/setup.c \ |
| 438 | 454 | $(SRCDIR)/sha1.c \ |
| 439 | 455 | $(SRCDIR)/shun.c \ |
| 456 | + $(SRCDIR)/sitemap.c \ | |
| 440 | 457 | $(SRCDIR)/skins.c \ |
| 441 | 458 | $(SRCDIR)/sqlcmd.c \ |
| 442 | 459 | $(SRCDIR)/stash.c \ |
| 443 | 460 | $(SRCDIR)/stat.c \ |
| 444 | 461 | $(SRCDIR)/style.c \ |
| @@ -556,10 +573,11 @@ | ||
| 556 | 573 | $(OBJDIR)/schema_.c \ |
| 557 | 574 | $(OBJDIR)/search_.c \ |
| 558 | 575 | $(OBJDIR)/setup_.c \ |
| 559 | 576 | $(OBJDIR)/sha1_.c \ |
| 560 | 577 | $(OBJDIR)/shun_.c \ |
| 578 | + $(OBJDIR)/sitemap_.c \ | |
| 561 | 579 | $(OBJDIR)/skins_.c \ |
| 562 | 580 | $(OBJDIR)/sqlcmd_.c \ |
| 563 | 581 | $(OBJDIR)/stash_.c \ |
| 564 | 582 | $(OBJDIR)/stat_.c \ |
| 565 | 583 | $(OBJDIR)/style_.c \ |
| @@ -674,10 +692,11 @@ | ||
| 674 | 692 | $(OBJDIR)/schema.o \ |
| 675 | 693 | $(OBJDIR)/search.o \ |
| 676 | 694 | $(OBJDIR)/setup.o \ |
| 677 | 695 | $(OBJDIR)/sha1.o \ |
| 678 | 696 | $(OBJDIR)/shun.o \ |
| 697 | + $(OBJDIR)/sitemap.o \ | |
| 679 | 698 | $(OBJDIR)/skins.o \ |
| 680 | 699 | $(OBJDIR)/sqlcmd.o \ |
| 681 | 700 | $(OBJDIR)/stash.o \ |
| 682 | 701 | $(OBJDIR)/stat.o \ |
| 683 | 702 | $(OBJDIR)/style.o \ |
| @@ -985,10 +1004,11 @@ | ||
| 985 | 1004 | $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \ |
| 986 | 1005 | $(OBJDIR)/search_.c:$(OBJDIR)/search.h \ |
| 987 | 1006 | $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \ |
| 988 | 1007 | $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h \ |
| 989 | 1008 | $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h \ |
| 1009 | + $(OBJDIR)/sitemap_.c:$(OBJDIR)/sitemap.h \ | |
| 990 | 1010 | $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \ |
| 991 | 1011 | $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \ |
| 992 | 1012 | $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h \ |
| 993 | 1013 | $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h \ |
| 994 | 1014 | $(OBJDIR)/style_.c:$(OBJDIR)/style.h \ |
| @@ -1718,10 +1738,18 @@ | ||
| 1718 | 1738 | |
| 1719 | 1739 | $(OBJDIR)/shun.o: $(OBJDIR)/shun_.c $(OBJDIR)/shun.h $(SRCDIR)/config.h |
| 1720 | 1740 | $(XTCC) -o $(OBJDIR)/shun.o -c $(OBJDIR)/shun_.c |
| 1721 | 1741 | |
| 1722 | 1742 | $(OBJDIR)/shun.h: $(OBJDIR)/headers |
| 1743 | + | |
| 1744 | +$(OBJDIR)/sitemap_.c: $(SRCDIR)/sitemap.c $(TRANSLATE) | |
| 1745 | + $(TRANSLATE) $(SRCDIR)/sitemap.c >$@ | |
| 1746 | + | |
| 1747 | +$(OBJDIR)/sitemap.o: $(OBJDIR)/sitemap_.c $(OBJDIR)/sitemap.h $(SRCDIR)/config.h | |
| 1748 | + $(XTCC) -o $(OBJDIR)/sitemap.o -c $(OBJDIR)/sitemap_.c | |
| 1749 | + | |
| 1750 | +$(OBJDIR)/sitemap.h: $(OBJDIR)/headers | |
| 1723 | 1751 | |
| 1724 | 1752 | $(OBJDIR)/skins_.c: $(SRCDIR)/skins.c $(TRANSLATE) |
| 1725 | 1753 | $(TRANSLATE) $(SRCDIR)/skins.c >$@ |
| 1726 | 1754 | |
| 1727 | 1755 | $(OBJDIR)/skins.o: $(OBJDIR)/skins_.c $(OBJDIR)/skins.h $(SRCDIR)/config.h |
| 1728 | 1756 |
| --- win/Makefile.mingw | |
| +++ win/Makefile.mingw | |
| @@ -87,11 +87,12 @@ | |
| 87 | # This is useful when Tcl has been compiled statically with MinGW. |
| 88 | # |
| 89 | FOSSIL_TCL_SOURCE = 1 |
| 90 | |
| 91 | #### Check if the workaround for the MinGW command line handling needs to |
| 92 | # be enabled by default. |
| 93 | # |
| 94 | ifndef MINGW_IS_32BIT_ONLY |
| 95 | ifeq (,$(findstring w64-mingw32,$(PREFIX))) |
| 96 | MINGW_IS_32BIT_ONLY = 1 |
| 97 | endif |
| @@ -100,31 +101,46 @@ | |
| 100 | #### The directories where the zlib include and library files are located. |
| 101 | # |
| 102 | ZINCDIR = $(SRCDIR)/../compat/zlib |
| 103 | ZLIBDIR = $(SRCDIR)/../compat/zlib |
| 104 | |
| 105 | ifndef X64 |
| 106 | ifneq (,$(findstring x86_64-w64-mingw32,$(PREFIX))) |
| 107 | X64 = 1 |
| 108 | endif |
| 109 | endif |
| 110 | |
| 111 | ifndef X64 |
| 112 | SSLCONFIG = mingw |
| 113 | ifndef FOSSIL_ENABLE_MINIZ |
| 114 | ZLIBCONFIG = LOC="-DASMV -DASMINF" OBJA="inffas86.o match.o" |
| 115 | LIBTARGETS = $(ZLIBDIR)/inffas86.o $(ZLIBDIR)/match.o |
| 116 | else |
| 117 | ZLIBCONFIG = |
| 118 | LIBTARGETS = |
| 119 | endif |
| 120 | else |
| 121 | SSLCONFIG = mingw64 |
| 122 | ZLIBCONFIG = |
| 123 | LIBTARGETS = |
| 124 | endif |
| 125 | |
| 126 | ifndef FOSSIL_ENABLE_MINIZ |
| 127 | SSLCONFIG += --with-zlib-lib=$(PWD)/$(ZLIBDIR) --with-zlib-include=$(PWD)/$(ZLIBDIR) zlib |
| 128 | endif |
| 129 | |
| 130 | #### The directories where the OpenSSL include and library files are located. |
| @@ -435,10 +451,11 @@ | |
| 435 | $(SRCDIR)/schema.c \ |
| 436 | $(SRCDIR)/search.c \ |
| 437 | $(SRCDIR)/setup.c \ |
| 438 | $(SRCDIR)/sha1.c \ |
| 439 | $(SRCDIR)/shun.c \ |
| 440 | $(SRCDIR)/skins.c \ |
| 441 | $(SRCDIR)/sqlcmd.c \ |
| 442 | $(SRCDIR)/stash.c \ |
| 443 | $(SRCDIR)/stat.c \ |
| 444 | $(SRCDIR)/style.c \ |
| @@ -556,10 +573,11 @@ | |
| 556 | $(OBJDIR)/schema_.c \ |
| 557 | $(OBJDIR)/search_.c \ |
| 558 | $(OBJDIR)/setup_.c \ |
| 559 | $(OBJDIR)/sha1_.c \ |
| 560 | $(OBJDIR)/shun_.c \ |
| 561 | $(OBJDIR)/skins_.c \ |
| 562 | $(OBJDIR)/sqlcmd_.c \ |
| 563 | $(OBJDIR)/stash_.c \ |
| 564 | $(OBJDIR)/stat_.c \ |
| 565 | $(OBJDIR)/style_.c \ |
| @@ -674,10 +692,11 @@ | |
| 674 | $(OBJDIR)/schema.o \ |
| 675 | $(OBJDIR)/search.o \ |
| 676 | $(OBJDIR)/setup.o \ |
| 677 | $(OBJDIR)/sha1.o \ |
| 678 | $(OBJDIR)/shun.o \ |
| 679 | $(OBJDIR)/skins.o \ |
| 680 | $(OBJDIR)/sqlcmd.o \ |
| 681 | $(OBJDIR)/stash.o \ |
| 682 | $(OBJDIR)/stat.o \ |
| 683 | $(OBJDIR)/style.o \ |
| @@ -985,10 +1004,11 @@ | |
| 985 | $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \ |
| 986 | $(OBJDIR)/search_.c:$(OBJDIR)/search.h \ |
| 987 | $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \ |
| 988 | $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h \ |
| 989 | $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h \ |
| 990 | $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \ |
| 991 | $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \ |
| 992 | $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h \ |
| 993 | $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h \ |
| 994 | $(OBJDIR)/style_.c:$(OBJDIR)/style.h \ |
| @@ -1718,10 +1738,18 @@ | |
| 1718 | |
| 1719 | $(OBJDIR)/shun.o: $(OBJDIR)/shun_.c $(OBJDIR)/shun.h $(SRCDIR)/config.h |
| 1720 | $(XTCC) -o $(OBJDIR)/shun.o -c $(OBJDIR)/shun_.c |
| 1721 | |
| 1722 | $(OBJDIR)/shun.h: $(OBJDIR)/headers |
| 1723 | |
| 1724 | $(OBJDIR)/skins_.c: $(SRCDIR)/skins.c $(TRANSLATE) |
| 1725 | $(TRANSLATE) $(SRCDIR)/skins.c >$@ |
| 1726 | |
| 1727 | $(OBJDIR)/skins.o: $(OBJDIR)/skins_.c $(OBJDIR)/skins.h $(SRCDIR)/config.h |
| 1728 |
| --- win/Makefile.mingw | |
| +++ win/Makefile.mingw | |
| @@ -87,11 +87,12 @@ | |
| 87 | # This is useful when Tcl has been compiled statically with MinGW. |
| 88 | # |
| 89 | FOSSIL_TCL_SOURCE = 1 |
| 90 | |
| 91 | #### Check if the workaround for the MinGW command line handling needs to |
| 92 | # be enabled by default. This check may be somewhat fragile due to the |
| 93 | # use of "findstring". |
| 94 | # |
| 95 | ifndef MINGW_IS_32BIT_ONLY |
| 96 | ifeq (,$(findstring w64-mingw32,$(PREFIX))) |
| 97 | MINGW_IS_32BIT_ONLY = 1 |
| 98 | endif |
| @@ -100,31 +101,46 @@ | |
| 101 | #### The directories where the zlib include and library files are located. |
| 102 | # |
| 103 | ZINCDIR = $(SRCDIR)/../compat/zlib |
| 104 | ZLIBDIR = $(SRCDIR)/../compat/zlib |
| 105 | |
| 106 | #### Make an attempt to detect if Fossil is being built for the x64 processor |
| 107 | # architecture. This check may be somewhat fragile due to "findstring". |
| 108 | # |
| 109 | ifndef X64 |
| 110 | ifneq (,$(findstring x86_64-w64-mingw32,$(PREFIX))) |
| 111 | X64 = 1 |
| 112 | endif |
| 113 | endif |
| 114 | |
| 115 | #### Determine if the optimized assembly routines provided with zlib should be |
| 116 | # used, taking into account whether zlib is actually enabled and the target |
| 117 | # processor architecture. |
| 118 | # |
| 119 | ifndef X64 |
| 120 | SSLCONFIG = mingw |
| 121 | ifndef FOSSIL_ENABLE_MINIZ |
| 122 | ZLIBCONFIG = LOC="-DASMV -DASMINF" OBJA="inffas86.o match.o" |
| 123 | LIBTARGETS = $(ZLIBDIR)/inffas86.o $(ZLIBDIR)/match.o |
| 124 | else |
| 125 | ZLIBCONFIG = |
| 126 | LIBTARGETS = |
| 127 | endif |
| 128 | else |
| 129 | SSLCONFIG = mingw64 |
| 130 | ZLIBCONFIG = |
| 131 | LIBTARGETS = |
| 132 | endif |
| 133 | |
| 134 | #### Disable creation of the OpenSSL shared libraries. Also, disable support |
| 135 | # for both SSLv2 and SSLv3 (i.e. thereby forcing the use of TLS). |
| 136 | # |
| 137 | SSLCONFIG += no-ssl2 no-ssl3 no-shared |
| 138 | |
| 139 | #### When using zlib, make sure that OpenSSL is configured to use the zlib |
| 140 | # that Fossil knows about (i.e. the one within the source tree). |
| 141 | # |
| 142 | ifndef FOSSIL_ENABLE_MINIZ |
| 143 | SSLCONFIG += --with-zlib-lib=$(PWD)/$(ZLIBDIR) --with-zlib-include=$(PWD)/$(ZLIBDIR) zlib |
| 144 | endif |
| 145 | |
| 146 | #### The directories where the OpenSSL include and library files are located. |
| @@ -435,10 +451,11 @@ | |
| 451 | $(SRCDIR)/schema.c \ |
| 452 | $(SRCDIR)/search.c \ |
| 453 | $(SRCDIR)/setup.c \ |
| 454 | $(SRCDIR)/sha1.c \ |
| 455 | $(SRCDIR)/shun.c \ |
| 456 | $(SRCDIR)/sitemap.c \ |
| 457 | $(SRCDIR)/skins.c \ |
| 458 | $(SRCDIR)/sqlcmd.c \ |
| 459 | $(SRCDIR)/stash.c \ |
| 460 | $(SRCDIR)/stat.c \ |
| 461 | $(SRCDIR)/style.c \ |
| @@ -556,10 +573,11 @@ | |
| 573 | $(OBJDIR)/schema_.c \ |
| 574 | $(OBJDIR)/search_.c \ |
| 575 | $(OBJDIR)/setup_.c \ |
| 576 | $(OBJDIR)/sha1_.c \ |
| 577 | $(OBJDIR)/shun_.c \ |
| 578 | $(OBJDIR)/sitemap_.c \ |
| 579 | $(OBJDIR)/skins_.c \ |
| 580 | $(OBJDIR)/sqlcmd_.c \ |
| 581 | $(OBJDIR)/stash_.c \ |
| 582 | $(OBJDIR)/stat_.c \ |
| 583 | $(OBJDIR)/style_.c \ |
| @@ -674,10 +692,11 @@ | |
| 692 | $(OBJDIR)/schema.o \ |
| 693 | $(OBJDIR)/search.o \ |
| 694 | $(OBJDIR)/setup.o \ |
| 695 | $(OBJDIR)/sha1.o \ |
| 696 | $(OBJDIR)/shun.o \ |
| 697 | $(OBJDIR)/sitemap.o \ |
| 698 | $(OBJDIR)/skins.o \ |
| 699 | $(OBJDIR)/sqlcmd.o \ |
| 700 | $(OBJDIR)/stash.o \ |
| 701 | $(OBJDIR)/stat.o \ |
| 702 | $(OBJDIR)/style.o \ |
| @@ -985,10 +1004,11 @@ | |
| 1004 | $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \ |
| 1005 | $(OBJDIR)/search_.c:$(OBJDIR)/search.h \ |
| 1006 | $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \ |
| 1007 | $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h \ |
| 1008 | $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h \ |
| 1009 | $(OBJDIR)/sitemap_.c:$(OBJDIR)/sitemap.h \ |
| 1010 | $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \ |
| 1011 | $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \ |
| 1012 | $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h \ |
| 1013 | $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h \ |
| 1014 | $(OBJDIR)/style_.c:$(OBJDIR)/style.h \ |
| @@ -1718,10 +1738,18 @@ | |
| 1738 | |
| 1739 | $(OBJDIR)/shun.o: $(OBJDIR)/shun_.c $(OBJDIR)/shun.h $(SRCDIR)/config.h |
| 1740 | $(XTCC) -o $(OBJDIR)/shun.o -c $(OBJDIR)/shun_.c |
| 1741 | |
| 1742 | $(OBJDIR)/shun.h: $(OBJDIR)/headers |
| 1743 | |
| 1744 | $(OBJDIR)/sitemap_.c: $(SRCDIR)/sitemap.c $(TRANSLATE) |
| 1745 | $(TRANSLATE) $(SRCDIR)/sitemap.c >$@ |
| 1746 | |
| 1747 | $(OBJDIR)/sitemap.o: $(OBJDIR)/sitemap_.c $(OBJDIR)/sitemap.h $(SRCDIR)/config.h |
| 1748 | $(XTCC) -o $(OBJDIR)/sitemap.o -c $(OBJDIR)/sitemap_.c |
| 1749 | |
| 1750 | $(OBJDIR)/sitemap.h: $(OBJDIR)/headers |
| 1751 | |
| 1752 | $(OBJDIR)/skins_.c: $(SRCDIR)/skins.c $(TRANSLATE) |
| 1753 | $(TRANSLATE) $(SRCDIR)/skins.c >$@ |
| 1754 | |
| 1755 | $(OBJDIR)/skins.o: $(OBJDIR)/skins_.c $(OBJDIR)/skins.h $(SRCDIR)/config.h |
| 1756 |
+83
-2
| --- win/Makefile.mingw.mistachkin | ||
| +++ win/Makefile.mingw.mistachkin | ||
| @@ -87,11 +87,12 @@ | ||
| 87 | 87 | # This is useful when Tcl has been compiled statically with MinGW. |
| 88 | 88 | # |
| 89 | 89 | FOSSIL_TCL_SOURCE = 1 |
| 90 | 90 | |
| 91 | 91 | #### Check if the workaround for the MinGW command line handling needs to |
| 92 | -# be enabled by default. | |
| 92 | +# be enabled by default. This check may be somewhat fragile due to the | |
| 93 | +# use of "findstring". | |
| 93 | 94 | # |
| 94 | 95 | ifndef MINGW_IS_32BIT_ONLY |
| 95 | 96 | ifeq (,$(findstring w64-mingw32,$(PREFIX))) |
| 96 | 97 | MINGW_IS_32BIT_ONLY = 1 |
| 97 | 98 | endif |
| @@ -100,26 +101,46 @@ | ||
| 100 | 101 | #### The directories where the zlib include and library files are located. |
| 101 | 102 | # |
| 102 | 103 | ZINCDIR = $(SRCDIR)/../compat/zlib |
| 103 | 104 | ZLIBDIR = $(SRCDIR)/../compat/zlib |
| 104 | 105 | |
| 106 | +#### Make an attempt to detect if Fossil is being built for the x64 processor | |
| 107 | +# architecture. This check may be somewhat fragile due to "findstring". | |
| 108 | +# | |
| 105 | 109 | ifndef X64 |
| 106 | 110 | ifneq (,$(findstring x86_64-w64-mingw32,$(PREFIX))) |
| 107 | 111 | X64 = 1 |
| 108 | 112 | endif |
| 109 | 113 | endif |
| 110 | 114 | |
| 115 | +#### Determine if the optimized assembly routines provided with zlib should be | |
| 116 | +# used, taking into account whether zlib is actually enabled and the target | |
| 117 | +# processor architecture. | |
| 118 | +# | |
| 111 | 119 | ifndef X64 |
| 112 | 120 | SSLCONFIG = mingw |
| 121 | +ifndef FOSSIL_ENABLE_MINIZ | |
| 113 | 122 | ZLIBCONFIG = LOC="-DASMV -DASMINF" OBJA="inffas86.o match.o" |
| 114 | 123 | LIBTARGETS = $(ZLIBDIR)/inffas86.o $(ZLIBDIR)/match.o |
| 124 | +else | |
| 125 | +ZLIBCONFIG = | |
| 126 | +LIBTARGETS = | |
| 127 | +endif | |
| 115 | 128 | else |
| 116 | 129 | SSLCONFIG = mingw64 |
| 117 | -ZLIBCONFIG = | |
| 130 | +ZLIBCONFIG = | |
| 118 | 131 | LIBTARGETS = |
| 119 | 132 | endif |
| 120 | 133 | |
| 134 | +#### Disable creation of the OpenSSL shared libraries. Also, disable support | |
| 135 | +# for both SSLv2 and SSLv3 (i.e. thereby forcing the use of TLS). | |
| 136 | +# | |
| 137 | +SSLCONFIG += no-ssl2 no-ssl3 no-shared | |
| 138 | + | |
| 139 | +#### When using zlib, make sure that OpenSSL is configured to use the zlib | |
| 140 | +# that Fossil knows about (i.e. the one within the source tree). | |
| 141 | +# | |
| 121 | 142 | ifndef FOSSIL_ENABLE_MINIZ |
| 122 | 143 | SSLCONFIG += --with-zlib-lib=$(PWD)/$(ZLIBDIR) --with-zlib-include=$(PWD)/$(ZLIBDIR) zlib |
| 123 | 144 | endif |
| 124 | 145 | |
| 125 | 146 | #### The directories where the OpenSSL include and library files are located. |
| @@ -352,10 +373,11 @@ | ||
| 352 | 373 | $(SRCDIR)/bisect.c \ |
| 353 | 374 | $(SRCDIR)/blob.c \ |
| 354 | 375 | $(SRCDIR)/branch.c \ |
| 355 | 376 | $(SRCDIR)/browse.c \ |
| 356 | 377 | $(SRCDIR)/builtin.c \ |
| 378 | + $(SRCDIR)/bundle.c \ | |
| 357 | 379 | $(SRCDIR)/cache.c \ |
| 358 | 380 | $(SRCDIR)/captcha.c \ |
| 359 | 381 | $(SRCDIR)/cgi.c \ |
| 360 | 382 | $(SRCDIR)/checkin.c \ |
| 361 | 383 | $(SRCDIR)/checkout.c \ |
| @@ -374,10 +396,11 @@ | ||
| 374 | 396 | $(SRCDIR)/encode.c \ |
| 375 | 397 | $(SRCDIR)/event.c \ |
| 376 | 398 | $(SRCDIR)/export.c \ |
| 377 | 399 | $(SRCDIR)/file.c \ |
| 378 | 400 | $(SRCDIR)/finfo.c \ |
| 401 | + $(SRCDIR)/foci.c \ | |
| 379 | 402 | $(SRCDIR)/fusefs.c \ |
| 380 | 403 | $(SRCDIR)/glob.c \ |
| 381 | 404 | $(SRCDIR)/graph.c \ |
| 382 | 405 | $(SRCDIR)/gzip.c \ |
| 383 | 406 | $(SRCDIR)/http.c \ |
| @@ -417,19 +440,22 @@ | ||
| 417 | 440 | $(SRCDIR)/path.c \ |
| 418 | 441 | $(SRCDIR)/pivot.c \ |
| 419 | 442 | $(SRCDIR)/popen.c \ |
| 420 | 443 | $(SRCDIR)/pqueue.c \ |
| 421 | 444 | $(SRCDIR)/printf.c \ |
| 445 | + $(SRCDIR)/publish.c \ | |
| 446 | + $(SRCDIR)/purge.c \ | |
| 422 | 447 | $(SRCDIR)/rebuild.c \ |
| 423 | 448 | $(SRCDIR)/regexp.c \ |
| 424 | 449 | $(SRCDIR)/report.c \ |
| 425 | 450 | $(SRCDIR)/rss.c \ |
| 426 | 451 | $(SRCDIR)/schema.c \ |
| 427 | 452 | $(SRCDIR)/search.c \ |
| 428 | 453 | $(SRCDIR)/setup.c \ |
| 429 | 454 | $(SRCDIR)/sha1.c \ |
| 430 | 455 | $(SRCDIR)/shun.c \ |
| 456 | + $(SRCDIR)/sitemap.c \ | |
| 431 | 457 | $(SRCDIR)/skins.c \ |
| 432 | 458 | $(SRCDIR)/sqlcmd.c \ |
| 433 | 459 | $(SRCDIR)/stash.c \ |
| 434 | 460 | $(SRCDIR)/stat.c \ |
| 435 | 461 | $(SRCDIR)/style.c \ |
| @@ -469,10 +495,11 @@ | ||
| 469 | 495 | $(OBJDIR)/bisect_.c \ |
| 470 | 496 | $(OBJDIR)/blob_.c \ |
| 471 | 497 | $(OBJDIR)/branch_.c \ |
| 472 | 498 | $(OBJDIR)/browse_.c \ |
| 473 | 499 | $(OBJDIR)/builtin_.c \ |
| 500 | + $(OBJDIR)/bundle_.c \ | |
| 474 | 501 | $(OBJDIR)/cache_.c \ |
| 475 | 502 | $(OBJDIR)/captcha_.c \ |
| 476 | 503 | $(OBJDIR)/cgi_.c \ |
| 477 | 504 | $(OBJDIR)/checkin_.c \ |
| 478 | 505 | $(OBJDIR)/checkout_.c \ |
| @@ -491,10 +518,11 @@ | ||
| 491 | 518 | $(OBJDIR)/encode_.c \ |
| 492 | 519 | $(OBJDIR)/event_.c \ |
| 493 | 520 | $(OBJDIR)/export_.c \ |
| 494 | 521 | $(OBJDIR)/file_.c \ |
| 495 | 522 | $(OBJDIR)/finfo_.c \ |
| 523 | + $(OBJDIR)/foci_.c \ | |
| 496 | 524 | $(OBJDIR)/fusefs_.c \ |
| 497 | 525 | $(OBJDIR)/glob_.c \ |
| 498 | 526 | $(OBJDIR)/graph_.c \ |
| 499 | 527 | $(OBJDIR)/gzip_.c \ |
| 500 | 528 | $(OBJDIR)/http_.c \ |
| @@ -534,19 +562,22 @@ | ||
| 534 | 562 | $(OBJDIR)/path_.c \ |
| 535 | 563 | $(OBJDIR)/pivot_.c \ |
| 536 | 564 | $(OBJDIR)/popen_.c \ |
| 537 | 565 | $(OBJDIR)/pqueue_.c \ |
| 538 | 566 | $(OBJDIR)/printf_.c \ |
| 567 | + $(OBJDIR)/publish_.c \ | |
| 568 | + $(OBJDIR)/purge_.c \ | |
| 539 | 569 | $(OBJDIR)/rebuild_.c \ |
| 540 | 570 | $(OBJDIR)/regexp_.c \ |
| 541 | 571 | $(OBJDIR)/report_.c \ |
| 542 | 572 | $(OBJDIR)/rss_.c \ |
| 543 | 573 | $(OBJDIR)/schema_.c \ |
| 544 | 574 | $(OBJDIR)/search_.c \ |
| 545 | 575 | $(OBJDIR)/setup_.c \ |
| 546 | 576 | $(OBJDIR)/sha1_.c \ |
| 547 | 577 | $(OBJDIR)/shun_.c \ |
| 578 | + $(OBJDIR)/sitemap_.c \ | |
| 548 | 579 | $(OBJDIR)/skins_.c \ |
| 549 | 580 | $(OBJDIR)/sqlcmd_.c \ |
| 550 | 581 | $(OBJDIR)/stash_.c \ |
| 551 | 582 | $(OBJDIR)/stat_.c \ |
| 552 | 583 | $(OBJDIR)/style_.c \ |
| @@ -583,10 +614,11 @@ | ||
| 583 | 614 | $(OBJDIR)/bisect.o \ |
| 584 | 615 | $(OBJDIR)/blob.o \ |
| 585 | 616 | $(OBJDIR)/branch.o \ |
| 586 | 617 | $(OBJDIR)/browse.o \ |
| 587 | 618 | $(OBJDIR)/builtin.o \ |
| 619 | + $(OBJDIR)/bundle.o \ | |
| 588 | 620 | $(OBJDIR)/cache.o \ |
| 589 | 621 | $(OBJDIR)/captcha.o \ |
| 590 | 622 | $(OBJDIR)/cgi.o \ |
| 591 | 623 | $(OBJDIR)/checkin.o \ |
| 592 | 624 | $(OBJDIR)/checkout.o \ |
| @@ -605,10 +637,11 @@ | ||
| 605 | 637 | $(OBJDIR)/encode.o \ |
| 606 | 638 | $(OBJDIR)/event.o \ |
| 607 | 639 | $(OBJDIR)/export.o \ |
| 608 | 640 | $(OBJDIR)/file.o \ |
| 609 | 641 | $(OBJDIR)/finfo.o \ |
| 642 | + $(OBJDIR)/foci.o \ | |
| 610 | 643 | $(OBJDIR)/fusefs.o \ |
| 611 | 644 | $(OBJDIR)/glob.o \ |
| 612 | 645 | $(OBJDIR)/graph.o \ |
| 613 | 646 | $(OBJDIR)/gzip.o \ |
| 614 | 647 | $(OBJDIR)/http.o \ |
| @@ -648,19 +681,22 @@ | ||
| 648 | 681 | $(OBJDIR)/path.o \ |
| 649 | 682 | $(OBJDIR)/pivot.o \ |
| 650 | 683 | $(OBJDIR)/popen.o \ |
| 651 | 684 | $(OBJDIR)/pqueue.o \ |
| 652 | 685 | $(OBJDIR)/printf.o \ |
| 686 | + $(OBJDIR)/publish.o \ | |
| 687 | + $(OBJDIR)/purge.o \ | |
| 653 | 688 | $(OBJDIR)/rebuild.o \ |
| 654 | 689 | $(OBJDIR)/regexp.o \ |
| 655 | 690 | $(OBJDIR)/report.o \ |
| 656 | 691 | $(OBJDIR)/rss.o \ |
| 657 | 692 | $(OBJDIR)/schema.o \ |
| 658 | 693 | $(OBJDIR)/search.o \ |
| 659 | 694 | $(OBJDIR)/setup.o \ |
| 660 | 695 | $(OBJDIR)/sha1.o \ |
| 661 | 696 | $(OBJDIR)/shun.o \ |
| 697 | + $(OBJDIR)/sitemap.o \ | |
| 662 | 698 | $(OBJDIR)/skins.o \ |
| 663 | 699 | $(OBJDIR)/sqlcmd.o \ |
| 664 | 700 | $(OBJDIR)/stash.o \ |
| 665 | 701 | $(OBJDIR)/stat.o \ |
| 666 | 702 | $(OBJDIR)/style.o \ |
| @@ -890,10 +926,11 @@ | ||
| 890 | 926 | $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h \ |
| 891 | 927 | $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h \ |
| 892 | 928 | $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h \ |
| 893 | 929 | $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h \ |
| 894 | 930 | $(OBJDIR)/builtin_.c:$(OBJDIR)/builtin.h \ |
| 931 | + $(OBJDIR)/bundle_.c:$(OBJDIR)/bundle.h \ | |
| 895 | 932 | $(OBJDIR)/cache_.c:$(OBJDIR)/cache.h \ |
| 896 | 933 | $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h \ |
| 897 | 934 | $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h \ |
| 898 | 935 | $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h \ |
| 899 | 936 | $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h \ |
| @@ -912,10 +949,11 @@ | ||
| 912 | 949 | $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h \ |
| 913 | 950 | $(OBJDIR)/event_.c:$(OBJDIR)/event.h \ |
| 914 | 951 | $(OBJDIR)/export_.c:$(OBJDIR)/export.h \ |
| 915 | 952 | $(OBJDIR)/file_.c:$(OBJDIR)/file.h \ |
| 916 | 953 | $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h \ |
| 954 | + $(OBJDIR)/foci_.c:$(OBJDIR)/foci.h \ | |
| 917 | 955 | $(OBJDIR)/fusefs_.c:$(OBJDIR)/fusefs.h \ |
| 918 | 956 | $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h \ |
| 919 | 957 | $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h \ |
| 920 | 958 | $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h \ |
| 921 | 959 | $(OBJDIR)/http_.c:$(OBJDIR)/http.h \ |
| @@ -955,19 +993,22 @@ | ||
| 955 | 993 | $(OBJDIR)/path_.c:$(OBJDIR)/path.h \ |
| 956 | 994 | $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \ |
| 957 | 995 | $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h \ |
| 958 | 996 | $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h \ |
| 959 | 997 | $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h \ |
| 998 | + $(OBJDIR)/publish_.c:$(OBJDIR)/publish.h \ | |
| 999 | + $(OBJDIR)/purge_.c:$(OBJDIR)/purge.h \ | |
| 960 | 1000 | $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h \ |
| 961 | 1001 | $(OBJDIR)/regexp_.c:$(OBJDIR)/regexp.h \ |
| 962 | 1002 | $(OBJDIR)/report_.c:$(OBJDIR)/report.h \ |
| 963 | 1003 | $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \ |
| 964 | 1004 | $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \ |
| 965 | 1005 | $(OBJDIR)/search_.c:$(OBJDIR)/search.h \ |
| 966 | 1006 | $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \ |
| 967 | 1007 | $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h \ |
| 968 | 1008 | $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h \ |
| 1009 | + $(OBJDIR)/sitemap_.c:$(OBJDIR)/sitemap.h \ | |
| 969 | 1010 | $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \ |
| 970 | 1011 | $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \ |
| 971 | 1012 | $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h \ |
| 972 | 1013 | $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h \ |
| 973 | 1014 | $(OBJDIR)/style_.c:$(OBJDIR)/style.h \ |
| @@ -1073,10 +1114,18 @@ | ||
| 1073 | 1114 | |
| 1074 | 1115 | $(OBJDIR)/builtin.o: $(OBJDIR)/builtin_.c $(OBJDIR)/builtin.h $(OBJDIR)/builtin_data.h $(SRCDIR)/config.h |
| 1075 | 1116 | $(XTCC) -o $(OBJDIR)/builtin.o -c $(OBJDIR)/builtin_.c |
| 1076 | 1117 | |
| 1077 | 1118 | $(OBJDIR)/builtin.h: $(OBJDIR)/headers |
| 1119 | + | |
| 1120 | +$(OBJDIR)/bundle_.c: $(SRCDIR)/bundle.c $(TRANSLATE) | |
| 1121 | + $(TRANSLATE) $(SRCDIR)/bundle.c >$@ | |
| 1122 | + | |
| 1123 | +$(OBJDIR)/bundle.o: $(OBJDIR)/bundle_.c $(OBJDIR)/bundle.h $(SRCDIR)/config.h | |
| 1124 | + $(XTCC) -o $(OBJDIR)/bundle.o -c $(OBJDIR)/bundle_.c | |
| 1125 | + | |
| 1126 | +$(OBJDIR)/bundle.h: $(OBJDIR)/headers | |
| 1078 | 1127 | |
| 1079 | 1128 | $(OBJDIR)/cache_.c: $(SRCDIR)/cache.c $(TRANSLATE) |
| 1080 | 1129 | $(TRANSLATE) $(SRCDIR)/cache.c >$@ |
| 1081 | 1130 | |
| 1082 | 1131 | $(OBJDIR)/cache.o: $(OBJDIR)/cache_.c $(OBJDIR)/cache.h $(SRCDIR)/config.h |
| @@ -1249,10 +1298,18 @@ | ||
| 1249 | 1298 | |
| 1250 | 1299 | $(OBJDIR)/finfo.o: $(OBJDIR)/finfo_.c $(OBJDIR)/finfo.h $(SRCDIR)/config.h |
| 1251 | 1300 | $(XTCC) -o $(OBJDIR)/finfo.o -c $(OBJDIR)/finfo_.c |
| 1252 | 1301 | |
| 1253 | 1302 | $(OBJDIR)/finfo.h: $(OBJDIR)/headers |
| 1303 | + | |
| 1304 | +$(OBJDIR)/foci_.c: $(SRCDIR)/foci.c $(TRANSLATE) | |
| 1305 | + $(TRANSLATE) $(SRCDIR)/foci.c >$@ | |
| 1306 | + | |
| 1307 | +$(OBJDIR)/foci.o: $(OBJDIR)/foci_.c $(OBJDIR)/foci.h $(SRCDIR)/config.h | |
| 1308 | + $(XTCC) -o $(OBJDIR)/foci.o -c $(OBJDIR)/foci_.c | |
| 1309 | + | |
| 1310 | +$(OBJDIR)/foci.h: $(OBJDIR)/headers | |
| 1254 | 1311 | |
| 1255 | 1312 | $(OBJDIR)/fusefs_.c: $(SRCDIR)/fusefs.c $(TRANSLATE) |
| 1256 | 1313 | $(TRANSLATE) $(SRCDIR)/fusefs.c >$@ |
| 1257 | 1314 | |
| 1258 | 1315 | $(OBJDIR)/fusefs.o: $(OBJDIR)/fusefs_.c $(OBJDIR)/fusefs.h $(SRCDIR)/config.h |
| @@ -1593,10 +1650,26 @@ | ||
| 1593 | 1650 | |
| 1594 | 1651 | $(OBJDIR)/printf.o: $(OBJDIR)/printf_.c $(OBJDIR)/printf.h $(SRCDIR)/config.h |
| 1595 | 1652 | $(XTCC) -o $(OBJDIR)/printf.o -c $(OBJDIR)/printf_.c |
| 1596 | 1653 | |
| 1597 | 1654 | $(OBJDIR)/printf.h: $(OBJDIR)/headers |
| 1655 | + | |
| 1656 | +$(OBJDIR)/publish_.c: $(SRCDIR)/publish.c $(TRANSLATE) | |
| 1657 | + $(TRANSLATE) $(SRCDIR)/publish.c >$@ | |
| 1658 | + | |
| 1659 | +$(OBJDIR)/publish.o: $(OBJDIR)/publish_.c $(OBJDIR)/publish.h $(SRCDIR)/config.h | |
| 1660 | + $(XTCC) -o $(OBJDIR)/publish.o -c $(OBJDIR)/publish_.c | |
| 1661 | + | |
| 1662 | +$(OBJDIR)/publish.h: $(OBJDIR)/headers | |
| 1663 | + | |
| 1664 | +$(OBJDIR)/purge_.c: $(SRCDIR)/purge.c $(TRANSLATE) | |
| 1665 | + $(TRANSLATE) $(SRCDIR)/purge.c >$@ | |
| 1666 | + | |
| 1667 | +$(OBJDIR)/purge.o: $(OBJDIR)/purge_.c $(OBJDIR)/purge.h $(SRCDIR)/config.h | |
| 1668 | + $(XTCC) -o $(OBJDIR)/purge.o -c $(OBJDIR)/purge_.c | |
| 1669 | + | |
| 1670 | +$(OBJDIR)/purge.h: $(OBJDIR)/headers | |
| 1598 | 1671 | |
| 1599 | 1672 | $(OBJDIR)/rebuild_.c: $(SRCDIR)/rebuild.c $(TRANSLATE) |
| 1600 | 1673 | $(TRANSLATE) $(SRCDIR)/rebuild.c >$@ |
| 1601 | 1674 | |
| 1602 | 1675 | $(OBJDIR)/rebuild.o: $(OBJDIR)/rebuild_.c $(OBJDIR)/rebuild.h $(SRCDIR)/config.h |
| @@ -1665,10 +1738,18 @@ | ||
| 1665 | 1738 | |
| 1666 | 1739 | $(OBJDIR)/shun.o: $(OBJDIR)/shun_.c $(OBJDIR)/shun.h $(SRCDIR)/config.h |
| 1667 | 1740 | $(XTCC) -o $(OBJDIR)/shun.o -c $(OBJDIR)/shun_.c |
| 1668 | 1741 | |
| 1669 | 1742 | $(OBJDIR)/shun.h: $(OBJDIR)/headers |
| 1743 | + | |
| 1744 | +$(OBJDIR)/sitemap_.c: $(SRCDIR)/sitemap.c $(TRANSLATE) | |
| 1745 | + $(TRANSLATE) $(SRCDIR)/sitemap.c >$@ | |
| 1746 | + | |
| 1747 | +$(OBJDIR)/sitemap.o: $(OBJDIR)/sitemap_.c $(OBJDIR)/sitemap.h $(SRCDIR)/config.h | |
| 1748 | + $(XTCC) -o $(OBJDIR)/sitemap.o -c $(OBJDIR)/sitemap_.c | |
| 1749 | + | |
| 1750 | +$(OBJDIR)/sitemap.h: $(OBJDIR)/headers | |
| 1670 | 1751 | |
| 1671 | 1752 | $(OBJDIR)/skins_.c: $(SRCDIR)/skins.c $(TRANSLATE) |
| 1672 | 1753 | $(TRANSLATE) $(SRCDIR)/skins.c >$@ |
| 1673 | 1754 | |
| 1674 | 1755 | $(OBJDIR)/skins.o: $(OBJDIR)/skins_.c $(OBJDIR)/skins.h $(SRCDIR)/config.h |
| 1675 | 1756 |
| --- win/Makefile.mingw.mistachkin | |
| +++ win/Makefile.mingw.mistachkin | |
| @@ -87,11 +87,12 @@ | |
| 87 | # This is useful when Tcl has been compiled statically with MinGW. |
| 88 | # |
| 89 | FOSSIL_TCL_SOURCE = 1 |
| 90 | |
| 91 | #### Check if the workaround for the MinGW command line handling needs to |
| 92 | # be enabled by default. |
| 93 | # |
| 94 | ifndef MINGW_IS_32BIT_ONLY |
| 95 | ifeq (,$(findstring w64-mingw32,$(PREFIX))) |
| 96 | MINGW_IS_32BIT_ONLY = 1 |
| 97 | endif |
| @@ -100,26 +101,46 @@ | |
| 100 | #### The directories where the zlib include and library files are located. |
| 101 | # |
| 102 | ZINCDIR = $(SRCDIR)/../compat/zlib |
| 103 | ZLIBDIR = $(SRCDIR)/../compat/zlib |
| 104 | |
| 105 | ifndef X64 |
| 106 | ifneq (,$(findstring x86_64-w64-mingw32,$(PREFIX))) |
| 107 | X64 = 1 |
| 108 | endif |
| 109 | endif |
| 110 | |
| 111 | ifndef X64 |
| 112 | SSLCONFIG = mingw |
| 113 | ZLIBCONFIG = LOC="-DASMV -DASMINF" OBJA="inffas86.o match.o" |
| 114 | LIBTARGETS = $(ZLIBDIR)/inffas86.o $(ZLIBDIR)/match.o |
| 115 | else |
| 116 | SSLCONFIG = mingw64 |
| 117 | ZLIBCONFIG = |
| 118 | LIBTARGETS = |
| 119 | endif |
| 120 | |
| 121 | ifndef FOSSIL_ENABLE_MINIZ |
| 122 | SSLCONFIG += --with-zlib-lib=$(PWD)/$(ZLIBDIR) --with-zlib-include=$(PWD)/$(ZLIBDIR) zlib |
| 123 | endif |
| 124 | |
| 125 | #### The directories where the OpenSSL include and library files are located. |
| @@ -352,10 +373,11 @@ | |
| 352 | $(SRCDIR)/bisect.c \ |
| 353 | $(SRCDIR)/blob.c \ |
| 354 | $(SRCDIR)/branch.c \ |
| 355 | $(SRCDIR)/browse.c \ |
| 356 | $(SRCDIR)/builtin.c \ |
| 357 | $(SRCDIR)/cache.c \ |
| 358 | $(SRCDIR)/captcha.c \ |
| 359 | $(SRCDIR)/cgi.c \ |
| 360 | $(SRCDIR)/checkin.c \ |
| 361 | $(SRCDIR)/checkout.c \ |
| @@ -374,10 +396,11 @@ | |
| 374 | $(SRCDIR)/encode.c \ |
| 375 | $(SRCDIR)/event.c \ |
| 376 | $(SRCDIR)/export.c \ |
| 377 | $(SRCDIR)/file.c \ |
| 378 | $(SRCDIR)/finfo.c \ |
| 379 | $(SRCDIR)/fusefs.c \ |
| 380 | $(SRCDIR)/glob.c \ |
| 381 | $(SRCDIR)/graph.c \ |
| 382 | $(SRCDIR)/gzip.c \ |
| 383 | $(SRCDIR)/http.c \ |
| @@ -417,19 +440,22 @@ | |
| 417 | $(SRCDIR)/path.c \ |
| 418 | $(SRCDIR)/pivot.c \ |
| 419 | $(SRCDIR)/popen.c \ |
| 420 | $(SRCDIR)/pqueue.c \ |
| 421 | $(SRCDIR)/printf.c \ |
| 422 | $(SRCDIR)/rebuild.c \ |
| 423 | $(SRCDIR)/regexp.c \ |
| 424 | $(SRCDIR)/report.c \ |
| 425 | $(SRCDIR)/rss.c \ |
| 426 | $(SRCDIR)/schema.c \ |
| 427 | $(SRCDIR)/search.c \ |
| 428 | $(SRCDIR)/setup.c \ |
| 429 | $(SRCDIR)/sha1.c \ |
| 430 | $(SRCDIR)/shun.c \ |
| 431 | $(SRCDIR)/skins.c \ |
| 432 | $(SRCDIR)/sqlcmd.c \ |
| 433 | $(SRCDIR)/stash.c \ |
| 434 | $(SRCDIR)/stat.c \ |
| 435 | $(SRCDIR)/style.c \ |
| @@ -469,10 +495,11 @@ | |
| 469 | $(OBJDIR)/bisect_.c \ |
| 470 | $(OBJDIR)/blob_.c \ |
| 471 | $(OBJDIR)/branch_.c \ |
| 472 | $(OBJDIR)/browse_.c \ |
| 473 | $(OBJDIR)/builtin_.c \ |
| 474 | $(OBJDIR)/cache_.c \ |
| 475 | $(OBJDIR)/captcha_.c \ |
| 476 | $(OBJDIR)/cgi_.c \ |
| 477 | $(OBJDIR)/checkin_.c \ |
| 478 | $(OBJDIR)/checkout_.c \ |
| @@ -491,10 +518,11 @@ | |
| 491 | $(OBJDIR)/encode_.c \ |
| 492 | $(OBJDIR)/event_.c \ |
| 493 | $(OBJDIR)/export_.c \ |
| 494 | $(OBJDIR)/file_.c \ |
| 495 | $(OBJDIR)/finfo_.c \ |
| 496 | $(OBJDIR)/fusefs_.c \ |
| 497 | $(OBJDIR)/glob_.c \ |
| 498 | $(OBJDIR)/graph_.c \ |
| 499 | $(OBJDIR)/gzip_.c \ |
| 500 | $(OBJDIR)/http_.c \ |
| @@ -534,19 +562,22 @@ | |
| 534 | $(OBJDIR)/path_.c \ |
| 535 | $(OBJDIR)/pivot_.c \ |
| 536 | $(OBJDIR)/popen_.c \ |
| 537 | $(OBJDIR)/pqueue_.c \ |
| 538 | $(OBJDIR)/printf_.c \ |
| 539 | $(OBJDIR)/rebuild_.c \ |
| 540 | $(OBJDIR)/regexp_.c \ |
| 541 | $(OBJDIR)/report_.c \ |
| 542 | $(OBJDIR)/rss_.c \ |
| 543 | $(OBJDIR)/schema_.c \ |
| 544 | $(OBJDIR)/search_.c \ |
| 545 | $(OBJDIR)/setup_.c \ |
| 546 | $(OBJDIR)/sha1_.c \ |
| 547 | $(OBJDIR)/shun_.c \ |
| 548 | $(OBJDIR)/skins_.c \ |
| 549 | $(OBJDIR)/sqlcmd_.c \ |
| 550 | $(OBJDIR)/stash_.c \ |
| 551 | $(OBJDIR)/stat_.c \ |
| 552 | $(OBJDIR)/style_.c \ |
| @@ -583,10 +614,11 @@ | |
| 583 | $(OBJDIR)/bisect.o \ |
| 584 | $(OBJDIR)/blob.o \ |
| 585 | $(OBJDIR)/branch.o \ |
| 586 | $(OBJDIR)/browse.o \ |
| 587 | $(OBJDIR)/builtin.o \ |
| 588 | $(OBJDIR)/cache.o \ |
| 589 | $(OBJDIR)/captcha.o \ |
| 590 | $(OBJDIR)/cgi.o \ |
| 591 | $(OBJDIR)/checkin.o \ |
| 592 | $(OBJDIR)/checkout.o \ |
| @@ -605,10 +637,11 @@ | |
| 605 | $(OBJDIR)/encode.o \ |
| 606 | $(OBJDIR)/event.o \ |
| 607 | $(OBJDIR)/export.o \ |
| 608 | $(OBJDIR)/file.o \ |
| 609 | $(OBJDIR)/finfo.o \ |
| 610 | $(OBJDIR)/fusefs.o \ |
| 611 | $(OBJDIR)/glob.o \ |
| 612 | $(OBJDIR)/graph.o \ |
| 613 | $(OBJDIR)/gzip.o \ |
| 614 | $(OBJDIR)/http.o \ |
| @@ -648,19 +681,22 @@ | |
| 648 | $(OBJDIR)/path.o \ |
| 649 | $(OBJDIR)/pivot.o \ |
| 650 | $(OBJDIR)/popen.o \ |
| 651 | $(OBJDIR)/pqueue.o \ |
| 652 | $(OBJDIR)/printf.o \ |
| 653 | $(OBJDIR)/rebuild.o \ |
| 654 | $(OBJDIR)/regexp.o \ |
| 655 | $(OBJDIR)/report.o \ |
| 656 | $(OBJDIR)/rss.o \ |
| 657 | $(OBJDIR)/schema.o \ |
| 658 | $(OBJDIR)/search.o \ |
| 659 | $(OBJDIR)/setup.o \ |
| 660 | $(OBJDIR)/sha1.o \ |
| 661 | $(OBJDIR)/shun.o \ |
| 662 | $(OBJDIR)/skins.o \ |
| 663 | $(OBJDIR)/sqlcmd.o \ |
| 664 | $(OBJDIR)/stash.o \ |
| 665 | $(OBJDIR)/stat.o \ |
| 666 | $(OBJDIR)/style.o \ |
| @@ -890,10 +926,11 @@ | |
| 890 | $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h \ |
| 891 | $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h \ |
| 892 | $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h \ |
| 893 | $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h \ |
| 894 | $(OBJDIR)/builtin_.c:$(OBJDIR)/builtin.h \ |
| 895 | $(OBJDIR)/cache_.c:$(OBJDIR)/cache.h \ |
| 896 | $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h \ |
| 897 | $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h \ |
| 898 | $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h \ |
| 899 | $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h \ |
| @@ -912,10 +949,11 @@ | |
| 912 | $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h \ |
| 913 | $(OBJDIR)/event_.c:$(OBJDIR)/event.h \ |
| 914 | $(OBJDIR)/export_.c:$(OBJDIR)/export.h \ |
| 915 | $(OBJDIR)/file_.c:$(OBJDIR)/file.h \ |
| 916 | $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h \ |
| 917 | $(OBJDIR)/fusefs_.c:$(OBJDIR)/fusefs.h \ |
| 918 | $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h \ |
| 919 | $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h \ |
| 920 | $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h \ |
| 921 | $(OBJDIR)/http_.c:$(OBJDIR)/http.h \ |
| @@ -955,19 +993,22 @@ | |
| 955 | $(OBJDIR)/path_.c:$(OBJDIR)/path.h \ |
| 956 | $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \ |
| 957 | $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h \ |
| 958 | $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h \ |
| 959 | $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h \ |
| 960 | $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h \ |
| 961 | $(OBJDIR)/regexp_.c:$(OBJDIR)/regexp.h \ |
| 962 | $(OBJDIR)/report_.c:$(OBJDIR)/report.h \ |
| 963 | $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \ |
| 964 | $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \ |
| 965 | $(OBJDIR)/search_.c:$(OBJDIR)/search.h \ |
| 966 | $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \ |
| 967 | $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h \ |
| 968 | $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h \ |
| 969 | $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \ |
| 970 | $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \ |
| 971 | $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h \ |
| 972 | $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h \ |
| 973 | $(OBJDIR)/style_.c:$(OBJDIR)/style.h \ |
| @@ -1073,10 +1114,18 @@ | |
| 1073 | |
| 1074 | $(OBJDIR)/builtin.o: $(OBJDIR)/builtin_.c $(OBJDIR)/builtin.h $(OBJDIR)/builtin_data.h $(SRCDIR)/config.h |
| 1075 | $(XTCC) -o $(OBJDIR)/builtin.o -c $(OBJDIR)/builtin_.c |
| 1076 | |
| 1077 | $(OBJDIR)/builtin.h: $(OBJDIR)/headers |
| 1078 | |
| 1079 | $(OBJDIR)/cache_.c: $(SRCDIR)/cache.c $(TRANSLATE) |
| 1080 | $(TRANSLATE) $(SRCDIR)/cache.c >$@ |
| 1081 | |
| 1082 | $(OBJDIR)/cache.o: $(OBJDIR)/cache_.c $(OBJDIR)/cache.h $(SRCDIR)/config.h |
| @@ -1249,10 +1298,18 @@ | |
| 1249 | |
| 1250 | $(OBJDIR)/finfo.o: $(OBJDIR)/finfo_.c $(OBJDIR)/finfo.h $(SRCDIR)/config.h |
| 1251 | $(XTCC) -o $(OBJDIR)/finfo.o -c $(OBJDIR)/finfo_.c |
| 1252 | |
| 1253 | $(OBJDIR)/finfo.h: $(OBJDIR)/headers |
| 1254 | |
| 1255 | $(OBJDIR)/fusefs_.c: $(SRCDIR)/fusefs.c $(TRANSLATE) |
| 1256 | $(TRANSLATE) $(SRCDIR)/fusefs.c >$@ |
| 1257 | |
| 1258 | $(OBJDIR)/fusefs.o: $(OBJDIR)/fusefs_.c $(OBJDIR)/fusefs.h $(SRCDIR)/config.h |
| @@ -1593,10 +1650,26 @@ | |
| 1593 | |
| 1594 | $(OBJDIR)/printf.o: $(OBJDIR)/printf_.c $(OBJDIR)/printf.h $(SRCDIR)/config.h |
| 1595 | $(XTCC) -o $(OBJDIR)/printf.o -c $(OBJDIR)/printf_.c |
| 1596 | |
| 1597 | $(OBJDIR)/printf.h: $(OBJDIR)/headers |
| 1598 | |
| 1599 | $(OBJDIR)/rebuild_.c: $(SRCDIR)/rebuild.c $(TRANSLATE) |
| 1600 | $(TRANSLATE) $(SRCDIR)/rebuild.c >$@ |
| 1601 | |
| 1602 | $(OBJDIR)/rebuild.o: $(OBJDIR)/rebuild_.c $(OBJDIR)/rebuild.h $(SRCDIR)/config.h |
| @@ -1665,10 +1738,18 @@ | |
| 1665 | |
| 1666 | $(OBJDIR)/shun.o: $(OBJDIR)/shun_.c $(OBJDIR)/shun.h $(SRCDIR)/config.h |
| 1667 | $(XTCC) -o $(OBJDIR)/shun.o -c $(OBJDIR)/shun_.c |
| 1668 | |
| 1669 | $(OBJDIR)/shun.h: $(OBJDIR)/headers |
| 1670 | |
| 1671 | $(OBJDIR)/skins_.c: $(SRCDIR)/skins.c $(TRANSLATE) |
| 1672 | $(TRANSLATE) $(SRCDIR)/skins.c >$@ |
| 1673 | |
| 1674 | $(OBJDIR)/skins.o: $(OBJDIR)/skins_.c $(OBJDIR)/skins.h $(SRCDIR)/config.h |
| 1675 |
| --- win/Makefile.mingw.mistachkin | |
| +++ win/Makefile.mingw.mistachkin | |
| @@ -87,11 +87,12 @@ | |
| 87 | # This is useful when Tcl has been compiled statically with MinGW. |
| 88 | # |
| 89 | FOSSIL_TCL_SOURCE = 1 |
| 90 | |
| 91 | #### Check if the workaround for the MinGW command line handling needs to |
| 92 | # be enabled by default. This check may be somewhat fragile due to the |
| 93 | # use of "findstring". |
| 94 | # |
| 95 | ifndef MINGW_IS_32BIT_ONLY |
| 96 | ifeq (,$(findstring w64-mingw32,$(PREFIX))) |
| 97 | MINGW_IS_32BIT_ONLY = 1 |
| 98 | endif |
| @@ -100,26 +101,46 @@ | |
| 101 | #### The directories where the zlib include and library files are located. |
| 102 | # |
| 103 | ZINCDIR = $(SRCDIR)/../compat/zlib |
| 104 | ZLIBDIR = $(SRCDIR)/../compat/zlib |
| 105 | |
| 106 | #### Make an attempt to detect if Fossil is being built for the x64 processor |
| 107 | # architecture. This check may be somewhat fragile due to "findstring". |
| 108 | # |
| 109 | ifndef X64 |
| 110 | ifneq (,$(findstring x86_64-w64-mingw32,$(PREFIX))) |
| 111 | X64 = 1 |
| 112 | endif |
| 113 | endif |
| 114 | |
| 115 | #### Determine if the optimized assembly routines provided with zlib should be |
| 116 | # used, taking into account whether zlib is actually enabled and the target |
| 117 | # processor architecture. |
| 118 | # |
| 119 | ifndef X64 |
| 120 | SSLCONFIG = mingw |
| 121 | ifndef FOSSIL_ENABLE_MINIZ |
| 122 | ZLIBCONFIG = LOC="-DASMV -DASMINF" OBJA="inffas86.o match.o" |
| 123 | LIBTARGETS = $(ZLIBDIR)/inffas86.o $(ZLIBDIR)/match.o |
| 124 | else |
| 125 | ZLIBCONFIG = |
| 126 | LIBTARGETS = |
| 127 | endif |
| 128 | else |
| 129 | SSLCONFIG = mingw64 |
| 130 | ZLIBCONFIG = |
| 131 | LIBTARGETS = |
| 132 | endif |
| 133 | |
| 134 | #### Disable creation of the OpenSSL shared libraries. Also, disable support |
| 135 | # for both SSLv2 and SSLv3 (i.e. thereby forcing the use of TLS). |
| 136 | # |
| 137 | SSLCONFIG += no-ssl2 no-ssl3 no-shared |
| 138 | |
| 139 | #### When using zlib, make sure that OpenSSL is configured to use the zlib |
| 140 | # that Fossil knows about (i.e. the one within the source tree). |
| 141 | # |
| 142 | ifndef FOSSIL_ENABLE_MINIZ |
| 143 | SSLCONFIG += --with-zlib-lib=$(PWD)/$(ZLIBDIR) --with-zlib-include=$(PWD)/$(ZLIBDIR) zlib |
| 144 | endif |
| 145 | |
| 146 | #### The directories where the OpenSSL include and library files are located. |
| @@ -352,10 +373,11 @@ | |
| 373 | $(SRCDIR)/bisect.c \ |
| 374 | $(SRCDIR)/blob.c \ |
| 375 | $(SRCDIR)/branch.c \ |
| 376 | $(SRCDIR)/browse.c \ |
| 377 | $(SRCDIR)/builtin.c \ |
| 378 | $(SRCDIR)/bundle.c \ |
| 379 | $(SRCDIR)/cache.c \ |
| 380 | $(SRCDIR)/captcha.c \ |
| 381 | $(SRCDIR)/cgi.c \ |
| 382 | $(SRCDIR)/checkin.c \ |
| 383 | $(SRCDIR)/checkout.c \ |
| @@ -374,10 +396,11 @@ | |
| 396 | $(SRCDIR)/encode.c \ |
| 397 | $(SRCDIR)/event.c \ |
| 398 | $(SRCDIR)/export.c \ |
| 399 | $(SRCDIR)/file.c \ |
| 400 | $(SRCDIR)/finfo.c \ |
| 401 | $(SRCDIR)/foci.c \ |
| 402 | $(SRCDIR)/fusefs.c \ |
| 403 | $(SRCDIR)/glob.c \ |
| 404 | $(SRCDIR)/graph.c \ |
| 405 | $(SRCDIR)/gzip.c \ |
| 406 | $(SRCDIR)/http.c \ |
| @@ -417,19 +440,22 @@ | |
| 440 | $(SRCDIR)/path.c \ |
| 441 | $(SRCDIR)/pivot.c \ |
| 442 | $(SRCDIR)/popen.c \ |
| 443 | $(SRCDIR)/pqueue.c \ |
| 444 | $(SRCDIR)/printf.c \ |
| 445 | $(SRCDIR)/publish.c \ |
| 446 | $(SRCDIR)/purge.c \ |
| 447 | $(SRCDIR)/rebuild.c \ |
| 448 | $(SRCDIR)/regexp.c \ |
| 449 | $(SRCDIR)/report.c \ |
| 450 | $(SRCDIR)/rss.c \ |
| 451 | $(SRCDIR)/schema.c \ |
| 452 | $(SRCDIR)/search.c \ |
| 453 | $(SRCDIR)/setup.c \ |
| 454 | $(SRCDIR)/sha1.c \ |
| 455 | $(SRCDIR)/shun.c \ |
| 456 | $(SRCDIR)/sitemap.c \ |
| 457 | $(SRCDIR)/skins.c \ |
| 458 | $(SRCDIR)/sqlcmd.c \ |
| 459 | $(SRCDIR)/stash.c \ |
| 460 | $(SRCDIR)/stat.c \ |
| 461 | $(SRCDIR)/style.c \ |
| @@ -469,10 +495,11 @@ | |
| 495 | $(OBJDIR)/bisect_.c \ |
| 496 | $(OBJDIR)/blob_.c \ |
| 497 | $(OBJDIR)/branch_.c \ |
| 498 | $(OBJDIR)/browse_.c \ |
| 499 | $(OBJDIR)/builtin_.c \ |
| 500 | $(OBJDIR)/bundle_.c \ |
| 501 | $(OBJDIR)/cache_.c \ |
| 502 | $(OBJDIR)/captcha_.c \ |
| 503 | $(OBJDIR)/cgi_.c \ |
| 504 | $(OBJDIR)/checkin_.c \ |
| 505 | $(OBJDIR)/checkout_.c \ |
| @@ -491,10 +518,11 @@ | |
| 518 | $(OBJDIR)/encode_.c \ |
| 519 | $(OBJDIR)/event_.c \ |
| 520 | $(OBJDIR)/export_.c \ |
| 521 | $(OBJDIR)/file_.c \ |
| 522 | $(OBJDIR)/finfo_.c \ |
| 523 | $(OBJDIR)/foci_.c \ |
| 524 | $(OBJDIR)/fusefs_.c \ |
| 525 | $(OBJDIR)/glob_.c \ |
| 526 | $(OBJDIR)/graph_.c \ |
| 527 | $(OBJDIR)/gzip_.c \ |
| 528 | $(OBJDIR)/http_.c \ |
| @@ -534,19 +562,22 @@ | |
| 562 | $(OBJDIR)/path_.c \ |
| 563 | $(OBJDIR)/pivot_.c \ |
| 564 | $(OBJDIR)/popen_.c \ |
| 565 | $(OBJDIR)/pqueue_.c \ |
| 566 | $(OBJDIR)/printf_.c \ |
| 567 | $(OBJDIR)/publish_.c \ |
| 568 | $(OBJDIR)/purge_.c \ |
| 569 | $(OBJDIR)/rebuild_.c \ |
| 570 | $(OBJDIR)/regexp_.c \ |
| 571 | $(OBJDIR)/report_.c \ |
| 572 | $(OBJDIR)/rss_.c \ |
| 573 | $(OBJDIR)/schema_.c \ |
| 574 | $(OBJDIR)/search_.c \ |
| 575 | $(OBJDIR)/setup_.c \ |
| 576 | $(OBJDIR)/sha1_.c \ |
| 577 | $(OBJDIR)/shun_.c \ |
| 578 | $(OBJDIR)/sitemap_.c \ |
| 579 | $(OBJDIR)/skins_.c \ |
| 580 | $(OBJDIR)/sqlcmd_.c \ |
| 581 | $(OBJDIR)/stash_.c \ |
| 582 | $(OBJDIR)/stat_.c \ |
| 583 | $(OBJDIR)/style_.c \ |
| @@ -583,10 +614,11 @@ | |
| 614 | $(OBJDIR)/bisect.o \ |
| 615 | $(OBJDIR)/blob.o \ |
| 616 | $(OBJDIR)/branch.o \ |
| 617 | $(OBJDIR)/browse.o \ |
| 618 | $(OBJDIR)/builtin.o \ |
| 619 | $(OBJDIR)/bundle.o \ |
| 620 | $(OBJDIR)/cache.o \ |
| 621 | $(OBJDIR)/captcha.o \ |
| 622 | $(OBJDIR)/cgi.o \ |
| 623 | $(OBJDIR)/checkin.o \ |
| 624 | $(OBJDIR)/checkout.o \ |
| @@ -605,10 +637,11 @@ | |
| 637 | $(OBJDIR)/encode.o \ |
| 638 | $(OBJDIR)/event.o \ |
| 639 | $(OBJDIR)/export.o \ |
| 640 | $(OBJDIR)/file.o \ |
| 641 | $(OBJDIR)/finfo.o \ |
| 642 | $(OBJDIR)/foci.o \ |
| 643 | $(OBJDIR)/fusefs.o \ |
| 644 | $(OBJDIR)/glob.o \ |
| 645 | $(OBJDIR)/graph.o \ |
| 646 | $(OBJDIR)/gzip.o \ |
| 647 | $(OBJDIR)/http.o \ |
| @@ -648,19 +681,22 @@ | |
| 681 | $(OBJDIR)/path.o \ |
| 682 | $(OBJDIR)/pivot.o \ |
| 683 | $(OBJDIR)/popen.o \ |
| 684 | $(OBJDIR)/pqueue.o \ |
| 685 | $(OBJDIR)/printf.o \ |
| 686 | $(OBJDIR)/publish.o \ |
| 687 | $(OBJDIR)/purge.o \ |
| 688 | $(OBJDIR)/rebuild.o \ |
| 689 | $(OBJDIR)/regexp.o \ |
| 690 | $(OBJDIR)/report.o \ |
| 691 | $(OBJDIR)/rss.o \ |
| 692 | $(OBJDIR)/schema.o \ |
| 693 | $(OBJDIR)/search.o \ |
| 694 | $(OBJDIR)/setup.o \ |
| 695 | $(OBJDIR)/sha1.o \ |
| 696 | $(OBJDIR)/shun.o \ |
| 697 | $(OBJDIR)/sitemap.o \ |
| 698 | $(OBJDIR)/skins.o \ |
| 699 | $(OBJDIR)/sqlcmd.o \ |
| 700 | $(OBJDIR)/stash.o \ |
| 701 | $(OBJDIR)/stat.o \ |
| 702 | $(OBJDIR)/style.o \ |
| @@ -890,10 +926,11 @@ | |
| 926 | $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h \ |
| 927 | $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h \ |
| 928 | $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h \ |
| 929 | $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h \ |
| 930 | $(OBJDIR)/builtin_.c:$(OBJDIR)/builtin.h \ |
| 931 | $(OBJDIR)/bundle_.c:$(OBJDIR)/bundle.h \ |
| 932 | $(OBJDIR)/cache_.c:$(OBJDIR)/cache.h \ |
| 933 | $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h \ |
| 934 | $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h \ |
| 935 | $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h \ |
| 936 | $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h \ |
| @@ -912,10 +949,11 @@ | |
| 949 | $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h \ |
| 950 | $(OBJDIR)/event_.c:$(OBJDIR)/event.h \ |
| 951 | $(OBJDIR)/export_.c:$(OBJDIR)/export.h \ |
| 952 | $(OBJDIR)/file_.c:$(OBJDIR)/file.h \ |
| 953 | $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h \ |
| 954 | $(OBJDIR)/foci_.c:$(OBJDIR)/foci.h \ |
| 955 | $(OBJDIR)/fusefs_.c:$(OBJDIR)/fusefs.h \ |
| 956 | $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h \ |
| 957 | $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h \ |
| 958 | $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h \ |
| 959 | $(OBJDIR)/http_.c:$(OBJDIR)/http.h \ |
| @@ -955,19 +993,22 @@ | |
| 993 | $(OBJDIR)/path_.c:$(OBJDIR)/path.h \ |
| 994 | $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h \ |
| 995 | $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h \ |
| 996 | $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h \ |
| 997 | $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h \ |
| 998 | $(OBJDIR)/publish_.c:$(OBJDIR)/publish.h \ |
| 999 | $(OBJDIR)/purge_.c:$(OBJDIR)/purge.h \ |
| 1000 | $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h \ |
| 1001 | $(OBJDIR)/regexp_.c:$(OBJDIR)/regexp.h \ |
| 1002 | $(OBJDIR)/report_.c:$(OBJDIR)/report.h \ |
| 1003 | $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h \ |
| 1004 | $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h \ |
| 1005 | $(OBJDIR)/search_.c:$(OBJDIR)/search.h \ |
| 1006 | $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h \ |
| 1007 | $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h \ |
| 1008 | $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h \ |
| 1009 | $(OBJDIR)/sitemap_.c:$(OBJDIR)/sitemap.h \ |
| 1010 | $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \ |
| 1011 | $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \ |
| 1012 | $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h \ |
| 1013 | $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h \ |
| 1014 | $(OBJDIR)/style_.c:$(OBJDIR)/style.h \ |
| @@ -1073,10 +1114,18 @@ | |
| 1114 | |
| 1115 | $(OBJDIR)/builtin.o: $(OBJDIR)/builtin_.c $(OBJDIR)/builtin.h $(OBJDIR)/builtin_data.h $(SRCDIR)/config.h |
| 1116 | $(XTCC) -o $(OBJDIR)/builtin.o -c $(OBJDIR)/builtin_.c |
| 1117 | |
| 1118 | $(OBJDIR)/builtin.h: $(OBJDIR)/headers |
| 1119 | |
| 1120 | $(OBJDIR)/bundle_.c: $(SRCDIR)/bundle.c $(TRANSLATE) |
| 1121 | $(TRANSLATE) $(SRCDIR)/bundle.c >$@ |
| 1122 | |
| 1123 | $(OBJDIR)/bundle.o: $(OBJDIR)/bundle_.c $(OBJDIR)/bundle.h $(SRCDIR)/config.h |
| 1124 | $(XTCC) -o $(OBJDIR)/bundle.o -c $(OBJDIR)/bundle_.c |
| 1125 | |
| 1126 | $(OBJDIR)/bundle.h: $(OBJDIR)/headers |
| 1127 | |
| 1128 | $(OBJDIR)/cache_.c: $(SRCDIR)/cache.c $(TRANSLATE) |
| 1129 | $(TRANSLATE) $(SRCDIR)/cache.c >$@ |
| 1130 | |
| 1131 | $(OBJDIR)/cache.o: $(OBJDIR)/cache_.c $(OBJDIR)/cache.h $(SRCDIR)/config.h |
| @@ -1249,10 +1298,18 @@ | |
| 1298 | |
| 1299 | $(OBJDIR)/finfo.o: $(OBJDIR)/finfo_.c $(OBJDIR)/finfo.h $(SRCDIR)/config.h |
| 1300 | $(XTCC) -o $(OBJDIR)/finfo.o -c $(OBJDIR)/finfo_.c |
| 1301 | |
| 1302 | $(OBJDIR)/finfo.h: $(OBJDIR)/headers |
| 1303 | |
| 1304 | $(OBJDIR)/foci_.c: $(SRCDIR)/foci.c $(TRANSLATE) |
| 1305 | $(TRANSLATE) $(SRCDIR)/foci.c >$@ |
| 1306 | |
| 1307 | $(OBJDIR)/foci.o: $(OBJDIR)/foci_.c $(OBJDIR)/foci.h $(SRCDIR)/config.h |
| 1308 | $(XTCC) -o $(OBJDIR)/foci.o -c $(OBJDIR)/foci_.c |
| 1309 | |
| 1310 | $(OBJDIR)/foci.h: $(OBJDIR)/headers |
| 1311 | |
| 1312 | $(OBJDIR)/fusefs_.c: $(SRCDIR)/fusefs.c $(TRANSLATE) |
| 1313 | $(TRANSLATE) $(SRCDIR)/fusefs.c >$@ |
| 1314 | |
| 1315 | $(OBJDIR)/fusefs.o: $(OBJDIR)/fusefs_.c $(OBJDIR)/fusefs.h $(SRCDIR)/config.h |
| @@ -1593,10 +1650,26 @@ | |
| 1650 | |
| 1651 | $(OBJDIR)/printf.o: $(OBJDIR)/printf_.c $(OBJDIR)/printf.h $(SRCDIR)/config.h |
| 1652 | $(XTCC) -o $(OBJDIR)/printf.o -c $(OBJDIR)/printf_.c |
| 1653 | |
| 1654 | $(OBJDIR)/printf.h: $(OBJDIR)/headers |
| 1655 | |
| 1656 | $(OBJDIR)/publish_.c: $(SRCDIR)/publish.c $(TRANSLATE) |
| 1657 | $(TRANSLATE) $(SRCDIR)/publish.c >$@ |
| 1658 | |
| 1659 | $(OBJDIR)/publish.o: $(OBJDIR)/publish_.c $(OBJDIR)/publish.h $(SRCDIR)/config.h |
| 1660 | $(XTCC) -o $(OBJDIR)/publish.o -c $(OBJDIR)/publish_.c |
| 1661 | |
| 1662 | $(OBJDIR)/publish.h: $(OBJDIR)/headers |
| 1663 | |
| 1664 | $(OBJDIR)/purge_.c: $(SRCDIR)/purge.c $(TRANSLATE) |
| 1665 | $(TRANSLATE) $(SRCDIR)/purge.c >$@ |
| 1666 | |
| 1667 | $(OBJDIR)/purge.o: $(OBJDIR)/purge_.c $(OBJDIR)/purge.h $(SRCDIR)/config.h |
| 1668 | $(XTCC) -o $(OBJDIR)/purge.o -c $(OBJDIR)/purge_.c |
| 1669 | |
| 1670 | $(OBJDIR)/purge.h: $(OBJDIR)/headers |
| 1671 | |
| 1672 | $(OBJDIR)/rebuild_.c: $(SRCDIR)/rebuild.c $(TRANSLATE) |
| 1673 | $(TRANSLATE) $(SRCDIR)/rebuild.c >$@ |
| 1674 | |
| 1675 | $(OBJDIR)/rebuild.o: $(OBJDIR)/rebuild_.c $(OBJDIR)/rebuild.h $(SRCDIR)/config.h |
| @@ -1665,10 +1738,18 @@ | |
| 1738 | |
| 1739 | $(OBJDIR)/shun.o: $(OBJDIR)/shun_.c $(OBJDIR)/shun.h $(SRCDIR)/config.h |
| 1740 | $(XTCC) -o $(OBJDIR)/shun.o -c $(OBJDIR)/shun_.c |
| 1741 | |
| 1742 | $(OBJDIR)/shun.h: $(OBJDIR)/headers |
| 1743 | |
| 1744 | $(OBJDIR)/sitemap_.c: $(SRCDIR)/sitemap.c $(TRANSLATE) |
| 1745 | $(TRANSLATE) $(SRCDIR)/sitemap.c >$@ |
| 1746 | |
| 1747 | $(OBJDIR)/sitemap.o: $(OBJDIR)/sitemap_.c $(OBJDIR)/sitemap.h $(SRCDIR)/config.h |
| 1748 | $(XTCC) -o $(OBJDIR)/sitemap.o -c $(OBJDIR)/sitemap_.c |
| 1749 | |
| 1750 | $(OBJDIR)/sitemap.h: $(OBJDIR)/headers |
| 1751 | |
| 1752 | $(OBJDIR)/skins_.c: $(SRCDIR)/skins.c $(TRANSLATE) |
| 1753 | $(TRANSLATE) $(SRCDIR)/skins.c >$@ |
| 1754 | |
| 1755 | $(OBJDIR)/skins.o: $(OBJDIR)/skins_.c $(OBJDIR)/skins.h $(SRCDIR)/config.h |
| 1756 |
+24
-5
| --- win/Makefile.msc | ||
| +++ win/Makefile.msc | ||
| @@ -62,23 +62,32 @@ | ||
| 62 | 62 | SSLLIBDIR = $(SSLDIR)\out32 |
| 63 | 63 | SSLLFLAGS = /nologo /opt:ref /debug |
| 64 | 64 | SSLLIB = ssleay32.lib libeay32.lib user32.lib gdi32.lib |
| 65 | 65 | !if "$(PLATFORM)"=="amd64" || "$(PLATFORM)"=="x64" |
| 66 | 66 | !message Using 'x64' platform for OpenSSL... |
| 67 | -SSLCONFIG = VC-WIN64A no-asm | |
| 67 | +# BUGBUG (OpenSSL): Apparently, using "no-ssl*" here breaks the build. | |
| 68 | +# SSLCONFIG = VC-WIN64A no-asm no-ssl2 no-ssl3 no-shared | |
| 69 | +SSLCONFIG = VC-WIN64A no-asm no-shared | |
| 68 | 70 | SSLSETUP = ms\do_win64a.bat |
| 69 | 71 | SSLNMAKE = ms\nt.mak all |
| 72 | +SSLCFLAGS = -DOPENSSL_NO_SSL2 -DOPENSSL_NO_SSL3 | |
| 70 | 73 | !elseif "$(PLATFORM)"=="ia64" |
| 71 | 74 | !message Using 'ia64' platform for OpenSSL... |
| 72 | -SSLCONFIG = VC-WIN64I no-asm | |
| 75 | +# BUGBUG (OpenSSL): Apparently, using "no-ssl*" here breaks the build. | |
| 76 | +# SSLCONFIG = VC-WIN64I no-asm no-ssl2 no-ssl3 no-shared | |
| 77 | +SSLCONFIG = VC-WIN64I no-asm no-shared | |
| 73 | 78 | SSLSETUP = ms\do_win64i.bat |
| 74 | 79 | SSLNMAKE = ms\nt.mak all |
| 80 | +SSLCFLAGS = -DOPENSSL_NO_SSL2 -DOPENSSL_NO_SSL3 | |
| 75 | 81 | !else |
| 76 | 82 | !message Assuming 'x86' platform for OpenSSL... |
| 77 | -SSLCONFIG = VC-WIN32 no-asm | |
| 83 | +# BUGBUG (OpenSSL): Apparently, using "no-ssl*" here breaks the build. | |
| 84 | +# SSLCONFIG = VC-WIN32 no-asm no-ssl2 no-ssl3 no-shared | |
| 85 | +SSLCONFIG = VC-WIN32 no-asm no-shared | |
| 78 | 86 | SSLSETUP = ms\do_ms.bat |
| 79 | 87 | SSLNMAKE = ms\nt.mak all |
| 88 | +SSLCFLAGS = -DOPENSSL_NO_SSL2 -DOPENSSL_NO_SSL3 | |
| 80 | 89 | !endif |
| 81 | 90 | !endif |
| 82 | 91 | |
| 83 | 92 | !ifdef FOSSIL_ENABLE_TCL |
| 84 | 93 | TCLDIR = $(B)\compat\tcl-8.6 |
| @@ -282,10 +291,11 @@ | ||
| 282 | 291 | schema_.c \ |
| 283 | 292 | search_.c \ |
| 284 | 293 | setup_.c \ |
| 285 | 294 | sha1_.c \ |
| 286 | 295 | shun_.c \ |
| 296 | + sitemap_.c \ | |
| 287 | 297 | skins_.c \ |
| 288 | 298 | sqlcmd_.c \ |
| 289 | 299 | stash_.c \ |
| 290 | 300 | stat_.c \ |
| 291 | 301 | style_.c \ |
| @@ -403,10 +413,11 @@ | ||
| 403 | 413 | $(OX)\search$O \ |
| 404 | 414 | $(OX)\setup$O \ |
| 405 | 415 | $(OX)\sha1$O \ |
| 406 | 416 | $(OX)\shell$O \ |
| 407 | 417 | $(OX)\shun$O \ |
| 418 | + $(OX)\sitemap$O \ | |
| 408 | 419 | $(OX)\skins$O \ |
| 409 | 420 | $(OX)\sqlcmd$O \ |
| 410 | 421 | $(OX)\sqlite3$O \ |
| 411 | 422 | $(OX)\stash$O \ |
| 412 | 423 | $(OX)\stat$O \ |
| @@ -465,13 +476,13 @@ | ||
| 465 | 476 | @set PATH=$(PERLDIR);$(PATH) |
| 466 | 477 | !endif |
| 467 | 478 | @pushd "$(SSLDIR)" && $(PERL) Configure $(SSLCONFIG) && popd |
| 468 | 479 | @pushd "$(SSLDIR)" && call $(SSLSETUP) && popd |
| 469 | 480 | !ifdef FOSSIL_ENABLE_WINXP |
| 470 | - @pushd "$(SSLDIR)" && $(MAKE) /f $(SSLNMAKE) "CC=cl $(XPCFLAGS)" "LFLAGS=$(SSLLFLAGS) $(XPLDFLAGS)" && popd | |
| 481 | + @pushd "$(SSLDIR)" && $(MAKE) /f $(SSLNMAKE) "CC=cl $(SSLCFLAGS) $(XPCFLAGS)" "LFLAGS=$(SSLLFLAGS) $(XPLDFLAGS)" && popd | |
| 471 | 482 | !else |
| 472 | - @pushd "$(SSLDIR)" && $(MAKE) /f $(SSLNMAKE) && popd | |
| 483 | + @pushd "$(SSLDIR)" && $(MAKE) /f $(SSLNMAKE) "CC=cl $(SSLCFLAGS)" && popd | |
| 473 | 484 | !endif |
| 474 | 485 | !endif |
| 475 | 486 | |
| 476 | 487 | !ifndef FOSSIL_ENABLE_MINIZ |
| 477 | 488 | APPTARGETS = $(APPTARGETS) zlib |
| @@ -576,10 +587,11 @@ | ||
| 576 | 587 | echo $(OX)\search.obj >> $@ |
| 577 | 588 | echo $(OX)\setup.obj >> $@ |
| 578 | 589 | echo $(OX)\sha1.obj >> $@ |
| 579 | 590 | echo $(OX)\shell.obj >> $@ |
| 580 | 591 | echo $(OX)\shun.obj >> $@ |
| 592 | + echo $(OX)\sitemap.obj >> $@ | |
| 581 | 593 | echo $(OX)\skins.obj >> $@ |
| 582 | 594 | echo $(OX)\sqlcmd.obj >> $@ |
| 583 | 595 | echo $(OX)\sqlite3.obj >> $@ |
| 584 | 596 | echo $(OX)\stash.obj >> $@ |
| 585 | 597 | echo $(OX)\stat.obj >> $@ |
| @@ -1229,10 +1241,16 @@ | ||
| 1229 | 1241 | $(OX)\shun$O : shun_.c shun.h |
| 1230 | 1242 | $(TCC) /Fo$@ -c shun_.c |
| 1231 | 1243 | |
| 1232 | 1244 | shun_.c : $(SRCDIR)\shun.c |
| 1233 | 1245 | translate$E $** > $@ |
| 1246 | + | |
| 1247 | +$(OX)\sitemap$O : sitemap_.c sitemap.h | |
| 1248 | + $(TCC) /Fo$@ -c sitemap_.c | |
| 1249 | + | |
| 1250 | +sitemap_.c : $(SRCDIR)\sitemap.c | |
| 1251 | + translate$E $** > $@ | |
| 1234 | 1252 | |
| 1235 | 1253 | $(OX)\skins$O : skins_.c skins.h |
| 1236 | 1254 | $(TCC) /Fo$@ -c skins_.c |
| 1237 | 1255 | |
| 1238 | 1256 | skins_.c : $(SRCDIR)\skins.c |
| @@ -1495,10 +1513,11 @@ | ||
| 1495 | 1513 | schema_.c:schema.h \ |
| 1496 | 1514 | search_.c:search.h \ |
| 1497 | 1515 | setup_.c:setup.h \ |
| 1498 | 1516 | sha1_.c:sha1.h \ |
| 1499 | 1517 | shun_.c:shun.h \ |
| 1518 | + sitemap_.c:sitemap.h \ | |
| 1500 | 1519 | skins_.c:skins.h \ |
| 1501 | 1520 | sqlcmd_.c:sqlcmd.h \ |
| 1502 | 1521 | stash_.c:stash.h \ |
| 1503 | 1522 | stat_.c:stat.h \ |
| 1504 | 1523 | style_.c:style.h \ |
| 1505 | 1524 |
| --- win/Makefile.msc | |
| +++ win/Makefile.msc | |
| @@ -62,23 +62,32 @@ | |
| 62 | SSLLIBDIR = $(SSLDIR)\out32 |
| 63 | SSLLFLAGS = /nologo /opt:ref /debug |
| 64 | SSLLIB = ssleay32.lib libeay32.lib user32.lib gdi32.lib |
| 65 | !if "$(PLATFORM)"=="amd64" || "$(PLATFORM)"=="x64" |
| 66 | !message Using 'x64' platform for OpenSSL... |
| 67 | SSLCONFIG = VC-WIN64A no-asm |
| 68 | SSLSETUP = ms\do_win64a.bat |
| 69 | SSLNMAKE = ms\nt.mak all |
| 70 | !elseif "$(PLATFORM)"=="ia64" |
| 71 | !message Using 'ia64' platform for OpenSSL... |
| 72 | SSLCONFIG = VC-WIN64I no-asm |
| 73 | SSLSETUP = ms\do_win64i.bat |
| 74 | SSLNMAKE = ms\nt.mak all |
| 75 | !else |
| 76 | !message Assuming 'x86' platform for OpenSSL... |
| 77 | SSLCONFIG = VC-WIN32 no-asm |
| 78 | SSLSETUP = ms\do_ms.bat |
| 79 | SSLNMAKE = ms\nt.mak all |
| 80 | !endif |
| 81 | !endif |
| 82 | |
| 83 | !ifdef FOSSIL_ENABLE_TCL |
| 84 | TCLDIR = $(B)\compat\tcl-8.6 |
| @@ -282,10 +291,11 @@ | |
| 282 | schema_.c \ |
| 283 | search_.c \ |
| 284 | setup_.c \ |
| 285 | sha1_.c \ |
| 286 | shun_.c \ |
| 287 | skins_.c \ |
| 288 | sqlcmd_.c \ |
| 289 | stash_.c \ |
| 290 | stat_.c \ |
| 291 | style_.c \ |
| @@ -403,10 +413,11 @@ | |
| 403 | $(OX)\search$O \ |
| 404 | $(OX)\setup$O \ |
| 405 | $(OX)\sha1$O \ |
| 406 | $(OX)\shell$O \ |
| 407 | $(OX)\shun$O \ |
| 408 | $(OX)\skins$O \ |
| 409 | $(OX)\sqlcmd$O \ |
| 410 | $(OX)\sqlite3$O \ |
| 411 | $(OX)\stash$O \ |
| 412 | $(OX)\stat$O \ |
| @@ -465,13 +476,13 @@ | |
| 465 | @set PATH=$(PERLDIR);$(PATH) |
| 466 | !endif |
| 467 | @pushd "$(SSLDIR)" && $(PERL) Configure $(SSLCONFIG) && popd |
| 468 | @pushd "$(SSLDIR)" && call $(SSLSETUP) && popd |
| 469 | !ifdef FOSSIL_ENABLE_WINXP |
| 470 | @pushd "$(SSLDIR)" && $(MAKE) /f $(SSLNMAKE) "CC=cl $(XPCFLAGS)" "LFLAGS=$(SSLLFLAGS) $(XPLDFLAGS)" && popd |
| 471 | !else |
| 472 | @pushd "$(SSLDIR)" && $(MAKE) /f $(SSLNMAKE) && popd |
| 473 | !endif |
| 474 | !endif |
| 475 | |
| 476 | !ifndef FOSSIL_ENABLE_MINIZ |
| 477 | APPTARGETS = $(APPTARGETS) zlib |
| @@ -576,10 +587,11 @@ | |
| 576 | echo $(OX)\search.obj >> $@ |
| 577 | echo $(OX)\setup.obj >> $@ |
| 578 | echo $(OX)\sha1.obj >> $@ |
| 579 | echo $(OX)\shell.obj >> $@ |
| 580 | echo $(OX)\shun.obj >> $@ |
| 581 | echo $(OX)\skins.obj >> $@ |
| 582 | echo $(OX)\sqlcmd.obj >> $@ |
| 583 | echo $(OX)\sqlite3.obj >> $@ |
| 584 | echo $(OX)\stash.obj >> $@ |
| 585 | echo $(OX)\stat.obj >> $@ |
| @@ -1229,10 +1241,16 @@ | |
| 1229 | $(OX)\shun$O : shun_.c shun.h |
| 1230 | $(TCC) /Fo$@ -c shun_.c |
| 1231 | |
| 1232 | shun_.c : $(SRCDIR)\shun.c |
| 1233 | translate$E $** > $@ |
| 1234 | |
| 1235 | $(OX)\skins$O : skins_.c skins.h |
| 1236 | $(TCC) /Fo$@ -c skins_.c |
| 1237 | |
| 1238 | skins_.c : $(SRCDIR)\skins.c |
| @@ -1495,10 +1513,11 @@ | |
| 1495 | schema_.c:schema.h \ |
| 1496 | search_.c:search.h \ |
| 1497 | setup_.c:setup.h \ |
| 1498 | sha1_.c:sha1.h \ |
| 1499 | shun_.c:shun.h \ |
| 1500 | skins_.c:skins.h \ |
| 1501 | sqlcmd_.c:sqlcmd.h \ |
| 1502 | stash_.c:stash.h \ |
| 1503 | stat_.c:stat.h \ |
| 1504 | style_.c:style.h \ |
| 1505 |
| --- win/Makefile.msc | |
| +++ win/Makefile.msc | |
| @@ -62,23 +62,32 @@ | |
| 62 | SSLLIBDIR = $(SSLDIR)\out32 |
| 63 | SSLLFLAGS = /nologo /opt:ref /debug |
| 64 | SSLLIB = ssleay32.lib libeay32.lib user32.lib gdi32.lib |
| 65 | !if "$(PLATFORM)"=="amd64" || "$(PLATFORM)"=="x64" |
| 66 | !message Using 'x64' platform for OpenSSL... |
| 67 | # BUGBUG (OpenSSL): Apparently, using "no-ssl*" here breaks the build. |
| 68 | # SSLCONFIG = VC-WIN64A no-asm no-ssl2 no-ssl3 no-shared |
| 69 | SSLCONFIG = VC-WIN64A no-asm no-shared |
| 70 | SSLSETUP = ms\do_win64a.bat |
| 71 | SSLNMAKE = ms\nt.mak all |
| 72 | SSLCFLAGS = -DOPENSSL_NO_SSL2 -DOPENSSL_NO_SSL3 |
| 73 | !elseif "$(PLATFORM)"=="ia64" |
| 74 | !message Using 'ia64' platform for OpenSSL... |
| 75 | # BUGBUG (OpenSSL): Apparently, using "no-ssl*" here breaks the build. |
| 76 | # SSLCONFIG = VC-WIN64I no-asm no-ssl2 no-ssl3 no-shared |
| 77 | SSLCONFIG = VC-WIN64I no-asm no-shared |
| 78 | SSLSETUP = ms\do_win64i.bat |
| 79 | SSLNMAKE = ms\nt.mak all |
| 80 | SSLCFLAGS = -DOPENSSL_NO_SSL2 -DOPENSSL_NO_SSL3 |
| 81 | !else |
| 82 | !message Assuming 'x86' platform for OpenSSL... |
| 83 | # BUGBUG (OpenSSL): Apparently, using "no-ssl*" here breaks the build. |
| 84 | # SSLCONFIG = VC-WIN32 no-asm no-ssl2 no-ssl3 no-shared |
| 85 | SSLCONFIG = VC-WIN32 no-asm no-shared |
| 86 | SSLSETUP = ms\do_ms.bat |
| 87 | SSLNMAKE = ms\nt.mak all |
| 88 | SSLCFLAGS = -DOPENSSL_NO_SSL2 -DOPENSSL_NO_SSL3 |
| 89 | !endif |
| 90 | !endif |
| 91 | |
| 92 | !ifdef FOSSIL_ENABLE_TCL |
| 93 | TCLDIR = $(B)\compat\tcl-8.6 |
| @@ -282,10 +291,11 @@ | |
| 291 | schema_.c \ |
| 292 | search_.c \ |
| 293 | setup_.c \ |
| 294 | sha1_.c \ |
| 295 | shun_.c \ |
| 296 | sitemap_.c \ |
| 297 | skins_.c \ |
| 298 | sqlcmd_.c \ |
| 299 | stash_.c \ |
| 300 | stat_.c \ |
| 301 | style_.c \ |
| @@ -403,10 +413,11 @@ | |
| 413 | $(OX)\search$O \ |
| 414 | $(OX)\setup$O \ |
| 415 | $(OX)\sha1$O \ |
| 416 | $(OX)\shell$O \ |
| 417 | $(OX)\shun$O \ |
| 418 | $(OX)\sitemap$O \ |
| 419 | $(OX)\skins$O \ |
| 420 | $(OX)\sqlcmd$O \ |
| 421 | $(OX)\sqlite3$O \ |
| 422 | $(OX)\stash$O \ |
| 423 | $(OX)\stat$O \ |
| @@ -465,13 +476,13 @@ | |
| 476 | @set PATH=$(PERLDIR);$(PATH) |
| 477 | !endif |
| 478 | @pushd "$(SSLDIR)" && $(PERL) Configure $(SSLCONFIG) && popd |
| 479 | @pushd "$(SSLDIR)" && call $(SSLSETUP) && popd |
| 480 | !ifdef FOSSIL_ENABLE_WINXP |
| 481 | @pushd "$(SSLDIR)" && $(MAKE) /f $(SSLNMAKE) "CC=cl $(SSLCFLAGS) $(XPCFLAGS)" "LFLAGS=$(SSLLFLAGS) $(XPLDFLAGS)" && popd |
| 482 | !else |
| 483 | @pushd "$(SSLDIR)" && $(MAKE) /f $(SSLNMAKE) "CC=cl $(SSLCFLAGS)" && popd |
| 484 | !endif |
| 485 | !endif |
| 486 | |
| 487 | !ifndef FOSSIL_ENABLE_MINIZ |
| 488 | APPTARGETS = $(APPTARGETS) zlib |
| @@ -576,10 +587,11 @@ | |
| 587 | echo $(OX)\search.obj >> $@ |
| 588 | echo $(OX)\setup.obj >> $@ |
| 589 | echo $(OX)\sha1.obj >> $@ |
| 590 | echo $(OX)\shell.obj >> $@ |
| 591 | echo $(OX)\shun.obj >> $@ |
| 592 | echo $(OX)\sitemap.obj >> $@ |
| 593 | echo $(OX)\skins.obj >> $@ |
| 594 | echo $(OX)\sqlcmd.obj >> $@ |
| 595 | echo $(OX)\sqlite3.obj >> $@ |
| 596 | echo $(OX)\stash.obj >> $@ |
| 597 | echo $(OX)\stat.obj >> $@ |
| @@ -1229,10 +1241,16 @@ | |
| 1241 | $(OX)\shun$O : shun_.c shun.h |
| 1242 | $(TCC) /Fo$@ -c shun_.c |
| 1243 | |
| 1244 | shun_.c : $(SRCDIR)\shun.c |
| 1245 | translate$E $** > $@ |
| 1246 | |
| 1247 | $(OX)\sitemap$O : sitemap_.c sitemap.h |
| 1248 | $(TCC) /Fo$@ -c sitemap_.c |
| 1249 | |
| 1250 | sitemap_.c : $(SRCDIR)\sitemap.c |
| 1251 | translate$E $** > $@ |
| 1252 | |
| 1253 | $(OX)\skins$O : skins_.c skins.h |
| 1254 | $(TCC) /Fo$@ -c skins_.c |
| 1255 | |
| 1256 | skins_.c : $(SRCDIR)\skins.c |
| @@ -1495,10 +1513,11 @@ | |
| 1513 | schema_.c:schema.h \ |
| 1514 | search_.c:search.h \ |
| 1515 | setup_.c:setup.h \ |
| 1516 | sha1_.c:sha1.h \ |
| 1517 | shun_.c:shun.h \ |
| 1518 | sitemap_.c:sitemap.h \ |
| 1519 | skins_.c:skins.h \ |
| 1520 | sqlcmd_.c:sqlcmd.h \ |
| 1521 | stash_.c:stash.h \ |
| 1522 | stat_.c:stat.h \ |
| 1523 | style_.c:style.h \ |
| 1524 |
+1
-1
| --- www/concepts.wiki | ||
| +++ www/concepts.wiki | ||
| @@ -405,11 +405,11 @@ | ||
| 405 | 405 | can do pushes or pulls against your server. Use the <b>--port</b> |
| 406 | 406 | option to the server command to specify a different TCP port. If |
| 407 | 407 | you do not have a local source tree, use the <b>-R</b> command-line |
| 408 | 408 | option to specify the repository file. |
| 409 | 409 | |
| 410 | -A stand-alone server is a great way to set of transient connections | |
| 410 | +The "fossil server" command is a great way to set of transient connections | |
| 411 | 411 | between coworkers for doing quick pushes or pulls. But you can also |
| 412 | 412 | set up a permanent stand-alone server if you prefer. Just make |
| 413 | 413 | arrangements for fossil to be launched with appropriate arguments |
| 414 | 414 | after every reboot. |
| 415 | 415 | |
| 416 | 416 |
| --- www/concepts.wiki | |
| +++ www/concepts.wiki | |
| @@ -405,11 +405,11 @@ | |
| 405 | can do pushes or pulls against your server. Use the <b>--port</b> |
| 406 | option to the server command to specify a different TCP port. If |
| 407 | you do not have a local source tree, use the <b>-R</b> command-line |
| 408 | option to specify the repository file. |
| 409 | |
| 410 | A stand-alone server is a great way to set of transient connections |
| 411 | between coworkers for doing quick pushes or pulls. But you can also |
| 412 | set up a permanent stand-alone server if you prefer. Just make |
| 413 | arrangements for fossil to be launched with appropriate arguments |
| 414 | after every reboot. |
| 415 | |
| 416 |
| --- www/concepts.wiki | |
| +++ www/concepts.wiki | |
| @@ -405,11 +405,11 @@ | |
| 405 | can do pushes or pulls against your server. Use the <b>--port</b> |
| 406 | option to the server command to specify a different TCP port. If |
| 407 | you do not have a local source tree, use the <b>-R</b> command-line |
| 408 | option to specify the repository file. |
| 409 | |
| 410 | The "fossil server" command is a great way to set of transient connections |
| 411 | between coworkers for doing quick pushes or pulls. But you can also |
| 412 | set up a permanent stand-alone server if you prefer. Just make |
| 413 | arrangements for fossil to be launched with appropriate arguments |
| 414 | after every reboot. |
| 415 | |
| 416 |
+8
-8
| --- www/faq.tcl | ||
| +++ www/faq.tcl | ||
| @@ -55,12 +55,12 @@ | ||
| 55 | 55 | If you already have a fork in your check-in tree and you want to convert |
| 56 | 56 | that fork to a branch, you can do this from the web interface. |
| 57 | 57 | First locate the check-in that you want to be |
| 58 | 58 | the initial check-in of your branch on the timeline and click on its |
| 59 | 59 | link so that you are on the <b>ci</b> page. Then find the "<b>edit</b>" |
| 60 | - link (near the "Commands:" label) and click on that. On the | |
| 61 | - "Edit Check-in" page, check the box beside "Branching:" and fill in | |
| 60 | + link (near the "Commands:" label) and click on that. On the | |
| 61 | + "Edit Check-in" page, check the box beside "Branching:" and fill in | |
| 62 | 62 | the name of your new branch to the right and press the "Apply Changes" |
| 63 | 63 | button. |
| 64 | 64 | } |
| 65 | 65 | |
| 66 | 66 | faq { |
| @@ -83,31 +83,31 @@ | ||
| 83 | 83 | |
| 84 | 84 | The CHECK-IN in the previous line can be any |
| 85 | 85 | [./checkin_names.wiki | valid check-in name format]. |
| 86 | 86 | |
| 87 | 87 | You can also add (and remove) tags from a check-in using the |
| 88 | - [./webui.wiki | web interface]. First locate the check-in that you | |
| 88 | + [./webui.wiki | web interface]. First locate the check-in that you | |
| 89 | 89 | what to tag on the tmline, then click on the link to go the detailed |
| 90 | 90 | information page for that check-in. Then find the "<b>edit</b>" |
| 91 | 91 | link (near the "Commands:" label) and click on that. There are |
| 92 | 92 | controls on the edit page that allow new tags to be added and existing |
| 93 | 93 | tags to be removed. |
| 94 | -} | |
| 94 | +} | |
| 95 | 95 | |
| 96 | 96 | faq { |
| 97 | 97 | How do I create a private branch that won't get pushed back to the |
| 98 | 98 | main repository. |
| 99 | 99 | } { |
| 100 | - Use the <b>--private</b> command-line option on the | |
| 100 | + Use the <b>--private</b> command-line option on the | |
| 101 | 101 | <b>commit</b> command. The result will be a check-in which exists on |
| 102 | - your local repository only and is never pushed to other repositories. | |
| 102 | + your local repository only and is never pushed to other repositories. | |
| 103 | 103 | All descendents of a private check-in are also private. |
| 104 | - | |
| 104 | + | |
| 105 | 105 | Unless you specify something different using the <b>--branch</b> and/or |
| 106 | 106 | <b>--bgcolor</b> options, the new private check-in will be put on a branch |
| 107 | 107 | named "private" with an orange background color. |
| 108 | - | |
| 108 | + | |
| 109 | 109 | You can merge from the trunk into your private branch in order to keep |
| 110 | 110 | your private branch in sync with the latest changes on the trunk. Once |
| 111 | 111 | you have everything in your private branch the way you want it, you can |
| 112 | 112 | then merge your private branch back into the trunk and push. Only the |
| 113 | 113 | final merge operation will appear in other repositories. It will seem |
| 114 | 114 |
| --- www/faq.tcl | |
| +++ www/faq.tcl | |
| @@ -55,12 +55,12 @@ | |
| 55 | If you already have a fork in your check-in tree and you want to convert |
| 56 | that fork to a branch, you can do this from the web interface. |
| 57 | First locate the check-in that you want to be |
| 58 | the initial check-in of your branch on the timeline and click on its |
| 59 | link so that you are on the <b>ci</b> page. Then find the "<b>edit</b>" |
| 60 | link (near the "Commands:" label) and click on that. On the |
| 61 | "Edit Check-in" page, check the box beside "Branching:" and fill in |
| 62 | the name of your new branch to the right and press the "Apply Changes" |
| 63 | button. |
| 64 | } |
| 65 | |
| 66 | faq { |
| @@ -83,31 +83,31 @@ | |
| 83 | |
| 84 | The CHECK-IN in the previous line can be any |
| 85 | [./checkin_names.wiki | valid check-in name format]. |
| 86 | |
| 87 | You can also add (and remove) tags from a check-in using the |
| 88 | [./webui.wiki | web interface]. First locate the check-in that you |
| 89 | what to tag on the tmline, then click on the link to go the detailed |
| 90 | information page for that check-in. Then find the "<b>edit</b>" |
| 91 | link (near the "Commands:" label) and click on that. There are |
| 92 | controls on the edit page that allow new tags to be added and existing |
| 93 | tags to be removed. |
| 94 | } |
| 95 | |
| 96 | faq { |
| 97 | How do I create a private branch that won't get pushed back to the |
| 98 | main repository. |
| 99 | } { |
| 100 | Use the <b>--private</b> command-line option on the |
| 101 | <b>commit</b> command. The result will be a check-in which exists on |
| 102 | your local repository only and is never pushed to other repositories. |
| 103 | All descendents of a private check-in are also private. |
| 104 | |
| 105 | Unless you specify something different using the <b>--branch</b> and/or |
| 106 | <b>--bgcolor</b> options, the new private check-in will be put on a branch |
| 107 | named "private" with an orange background color. |
| 108 | |
| 109 | You can merge from the trunk into your private branch in order to keep |
| 110 | your private branch in sync with the latest changes on the trunk. Once |
| 111 | you have everything in your private branch the way you want it, you can |
| 112 | then merge your private branch back into the trunk and push. Only the |
| 113 | final merge operation will appear in other repositories. It will seem |
| 114 |
| --- www/faq.tcl | |
| +++ www/faq.tcl | |
| @@ -55,12 +55,12 @@ | |
| 55 | If you already have a fork in your check-in tree and you want to convert |
| 56 | that fork to a branch, you can do this from the web interface. |
| 57 | First locate the check-in that you want to be |
| 58 | the initial check-in of your branch on the timeline and click on its |
| 59 | link so that you are on the <b>ci</b> page. Then find the "<b>edit</b>" |
| 60 | link (near the "Commands:" label) and click on that. On the |
| 61 | "Edit Check-in" page, check the box beside "Branching:" and fill in |
| 62 | the name of your new branch to the right and press the "Apply Changes" |
| 63 | button. |
| 64 | } |
| 65 | |
| 66 | faq { |
| @@ -83,31 +83,31 @@ | |
| 83 | |
| 84 | The CHECK-IN in the previous line can be any |
| 85 | [./checkin_names.wiki | valid check-in name format]. |
| 86 | |
| 87 | You can also add (and remove) tags from a check-in using the |
| 88 | [./webui.wiki | web interface]. First locate the check-in that you |
| 89 | what to tag on the tmline, then click on the link to go the detailed |
| 90 | information page for that check-in. Then find the "<b>edit</b>" |
| 91 | link (near the "Commands:" label) and click on that. There are |
| 92 | controls on the edit page that allow new tags to be added and existing |
| 93 | tags to be removed. |
| 94 | } |
| 95 | |
| 96 | faq { |
| 97 | How do I create a private branch that won't get pushed back to the |
| 98 | main repository. |
| 99 | } { |
| 100 | Use the <b>--private</b> command-line option on the |
| 101 | <b>commit</b> command. The result will be a check-in which exists on |
| 102 | your local repository only and is never pushed to other repositories. |
| 103 | All descendents of a private check-in are also private. |
| 104 | |
| 105 | Unless you specify something different using the <b>--branch</b> and/or |
| 106 | <b>--bgcolor</b> options, the new private check-in will be put on a branch |
| 107 | named "private" with an orange background color. |
| 108 | |
| 109 | You can merge from the trunk into your private branch in order to keep |
| 110 | your private branch in sync with the latest changes on the trunk. Once |
| 111 | you have everything in your private branch the way you want it, you can |
| 112 | then merge your private branch back into the trunk and push. Only the |
| 113 | final merge operation will appear in other repositories. It will seem |
| 114 |
+5
-5
| --- www/fileformat.wiki | ||
| +++ www/fileformat.wiki | ||
| @@ -49,11 +49,11 @@ | ||
| 49 | 49 | </ul> |
| 50 | 50 | |
| 51 | 51 | These seven artifact types are described in the following sections. |
| 52 | 52 | |
| 53 | 53 | In the current implementation (as of 2009-01-25) the artifacts that |
| 54 | -make up a fossil repository are stored in in as delta- and zlib-compressed | |
| 54 | +make up a fossil repository are stored as delta- and zlib-compressed | |
| 55 | 55 | blobs in an <a href="http://www.sqlite.org/">SQLite</a> database. This |
| 56 | 56 | is an implementation detail and might change in a future release. For |
| 57 | 57 | the purpose of this article "file format" means the format of the artifacts, |
| 58 | 58 | not how the artifacts are stored on disk. It is the artifact format that |
| 59 | 59 | is intended to be enduring. The specifics of how artifacts are stored on |
| @@ -184,11 +184,11 @@ | ||
| 184 | 184 | ancestor, the Q-card is used to identify a single check-in or a small |
| 185 | 185 | range of check-ins which were cherry-picked for inclusion in or |
| 186 | 186 | exclusion from the current manifest. The first argument of |
| 187 | 187 | the Q-card is the artifact ID of another manifest (the "target") |
| 188 | 188 | which has had its changes included or excluded in the current manifest. |
| 189 | -The target is preceeded by "+" or "-" to show inclusion or | |
| 189 | +The target is preceded by "+" or "-" to show inclusion or | |
| 190 | 190 | exclusion, respectively. The optional second argument to the |
| 191 | 191 | Q-card is another manifest artifact ID which is the "baseline" |
| 192 | 192 | for the cherry-pick. If omitted, the baseline is the primary |
| 193 | 193 | parent of the target. The |
| 194 | 194 | changes included or excluded consist of all changes moving from |
| @@ -315,11 +315,11 @@ | ||
| 315 | 315 | is either "+", "-", or "*". The "+" means the tag should be added |
| 316 | 316 | to the artifact. The "-" means the tag should be removed. |
| 317 | 317 | The "*" character means the tag should be added to the artifact |
| 318 | 318 | and all direct descendants (but not descendents through a merge) down |
| 319 | 319 | to but not including the first descendant that contains a |
| 320 | -more recent "-" or "+" tag with the same name. | |
| 320 | +more recent "-", "*", or "+" tag with the same name. | |
| 321 | 321 | The optional third argument is the value of the tag. A tag |
| 322 | 322 | without a value is a boolean. |
| 323 | 323 | |
| 324 | 324 | When two or more tags with the same name are applied to the |
| 325 | 325 | same artifact, the tag with the latest (most recent) date is |
| @@ -362,11 +362,11 @@ | ||
| 362 | 362 | gives the name of the wiki page. The optional N card specifies |
| 363 | 363 | the mimetype of the wiki text. If the N card is omitted, the |
| 364 | 364 | mimetype is assumed to be text/x-fossil-wiki. |
| 365 | 365 | The U card specifies the login |
| 366 | 366 | of the user who made this edit to the wiki page. The Z card is |
| 367 | -the usual checksum over the either artifact and is required. | |
| 367 | +the usual checksum over the entire artifact and is required. | |
| 368 | 368 | |
| 369 | 369 | The W card is used to specify the text of the wiki page. The |
| 370 | 370 | argument to the W card is an integer which is the number of bytes |
| 371 | 371 | of text in the wiki page. That text follows the newline character |
| 372 | 372 | that terminates the W card. The wiki text is always followed by one |
| @@ -453,11 +453,11 @@ | ||
| 453 | 453 | |
| 454 | 454 | There may be zero or one N cards. The N card specifies the mimetype of the |
| 455 | 455 | comment text provided in the C card. If the N card is omitted, the C card |
| 456 | 456 | mimetype is taken to be text/plain. |
| 457 | 457 | |
| 458 | -A single U card gives the name of the user to added the attachment. | |
| 458 | +A single U card gives the name of the user who added the attachment. | |
| 459 | 459 | If an attachment is added anonymously, then the U card may be omitted. |
| 460 | 460 | |
| 461 | 461 | The Z card is the usual checksum over the rest of the attachment artifact. |
| 462 | 462 | The Z card is required. |
| 463 | 463 | |
| 464 | 464 |
| --- www/fileformat.wiki | |
| +++ www/fileformat.wiki | |
| @@ -49,11 +49,11 @@ | |
| 49 | </ul> |
| 50 | |
| 51 | These seven artifact types are described in the following sections. |
| 52 | |
| 53 | In the current implementation (as of 2009-01-25) the artifacts that |
| 54 | make up a fossil repository are stored in in as delta- and zlib-compressed |
| 55 | blobs in an <a href="http://www.sqlite.org/">SQLite</a> database. This |
| 56 | is an implementation detail and might change in a future release. For |
| 57 | the purpose of this article "file format" means the format of the artifacts, |
| 58 | not how the artifacts are stored on disk. It is the artifact format that |
| 59 | is intended to be enduring. The specifics of how artifacts are stored on |
| @@ -184,11 +184,11 @@ | |
| 184 | ancestor, the Q-card is used to identify a single check-in or a small |
| 185 | range of check-ins which were cherry-picked for inclusion in or |
| 186 | exclusion from the current manifest. The first argument of |
| 187 | the Q-card is the artifact ID of another manifest (the "target") |
| 188 | which has had its changes included or excluded in the current manifest. |
| 189 | The target is preceeded by "+" or "-" to show inclusion or |
| 190 | exclusion, respectively. The optional second argument to the |
| 191 | Q-card is another manifest artifact ID which is the "baseline" |
| 192 | for the cherry-pick. If omitted, the baseline is the primary |
| 193 | parent of the target. The |
| 194 | changes included or excluded consist of all changes moving from |
| @@ -315,11 +315,11 @@ | |
| 315 | is either "+", "-", or "*". The "+" means the tag should be added |
| 316 | to the artifact. The "-" means the tag should be removed. |
| 317 | The "*" character means the tag should be added to the artifact |
| 318 | and all direct descendants (but not descendents through a merge) down |
| 319 | to but not including the first descendant that contains a |
| 320 | more recent "-" or "+" tag with the same name. |
| 321 | The optional third argument is the value of the tag. A tag |
| 322 | without a value is a boolean. |
| 323 | |
| 324 | When two or more tags with the same name are applied to the |
| 325 | same artifact, the tag with the latest (most recent) date is |
| @@ -362,11 +362,11 @@ | |
| 362 | gives the name of the wiki page. The optional N card specifies |
| 363 | the mimetype of the wiki text. If the N card is omitted, the |
| 364 | mimetype is assumed to be text/x-fossil-wiki. |
| 365 | The U card specifies the login |
| 366 | of the user who made this edit to the wiki page. The Z card is |
| 367 | the usual checksum over the either artifact and is required. |
| 368 | |
| 369 | The W card is used to specify the text of the wiki page. The |
| 370 | argument to the W card is an integer which is the number of bytes |
| 371 | of text in the wiki page. That text follows the newline character |
| 372 | that terminates the W card. The wiki text is always followed by one |
| @@ -453,11 +453,11 @@ | |
| 453 | |
| 454 | There may be zero or one N cards. The N card specifies the mimetype of the |
| 455 | comment text provided in the C card. If the N card is omitted, the C card |
| 456 | mimetype is taken to be text/plain. |
| 457 | |
| 458 | A single U card gives the name of the user to added the attachment. |
| 459 | If an attachment is added anonymously, then the U card may be omitted. |
| 460 | |
| 461 | The Z card is the usual checksum over the rest of the attachment artifact. |
| 462 | The Z card is required. |
| 463 | |
| 464 |
| --- www/fileformat.wiki | |
| +++ www/fileformat.wiki | |
| @@ -49,11 +49,11 @@ | |
| 49 | </ul> |
| 50 | |
| 51 | These seven artifact types are described in the following sections. |
| 52 | |
| 53 | In the current implementation (as of 2009-01-25) the artifacts that |
| 54 | make up a fossil repository are stored as delta- and zlib-compressed |
| 55 | blobs in an <a href="http://www.sqlite.org/">SQLite</a> database. This |
| 56 | is an implementation detail and might change in a future release. For |
| 57 | the purpose of this article "file format" means the format of the artifacts, |
| 58 | not how the artifacts are stored on disk. It is the artifact format that |
| 59 | is intended to be enduring. The specifics of how artifacts are stored on |
| @@ -184,11 +184,11 @@ | |
| 184 | ancestor, the Q-card is used to identify a single check-in or a small |
| 185 | range of check-ins which were cherry-picked for inclusion in or |
| 186 | exclusion from the current manifest. The first argument of |
| 187 | the Q-card is the artifact ID of another manifest (the "target") |
| 188 | which has had its changes included or excluded in the current manifest. |
| 189 | The target is preceded by "+" or "-" to show inclusion or |
| 190 | exclusion, respectively. The optional second argument to the |
| 191 | Q-card is another manifest artifact ID which is the "baseline" |
| 192 | for the cherry-pick. If omitted, the baseline is the primary |
| 193 | parent of the target. The |
| 194 | changes included or excluded consist of all changes moving from |
| @@ -315,11 +315,11 @@ | |
| 315 | is either "+", "-", or "*". The "+" means the tag should be added |
| 316 | to the artifact. The "-" means the tag should be removed. |
| 317 | The "*" character means the tag should be added to the artifact |
| 318 | and all direct descendants (but not descendents through a merge) down |
| 319 | to but not including the first descendant that contains a |
| 320 | more recent "-", "*", or "+" tag with the same name. |
| 321 | The optional third argument is the value of the tag. A tag |
| 322 | without a value is a boolean. |
| 323 | |
| 324 | When two or more tags with the same name are applied to the |
| 325 | same artifact, the tag with the latest (most recent) date is |
| @@ -362,11 +362,11 @@ | |
| 362 | gives the name of the wiki page. The optional N card specifies |
| 363 | the mimetype of the wiki text. If the N card is omitted, the |
| 364 | mimetype is assumed to be text/x-fossil-wiki. |
| 365 | The U card specifies the login |
| 366 | of the user who made this edit to the wiki page. The Z card is |
| 367 | the usual checksum over the entire artifact and is required. |
| 368 | |
| 369 | The W card is used to specify the text of the wiki page. The |
| 370 | argument to the W card is an integer which is the number of bytes |
| 371 | of text in the wiki page. That text follows the newline character |
| 372 | that terminates the W card. The wiki text is always followed by one |
| @@ -453,11 +453,11 @@ | |
| 453 | |
| 454 | There may be zero or one N cards. The N card specifies the mimetype of the |
| 455 | comment text provided in the C card. If the N card is omitted, the C card |
| 456 | mimetype is taken to be text/plain. |
| 457 | |
| 458 | A single U card gives the name of the user who added the attachment. |
| 459 | If an attachment is added anonymously, then the U card may be omitted. |
| 460 | |
| 461 | The Z card is the usual checksum over the rest of the attachment artifact. |
| 462 | The Z card is required. |
| 463 | |
| 464 |
+1
-1
| --- www/foss-cklist.wiki | ||
| +++ www/foss-cklist.wiki | ||
| @@ -5,11 +5,11 @@ | ||
| 5 | 5 | blog post <a href="http://spot.livejournal.com/308370.html"> |
| 6 | 6 | http://spot.livejournal.com/308370.html</a> (see also |
| 7 | 7 | <a href="http://www.theopensourceway.org/book/The_Open_Source_Way-How_to_tell_if_a_FLOSS_project_is_doomed_to_FAIL.html">[1]</a> and |
| 8 | 8 | <a href="https://www.theopensourceway.org/wiki/How_to_tell_if_a_FLOSS_project_is_doomed_to_FAIL">[2]</a>). |
| 9 | 9 | Tom's original post assigned point scores to the various elements and |
| 10 | -by adding together the individual points, the reader is suppose to be able | |
| 10 | +by adding together the individual points, the reader is supposed to be able | |
| 11 | 11 | to judge the likelihood that the project will fail. |
| 12 | 12 | The point scores, and the items on the list, clearly reflect Tom's |
| 13 | 13 | biases and are not necessarily those of the larger open-source community. |
| 14 | 14 | Nevertheless, the policy of the Fossil shall be to strive for a perfect |
| 15 | 15 | score.</p> |
| 16 | 16 |
| --- www/foss-cklist.wiki | |
| +++ www/foss-cklist.wiki | |
| @@ -5,11 +5,11 @@ | |
| 5 | blog post <a href="http://spot.livejournal.com/308370.html"> |
| 6 | http://spot.livejournal.com/308370.html</a> (see also |
| 7 | <a href="http://www.theopensourceway.org/book/The_Open_Source_Way-How_to_tell_if_a_FLOSS_project_is_doomed_to_FAIL.html">[1]</a> and |
| 8 | <a href="https://www.theopensourceway.org/wiki/How_to_tell_if_a_FLOSS_project_is_doomed_to_FAIL">[2]</a>). |
| 9 | Tom's original post assigned point scores to the various elements and |
| 10 | by adding together the individual points, the reader is suppose to be able |
| 11 | to judge the likelihood that the project will fail. |
| 12 | The point scores, and the items on the list, clearly reflect Tom's |
| 13 | biases and are not necessarily those of the larger open-source community. |
| 14 | Nevertheless, the policy of the Fossil shall be to strive for a perfect |
| 15 | score.</p> |
| 16 |
| --- www/foss-cklist.wiki | |
| +++ www/foss-cklist.wiki | |
| @@ -5,11 +5,11 @@ | |
| 5 | blog post <a href="http://spot.livejournal.com/308370.html"> |
| 6 | http://spot.livejournal.com/308370.html</a> (see also |
| 7 | <a href="http://www.theopensourceway.org/book/The_Open_Source_Way-How_to_tell_if_a_FLOSS_project_is_doomed_to_FAIL.html">[1]</a> and |
| 8 | <a href="https://www.theopensourceway.org/wiki/How_to_tell_if_a_FLOSS_project_is_doomed_to_FAIL">[2]</a>). |
| 9 | Tom's original post assigned point scores to the various elements and |
| 10 | by adding together the individual points, the reader is supposed to be able |
| 11 | to judge the likelihood that the project will fail. |
| 12 | The point scores, and the items on the list, clearly reflect Tom's |
| 13 | biases and are not necessarily those of the larger open-source community. |
| 14 | Nevertheless, the policy of the Fossil shall be to strive for a perfect |
| 15 | score.</p> |
| 16 |
+1
-1
| --- www/fossil-v-git.wiki | ||
| +++ www/fossil-v-git.wiki | ||
| @@ -185,11 +185,11 @@ | ||
| 185 | 185 | between repositories and working checkouts. A power-loss or system crash |
| 186 | 186 | in the middle of Git operation can damage or corrupt the Git repository. |
| 187 | 187 | |
| 188 | 188 | A Fossil repository consists of a single disk file. A single Fossil |
| 189 | 189 | repository can serve multiple simultaneous working checkouts. |
| 190 | -A Fossil repository is an SQLite database, so it highly resistant | |
| 190 | +A Fossil repository is an SQLite database, so it is highly resistant | |
| 191 | 191 | to damage from a power-loss or system crash - incomplete transactions |
| 192 | 192 | are simply rolled back after the system reboots. |
| 193 | 193 | |
| 194 | 194 | <h3>3.8 Audit Trail</h3> |
| 195 | 195 | |
| 196 | 196 |
| --- www/fossil-v-git.wiki | |
| +++ www/fossil-v-git.wiki | |
| @@ -185,11 +185,11 @@ | |
| 185 | between repositories and working checkouts. A power-loss or system crash |
| 186 | in the middle of Git operation can damage or corrupt the Git repository. |
| 187 | |
| 188 | A Fossil repository consists of a single disk file. A single Fossil |
| 189 | repository can serve multiple simultaneous working checkouts. |
| 190 | A Fossil repository is an SQLite database, so it highly resistant |
| 191 | to damage from a power-loss or system crash - incomplete transactions |
| 192 | are simply rolled back after the system reboots. |
| 193 | |
| 194 | <h3>3.8 Audit Trail</h3> |
| 195 | |
| 196 |
| --- www/fossil-v-git.wiki | |
| +++ www/fossil-v-git.wiki | |
| @@ -185,11 +185,11 @@ | |
| 185 | between repositories and working checkouts. A power-loss or system crash |
| 186 | in the middle of Git operation can damage or corrupt the Git repository. |
| 187 | |
| 188 | A Fossil repository consists of a single disk file. A single Fossil |
| 189 | repository can serve multiple simultaneous working checkouts. |
| 190 | A Fossil repository is an SQLite database, so it is highly resistant |
| 191 | to damage from a power-loss or system crash - incomplete transactions |
| 192 | are simply rolled back after the system reboots. |
| 193 | |
| 194 | <h3>3.8 Audit Trail</h3> |
| 195 | |
| 196 |
+4
| --- www/index.wiki | ||
| +++ www/index.wiki | ||
| @@ -110,10 +110,14 @@ | ||
| 110 | 110 | a Fossil repository. |
| 111 | 111 | |
| 112 | 112 | <hr> |
| 113 | 113 | <h3>Links For Fossil Users:</h3> |
| 114 | 114 | |
| 115 | + * "Fuel" is cross-platform GUI front-end for Fossil | |
| 116 | + written in Qt. [http://fuelscm.org/]. | |
| 117 | + Fuel is an independent project run by a different group of | |
| 118 | + developers. | |
| 115 | 119 | * [./reviews.wiki | Testimonials] from satisfied fossil users and |
| 116 | 120 | [./quotes.wiki | Quotes] about Fossil and other DVCSes. |
| 117 | 121 | * [./faq.wiki | FAQ] |
| 118 | 122 | * The [./concepts.wiki | concepts] behind fossil |
| 119 | 123 | * [./quickstart.wiki | Quick Start] guide to using fossil |
| 120 | 124 |
| --- www/index.wiki | |
| +++ www/index.wiki | |
| @@ -110,10 +110,14 @@ | |
| 110 | a Fossil repository. |
| 111 | |
| 112 | <hr> |
| 113 | <h3>Links For Fossil Users:</h3> |
| 114 | |
| 115 | * [./reviews.wiki | Testimonials] from satisfied fossil users and |
| 116 | [./quotes.wiki | Quotes] about Fossil and other DVCSes. |
| 117 | * [./faq.wiki | FAQ] |
| 118 | * The [./concepts.wiki | concepts] behind fossil |
| 119 | * [./quickstart.wiki | Quick Start] guide to using fossil |
| 120 |
| --- www/index.wiki | |
| +++ www/index.wiki | |
| @@ -110,10 +110,14 @@ | |
| 110 | a Fossil repository. |
| 111 | |
| 112 | <hr> |
| 113 | <h3>Links For Fossil Users:</h3> |
| 114 | |
| 115 | * "Fuel" is cross-platform GUI front-end for Fossil |
| 116 | written in Qt. [http://fuelscm.org/]. |
| 117 | Fuel is an independent project run by a different group of |
| 118 | developers. |
| 119 | * [./reviews.wiki | Testimonials] from satisfied fossil users and |
| 120 | [./quotes.wiki | Quotes] about Fossil and other DVCSes. |
| 121 | * [./faq.wiki | FAQ] |
| 122 | * The [./concepts.wiki | concepts] behind fossil |
| 123 | * [./quickstart.wiki | Quick Start] guide to using fossil |
| 124 |
+1
-1
| --- www/mkindex.tcl | ||
| +++ www/mkindex.tcl | ||
| @@ -1,8 +1,8 @@ | ||
| 1 | 1 | #!/bin/sh |
| 2 | 2 | # |
| 3 | -# Run this TCL script to generate a WIKI page that contains a | |
| 3 | +# Run this TCL script to generate a WIKI page that contains a | |
| 4 | 4 | # permuted index of the various documentation files. |
| 5 | 5 | # |
| 6 | 6 | # tclsh mkindex.tcl >permutedindex.wiki |
| 7 | 7 | # |
| 8 | 8 | |
| 9 | 9 |
| --- www/mkindex.tcl | |
| +++ www/mkindex.tcl | |
| @@ -1,8 +1,8 @@ | |
| 1 | #!/bin/sh |
| 2 | # |
| 3 | # Run this TCL script to generate a WIKI page that contains a |
| 4 | # permuted index of the various documentation files. |
| 5 | # |
| 6 | # tclsh mkindex.tcl >permutedindex.wiki |
| 7 | # |
| 8 | |
| 9 |
| --- www/mkindex.tcl | |
| +++ www/mkindex.tcl | |
| @@ -1,8 +1,8 @@ | |
| 1 | #!/bin/sh |
| 2 | # |
| 3 | # Run this TCL script to generate a WIKI page that contains a |
| 4 | # permuted index of the various documentation files. |
| 5 | # |
| 6 | # tclsh mkindex.tcl >permutedindex.wiki |
| 7 | # |
| 8 | |
| 9 |
+1
-1
| --- www/server.wiki | ||
| +++ www/server.wiki | ||
| @@ -70,11 +70,11 @@ | ||
| 70 | 70 | need to modify the pathnames for your particular setup. |
| 71 | 71 | The final argument is either the name of the fossil repository to be served, |
| 72 | 72 | or a directory containing multiple repositories. |
| 73 | 73 | </p> |
| 74 | 74 | <p> |
| 75 | -If you system is running xinetd, then the configuration is likely to be | |
| 75 | +If your system is running xinetd, then the configuration is likely to be | |
| 76 | 76 | in the file "/etc/xinetd.conf" or in a subfile of "/etc/xinetd.d". |
| 77 | 77 | An xinetd configuration file will appear like this:</p> |
| 78 | 78 | <blockquote> |
| 79 | 79 | <pre> |
| 80 | 80 | service http-alt |
| 81 | 81 |
| --- www/server.wiki | |
| +++ www/server.wiki | |
| @@ -70,11 +70,11 @@ | |
| 70 | need to modify the pathnames for your particular setup. |
| 71 | The final argument is either the name of the fossil repository to be served, |
| 72 | or a directory containing multiple repositories. |
| 73 | </p> |
| 74 | <p> |
| 75 | If you system is running xinetd, then the configuration is likely to be |
| 76 | in the file "/etc/xinetd.conf" or in a subfile of "/etc/xinetd.d". |
| 77 | An xinetd configuration file will appear like this:</p> |
| 78 | <blockquote> |
| 79 | <pre> |
| 80 | service http-alt |
| 81 |
| --- www/server.wiki | |
| +++ www/server.wiki | |
| @@ -70,11 +70,11 @@ | |
| 70 | need to modify the pathnames for your particular setup. |
| 71 | The final argument is either the name of the fossil repository to be served, |
| 72 | or a directory containing multiple repositories. |
| 73 | </p> |
| 74 | <p> |
| 75 | If your system is running xinetd, then the configuration is likely to be |
| 76 | in the file "/etc/xinetd.conf" or in a subfile of "/etc/xinetd.d". |
| 77 | An xinetd configuration file will appear like this:</p> |
| 78 | <blockquote> |
| 79 | <pre> |
| 80 | service http-alt |
| 81 |