Fossil SCM
merge with latest trunk
Commit
4d39236638ccacfdad3d6a979f37dfb93ae333c4
Parent
518e1f8d7fcb74b…
21 files changed
+1
-1
+1
-1
+25
-19
+27
+22
-7
+17
-7
+4
+31
-5
+72
+54
-1
+23
-17
+1
-1
+18
-2
+31
-6
+28
+13
-10
+2
-2
+1
+1
-1
+21
-8
+25
~
VERSION
~
ajax/js/whajaj.js
~
auto.def
~
autosetup/local.tcl
~
src/add.c
~
src/browse.c
~
src/configure.c
~
src/content.c
~
src/cson_amalgamation.c
~
src/cson_amalgamation.h
~
src/finfo.c
~
src/http.c
~
src/json_login.c
~
src/login.c
~
src/manifest.c
~
src/sqlite3.c
~
src/sqlite3.h
~
src/style.c
~
src/update.c
~
src/xfer.c
~
www/changes.wiki
M
VERSION
+1
-1
| --- VERSION | ||
| +++ VERSION | ||
| @@ -1,1 +1,1 @@ | ||
| 1 | -1.20 | |
| 1 | +1.21 | |
| 2 | 2 |
| --- VERSION | |
| +++ VERSION | |
| @@ -1,1 +1,1 @@ | |
| 1 | 1.20 |
| 2 |
| --- VERSION | |
| +++ VERSION | |
| @@ -1,1 +1,1 @@ | |
| 1 | 1.21 |
| 2 |
+1
-1
| --- ajax/js/whajaj.js | ||
| +++ ajax/js/whajaj.js | ||
| @@ -103,11 +103,11 @@ | ||
| 103 | 103 | like PHP does. |
| 104 | 104 | |
| 105 | 105 | */ |
| 106 | 106 | WhAjaj.processUrlArgs = function(str) { |
| 107 | 107 | if( 0 === arguments.length ) { |
| 108 | - if( (undefined === typeof window) || | |
| 108 | + if( ('undefined' === typeof window) || | |
| 109 | 109 | !window.location || |
| 110 | 110 | !window.location.search ) return false; |
| 111 | 111 | else str = (''+window.location.search).substring(1); |
| 112 | 112 | } |
| 113 | 113 | if( ! str ) return false; |
| 114 | 114 |
| --- ajax/js/whajaj.js | |
| +++ ajax/js/whajaj.js | |
| @@ -103,11 +103,11 @@ | |
| 103 | like PHP does. |
| 104 | |
| 105 | */ |
| 106 | WhAjaj.processUrlArgs = function(str) { |
| 107 | if( 0 === arguments.length ) { |
| 108 | if( (undefined === typeof window) || |
| 109 | !window.location || |
| 110 | !window.location.search ) return false; |
| 111 | else str = (''+window.location.search).substring(1); |
| 112 | } |
| 113 | if( ! str ) return false; |
| 114 |
| --- ajax/js/whajaj.js | |
| +++ ajax/js/whajaj.js | |
| @@ -103,11 +103,11 @@ | |
| 103 | like PHP does. |
| 104 | |
| 105 | */ |
| 106 | WhAjaj.processUrlArgs = function(str) { |
| 107 | if( 0 === arguments.length ) { |
| 108 | if( ('undefined' === typeof window) || |
| 109 | !window.location || |
| 110 | !window.location.search ) return false; |
| 111 | else str = (''+window.location.search).substring(1); |
| 112 | } |
| 113 | if( ! str ) return false; |
| 114 |
M
auto.def
+25
-19
| --- auto.def | ||
| +++ auto.def | ||
| @@ -87,30 +87,36 @@ | ||
| 87 | 87 | user-error "zlib not found please install it or specify the location with --with-zlib" |
| 88 | 88 | } |
| 89 | 89 | |
| 90 | 90 | set tclpath [opt-val with-tcl] |
| 91 | 91 | if {$tclpath ne ""} { |
| 92 | - if {$tclpath ne "1"} { | |
| 93 | - cc-with [list -cflags [list -I$tclpath/include -L$tclpath/lib]] | |
| 94 | - } | |
| 95 | - if {![cc-check-includes tcl.h]} { | |
| 96 | - user-error "Cannot find tcl.h" | |
| 97 | - } | |
| 98 | - foreach tlib {tcl8.6 tcl8.5 tcl notfound} { | |
| 99 | - if {$tlib=="notfound"} { | |
| 100 | - user-error "Cannot find a usable libtcl" | |
| 101 | - } | |
| 102 | - if {[cc-check-function-in-lib Tcl_CreateInterp $tlib]} { | |
| 103 | - define-append LIBS -l$tlib | |
| 104 | - break | |
| 105 | - } | |
| 106 | - } | |
| 92 | + # Note parse-tclconfig-sh is in autosetup/local.tcl | |
| 93 | + if {$tclpath eq "1"} { | |
| 94 | + # Use the system Tcl. Look in some likely places. | |
| 95 | + array set tclconfig [parse-tclconfig-sh /usr /usr/local /usr/share /opt/local] | |
| 96 | + set msg "on your system" | |
| 97 | + } else { | |
| 98 | + array set tclconfig [parse-tclconfig-sh $tclpath] | |
| 99 | + set msg "at $tclpath" | |
| 100 | + } | |
| 101 | + if {![info exists tclconfig(TCL_INCLUDE_SPEC)]} { | |
| 102 | + user-error "Cannot find Tcl $msg" | |
| 103 | + } | |
| 104 | + set cflags $tclconfig(TCL_INCLUDE_SPEC) | |
| 105 | + set libs "$tclconfig(TCL_LIB_SPEC) $tclconfig(TCL_LIBS)" | |
| 106 | + cc-with [list -cflags $cflags -libs $libs] { | |
| 107 | + if {![cc-check-functions Tcl_CreateInterp]} { | |
| 108 | + user-error "Cannot find a usable Tcl $msg" | |
| 109 | + } | |
| 110 | + } | |
| 111 | + set version $tclconfig(TCL_VERSION)$tclconfig(TCL_PATCH_LEVEL) | |
| 112 | + msg-result "Found Tcl $version at $tclconfig(TCL_PREFIX)" | |
| 113 | + define-append LIBS $libs | |
| 114 | + define-append EXTRA_CFLAGS $cflags | |
| 115 | + define-append EXTRA_LDFLAGS $tclconfig(TCL_LD_FLAGS) | |
| 116 | + | |
| 107 | 117 | define FOSSIL_ENABLE_TCL |
| 108 | - if {$tclpath ne "1"} { | |
| 109 | - define-append EXTRA_CFLAGS -I$tclpath/include | |
| 110 | - define-append EXTRA_LDFLAGS -L$tclpath/lib | |
| 111 | - } | |
| 112 | 118 | } |
| 113 | 119 | |
| 114 | 120 | # Helper for openssl checking |
| 115 | 121 | proc check-for-openssl {msg {cflags {}}} { |
| 116 | 122 | msg-checking "Checking for $msg..." |
| 117 | 123 |
| --- auto.def | |
| +++ auto.def | |
| @@ -87,30 +87,36 @@ | |
| 87 | user-error "zlib not found please install it or specify the location with --with-zlib" |
| 88 | } |
| 89 | |
| 90 | set tclpath [opt-val with-tcl] |
| 91 | if {$tclpath ne ""} { |
| 92 | if {$tclpath ne "1"} { |
| 93 | cc-with [list -cflags [list -I$tclpath/include -L$tclpath/lib]] |
| 94 | } |
| 95 | if {![cc-check-includes tcl.h]} { |
| 96 | user-error "Cannot find tcl.h" |
| 97 | } |
| 98 | foreach tlib {tcl8.6 tcl8.5 tcl notfound} { |
| 99 | if {$tlib=="notfound"} { |
| 100 | user-error "Cannot find a usable libtcl" |
| 101 | } |
| 102 | if {[cc-check-function-in-lib Tcl_CreateInterp $tlib]} { |
| 103 | define-append LIBS -l$tlib |
| 104 | break |
| 105 | } |
| 106 | } |
| 107 | define FOSSIL_ENABLE_TCL |
| 108 | if {$tclpath ne "1"} { |
| 109 | define-append EXTRA_CFLAGS -I$tclpath/include |
| 110 | define-append EXTRA_LDFLAGS -L$tclpath/lib |
| 111 | } |
| 112 | } |
| 113 | |
| 114 | # Helper for openssl checking |
| 115 | proc check-for-openssl {msg {cflags {}}} { |
| 116 | msg-checking "Checking for $msg..." |
| 117 |
| --- auto.def | |
| +++ auto.def | |
| @@ -87,30 +87,36 @@ | |
| 87 | user-error "zlib not found please install it or specify the location with --with-zlib" |
| 88 | } |
| 89 | |
| 90 | set tclpath [opt-val with-tcl] |
| 91 | if {$tclpath ne ""} { |
| 92 | # Note parse-tclconfig-sh is in autosetup/local.tcl |
| 93 | if {$tclpath eq "1"} { |
| 94 | # Use the system Tcl. Look in some likely places. |
| 95 | array set tclconfig [parse-tclconfig-sh /usr /usr/local /usr/share /opt/local] |
| 96 | set msg "on your system" |
| 97 | } else { |
| 98 | array set tclconfig [parse-tclconfig-sh $tclpath] |
| 99 | set msg "at $tclpath" |
| 100 | } |
| 101 | if {![info exists tclconfig(TCL_INCLUDE_SPEC)]} { |
| 102 | user-error "Cannot find Tcl $msg" |
| 103 | } |
| 104 | set cflags $tclconfig(TCL_INCLUDE_SPEC) |
| 105 | set libs "$tclconfig(TCL_LIB_SPEC) $tclconfig(TCL_LIBS)" |
| 106 | cc-with [list -cflags $cflags -libs $libs] { |
| 107 | if {![cc-check-functions Tcl_CreateInterp]} { |
| 108 | user-error "Cannot find a usable Tcl $msg" |
| 109 | } |
| 110 | } |
| 111 | set version $tclconfig(TCL_VERSION)$tclconfig(TCL_PATCH_LEVEL) |
| 112 | msg-result "Found Tcl $version at $tclconfig(TCL_PREFIX)" |
| 113 | define-append LIBS $libs |
| 114 | define-append EXTRA_CFLAGS $cflags |
| 115 | define-append EXTRA_LDFLAGS $tclconfig(TCL_LD_FLAGS) |
| 116 | |
| 117 | define FOSSIL_ENABLE_TCL |
| 118 | } |
| 119 | |
| 120 | # Helper for openssl checking |
| 121 | proc check-for-openssl {msg {cflags {}}} { |
| 122 | msg-checking "Checking for $msg..." |
| 123 |
+27
| --- autosetup/local.tcl | ||
| +++ autosetup/local.tcl | ||
| @@ -1,2 +1,29 @@ | ||
| 1 | 1 | # For this project, disable the pager for --help |
| 2 | 2 | set useropts(nopager) 1 |
| 3 | + | |
| 4 | +# Searches for a usable Tcl (prefer 8.6, 8.5, 8.4) in the given paths | |
| 5 | +# Returns a dictionary of the contents of the tclConfig.sh file, or | |
| 6 | +# empty if not found | |
| 7 | +proc parse-tclconfig-sh {args} { | |
| 8 | + foreach p $args { | |
| 9 | + # Allow pointing directly to the path containing tclConfig.sh | |
| 10 | + if {[file exists $p/tclConfig.sh]} { | |
| 11 | + return [parse-tclconfig-sh-file $p/tclConfig.sh] | |
| 12 | + } | |
| 13 | + # Some systems allow for multiple versions | |
| 14 | + foreach libpath {lib/tcl8.6 lib/tcl8.5 lib/tcl8.4 lib/tcl tcl lib} { | |
| 15 | + if {[file exists $p/$libpath/tclConfig.sh]} { | |
| 16 | + return [parse-tclconfig-sh-file $p/$libpath/tclConfig.sh] | |
| 17 | + } | |
| 18 | + } | |
| 19 | + } | |
| 20 | +} | |
| 21 | + | |
| 22 | +proc parse-tclconfig-sh-file {filename} { | |
| 23 | + foreach line [split [readfile $filename] \n] { | |
| 24 | + if {[regexp {^(TCL_[^=]*)=(.*)$} $line -> name value]} { | |
| 25 | + set tclconfig($name) [string trim $value '] | |
| 26 | + } | |
| 27 | + } | |
| 28 | + return [array get tclconfig] | |
| 29 | +} | |
| 3 | 30 |
| --- autosetup/local.tcl | |
| +++ autosetup/local.tcl | |
| @@ -1,2 +1,29 @@ | |
| 1 | # For this project, disable the pager for --help |
| 2 | set useropts(nopager) 1 |
| 3 |
| --- autosetup/local.tcl | |
| +++ autosetup/local.tcl | |
| @@ -1,2 +1,29 @@ | |
| 1 | # For this project, disable the pager for --help |
| 2 | set useropts(nopager) 1 |
| 3 | |
| 4 | # Searches for a usable Tcl (prefer 8.6, 8.5, 8.4) in the given paths |
| 5 | # Returns a dictionary of the contents of the tclConfig.sh file, or |
| 6 | # empty if not found |
| 7 | proc parse-tclconfig-sh {args} { |
| 8 | foreach p $args { |
| 9 | # Allow pointing directly to the path containing tclConfig.sh |
| 10 | if {[file exists $p/tclConfig.sh]} { |
| 11 | return [parse-tclconfig-sh-file $p/tclConfig.sh] |
| 12 | } |
| 13 | # Some systems allow for multiple versions |
| 14 | foreach libpath {lib/tcl8.6 lib/tcl8.5 lib/tcl8.4 lib/tcl tcl lib} { |
| 15 | if {[file exists $p/$libpath/tclConfig.sh]} { |
| 16 | return [parse-tclconfig-sh-file $p/$libpath/tclConfig.sh] |
| 17 | } |
| 18 | } |
| 19 | } |
| 20 | } |
| 21 | |
| 22 | proc parse-tclconfig-sh-file {filename} { |
| 23 | foreach line [split [readfile $filename] \n] { |
| 24 | if {[regexp {^(TCL_[^=]*)=(.*)$} $line -> name value]} { |
| 25 | set tclconfig($name) [string trim $value '] |
| 26 | } |
| 27 | } |
| 28 | return [array get tclconfig] |
| 29 | } |
| 30 |
+22
-7
| --- src/add.c | ||
| +++ src/add.c | ||
| @@ -337,24 +337,39 @@ | ||
| 337 | 337 | ** |
| 338 | 338 | ** The --case-sensitive BOOLEAN command-line option overrides any |
| 339 | 339 | ** setting. |
| 340 | 340 | */ |
| 341 | 341 | int filenames_are_case_sensitive(void){ |
| 342 | - int caseSensitive; | |
| 342 | + static int caseSensitive; | |
| 343 | + static int once = 1; | |
| 343 | 344 | |
| 344 | - if( zCaseSensitive ){ | |
| 345 | - caseSensitive = is_truth(zCaseSensitive); | |
| 346 | - }else{ | |
| 345 | + if( once ){ | |
| 346 | + once = 0; | |
| 347 | + if( zCaseSensitive ){ | |
| 348 | + caseSensitive = is_truth(zCaseSensitive); | |
| 349 | + }else{ | |
| 347 | 350 | #if !defined(_WIN32) && !defined(__DARWIN__) && !defined(__APPLE__) |
| 348 | - caseSensitive = 1; | |
| 351 | + caseSensitive = 1; /* Unix */ | |
| 349 | 352 | #else |
| 350 | - caseSensitive = 0; | |
| 353 | + caseSensitive = 0; /* Windows and Mac */ | |
| 351 | 354 | #endif |
| 352 | - caseSensitive = db_get_boolean("case-sensitive",caseSensitive); | |
| 355 | + caseSensitive = db_get_boolean("case-sensitive",caseSensitive); | |
| 356 | + } | |
| 353 | 357 | } |
| 354 | 358 | return caseSensitive; |
| 355 | 359 | } |
| 360 | + | |
| 361 | +/* | |
| 362 | +** Return one of two things: | |
| 363 | +** | |
| 364 | +** "" (empty string) if filenames are case sensitive | |
| 365 | +** | |
| 366 | +** "COLLATE nocase" if filenames are not case sensitive. | |
| 367 | +*/ | |
| 368 | +const char *filename_collation(void){ | |
| 369 | + return filenames_are_case_sensitive() ? "" : "COLLATE nocase"; | |
| 370 | +} | |
| 356 | 371 | |
| 357 | 372 | /* |
| 358 | 373 | ** COMMAND: addremove |
| 359 | 374 | ** |
| 360 | 375 | ** Usage: %fossil addremove ?OPTIONS? |
| 361 | 376 |
| --- src/add.c | |
| +++ src/add.c | |
| @@ -337,24 +337,39 @@ | |
| 337 | ** |
| 338 | ** The --case-sensitive BOOLEAN command-line option overrides any |
| 339 | ** setting. |
| 340 | */ |
| 341 | int filenames_are_case_sensitive(void){ |
| 342 | int caseSensitive; |
| 343 | |
| 344 | if( zCaseSensitive ){ |
| 345 | caseSensitive = is_truth(zCaseSensitive); |
| 346 | }else{ |
| 347 | #if !defined(_WIN32) && !defined(__DARWIN__) && !defined(__APPLE__) |
| 348 | caseSensitive = 1; |
| 349 | #else |
| 350 | caseSensitive = 0; |
| 351 | #endif |
| 352 | caseSensitive = db_get_boolean("case-sensitive",caseSensitive); |
| 353 | } |
| 354 | return caseSensitive; |
| 355 | } |
| 356 | |
| 357 | /* |
| 358 | ** COMMAND: addremove |
| 359 | ** |
| 360 | ** Usage: %fossil addremove ?OPTIONS? |
| 361 |
| --- src/add.c | |
| +++ src/add.c | |
| @@ -337,24 +337,39 @@ | |
| 337 | ** |
| 338 | ** The --case-sensitive BOOLEAN command-line option overrides any |
| 339 | ** setting. |
| 340 | */ |
| 341 | int filenames_are_case_sensitive(void){ |
| 342 | static int caseSensitive; |
| 343 | static int once = 1; |
| 344 | |
| 345 | if( once ){ |
| 346 | once = 0; |
| 347 | if( zCaseSensitive ){ |
| 348 | caseSensitive = is_truth(zCaseSensitive); |
| 349 | }else{ |
| 350 | #if !defined(_WIN32) && !defined(__DARWIN__) && !defined(__APPLE__) |
| 351 | caseSensitive = 1; /* Unix */ |
| 352 | #else |
| 353 | caseSensitive = 0; /* Windows and Mac */ |
| 354 | #endif |
| 355 | caseSensitive = db_get_boolean("case-sensitive",caseSensitive); |
| 356 | } |
| 357 | } |
| 358 | return caseSensitive; |
| 359 | } |
| 360 | |
| 361 | /* |
| 362 | ** Return one of two things: |
| 363 | ** |
| 364 | ** "" (empty string) if filenames are case sensitive |
| 365 | ** |
| 366 | ** "COLLATE nocase" if filenames are not case sensitive. |
| 367 | */ |
| 368 | const char *filename_collation(void){ |
| 369 | return filenames_are_case_sensitive() ? "" : "COLLATE nocase"; |
| 370 | } |
| 371 | |
| 372 | /* |
| 373 | ** COMMAND: addremove |
| 374 | ** |
| 375 | ** Usage: %fossil addremove ?OPTIONS? |
| 376 |
+17
-7
| --- src/browse.c | ||
| +++ src/browse.c | ||
| @@ -196,11 +196,12 @@ | ||
| 196 | 196 | ** Subdirectory names begin with "/". This causes them to sort |
| 197 | 197 | ** first and it also gives us an easy way to distinguish files |
| 198 | 198 | ** from directories in the loop that follows. |
| 199 | 199 | */ |
| 200 | 200 | db_multi_exec( |
| 201 | - "CREATE TEMP TABLE localfiles(x UNIQUE NOT NULL, u);" | |
| 201 | + "CREATE TEMP TABLE localfiles(x UNIQUE NOT NULL %s, u);", | |
| 202 | + filename_collation() | |
| 202 | 203 | ); |
| 203 | 204 | if( zCI ){ |
| 204 | 205 | Stmt ins; |
| 205 | 206 | ManifestFile *pFile; |
| 206 | 207 | ManifestFile *pPrev = 0; |
| @@ -231,16 +232,25 @@ | ||
| 231 | 232 | for(nPrev=0; (c=pPrev->zName[nD+nPrev]) && c!='/'; nPrev++){} |
| 232 | 233 | if( c=='/' ) nPrev++; |
| 233 | 234 | } |
| 234 | 235 | db_finalize(&ins); |
| 235 | 236 | }else if( zD ){ |
| 236 | - db_multi_exec( | |
| 237 | - "INSERT OR IGNORE INTO localfiles" | |
| 238 | - " SELECT pathelement(name,%d), NULL FROM filename" | |
| 239 | - " WHERE name GLOB '%q/*'", | |
| 240 | - nD, zD | |
| 241 | - ); | |
| 237 | + if( filenames_are_case_sensitive() ){ | |
| 238 | + db_multi_exec( | |
| 239 | + "INSERT OR IGNORE INTO localfiles" | |
| 240 | + " SELECT pathelement(name,%d), NULL FROM filename" | |
| 241 | + " WHERE name GLOB '%q/*'", | |
| 242 | + nD, zD | |
| 243 | + ); | |
| 244 | + }else{ | |
| 245 | + db_multi_exec( | |
| 246 | + "INSERT OR IGNORE INTO localfiles" | |
| 247 | + " SELECT pathelement(name,%d), NULL FROM filename" | |
| 248 | + " WHERE name LIKE '%q/%%'", | |
| 249 | + nD, zD | |
| 250 | + ); | |
| 251 | + } | |
| 242 | 252 | }else{ |
| 243 | 253 | db_multi_exec( |
| 244 | 254 | "INSERT OR IGNORE INTO localfiles" |
| 245 | 255 | " SELECT pathelement(name,0), NULL FROM filename" |
| 246 | 256 | ); |
| 247 | 257 |
| --- src/browse.c | |
| +++ src/browse.c | |
| @@ -196,11 +196,12 @@ | |
| 196 | ** Subdirectory names begin with "/". This causes them to sort |
| 197 | ** first and it also gives us an easy way to distinguish files |
| 198 | ** from directories in the loop that follows. |
| 199 | */ |
| 200 | db_multi_exec( |
| 201 | "CREATE TEMP TABLE localfiles(x UNIQUE NOT NULL, u);" |
| 202 | ); |
| 203 | if( zCI ){ |
| 204 | Stmt ins; |
| 205 | ManifestFile *pFile; |
| 206 | ManifestFile *pPrev = 0; |
| @@ -231,16 +232,25 @@ | |
| 231 | for(nPrev=0; (c=pPrev->zName[nD+nPrev]) && c!='/'; nPrev++){} |
| 232 | if( c=='/' ) nPrev++; |
| 233 | } |
| 234 | db_finalize(&ins); |
| 235 | }else if( zD ){ |
| 236 | db_multi_exec( |
| 237 | "INSERT OR IGNORE INTO localfiles" |
| 238 | " SELECT pathelement(name,%d), NULL FROM filename" |
| 239 | " WHERE name GLOB '%q/*'", |
| 240 | nD, zD |
| 241 | ); |
| 242 | }else{ |
| 243 | db_multi_exec( |
| 244 | "INSERT OR IGNORE INTO localfiles" |
| 245 | " SELECT pathelement(name,0), NULL FROM filename" |
| 246 | ); |
| 247 |
| --- src/browse.c | |
| +++ src/browse.c | |
| @@ -196,11 +196,12 @@ | |
| 196 | ** Subdirectory names begin with "/". This causes them to sort |
| 197 | ** first and it also gives us an easy way to distinguish files |
| 198 | ** from directories in the loop that follows. |
| 199 | */ |
| 200 | db_multi_exec( |
| 201 | "CREATE TEMP TABLE localfiles(x UNIQUE NOT NULL %s, u);", |
| 202 | filename_collation() |
| 203 | ); |
| 204 | if( zCI ){ |
| 205 | Stmt ins; |
| 206 | ManifestFile *pFile; |
| 207 | ManifestFile *pPrev = 0; |
| @@ -231,16 +232,25 @@ | |
| 232 | for(nPrev=0; (c=pPrev->zName[nD+nPrev]) && c!='/'; nPrev++){} |
| 233 | if( c=='/' ) nPrev++; |
| 234 | } |
| 235 | db_finalize(&ins); |
| 236 | }else if( zD ){ |
| 237 | if( filenames_are_case_sensitive() ){ |
| 238 | db_multi_exec( |
| 239 | "INSERT OR IGNORE INTO localfiles" |
| 240 | " SELECT pathelement(name,%d), NULL FROM filename" |
| 241 | " WHERE name GLOB '%q/*'", |
| 242 | nD, zD |
| 243 | ); |
| 244 | }else{ |
| 245 | db_multi_exec( |
| 246 | "INSERT OR IGNORE INTO localfiles" |
| 247 | " SELECT pathelement(name,%d), NULL FROM filename" |
| 248 | " WHERE name LIKE '%q/%%'", |
| 249 | nD, zD |
| 250 | ); |
| 251 | } |
| 252 | }else{ |
| 253 | db_multi_exec( |
| 254 | "INSERT OR IGNORE INTO localfiles" |
| 255 | " SELECT pathelement(name,0), NULL FROM filename" |
| 256 | ); |
| 257 |
+4
| --- src/configure.c | ||
| +++ src/configure.c | ||
| @@ -82,11 +82,15 @@ | ||
| 82 | 82 | { "project-description", CONFIGSET_PROJ }, |
| 83 | 83 | { "manifest", CONFIGSET_PROJ }, |
| 84 | 84 | { "ignore-glob", CONFIGSET_PROJ }, |
| 85 | 85 | { "crnl-glob", CONFIGSET_PROJ }, |
| 86 | 86 | { "empty-dirs", CONFIGSET_PROJ }, |
| 87 | + { "allow-symlinks", CONFIGSET_PROJ }, | |
| 87 | 88 | { "index-page", CONFIGSET_SKIN }, |
| 89 | +#ifdef FOSSIL_ENABLE_TCL | |
| 90 | + { "tcl", CONFIGSET_SKIN|CONFIGSET_TKT }, | |
| 91 | +#endif | |
| 88 | 92 | { "timeline-block-markup", CONFIGSET_SKIN }, |
| 89 | 93 | { "timeline-max-comment", CONFIGSET_SKIN }, |
| 90 | 94 | { "ticket-table", CONFIGSET_TKT }, |
| 91 | 95 | { "ticket-common", CONFIGSET_TKT }, |
| 92 | 96 | { "ticket-newpage", CONFIGSET_TKT }, |
| 93 | 97 |
| --- src/configure.c | |
| +++ src/configure.c | |
| @@ -82,11 +82,15 @@ | |
| 82 | { "project-description", CONFIGSET_PROJ }, |
| 83 | { "manifest", CONFIGSET_PROJ }, |
| 84 | { "ignore-glob", CONFIGSET_PROJ }, |
| 85 | { "crnl-glob", CONFIGSET_PROJ }, |
| 86 | { "empty-dirs", CONFIGSET_PROJ }, |
| 87 | { "index-page", CONFIGSET_SKIN }, |
| 88 | { "timeline-block-markup", CONFIGSET_SKIN }, |
| 89 | { "timeline-max-comment", CONFIGSET_SKIN }, |
| 90 | { "ticket-table", CONFIGSET_TKT }, |
| 91 | { "ticket-common", CONFIGSET_TKT }, |
| 92 | { "ticket-newpage", CONFIGSET_TKT }, |
| 93 |
| --- src/configure.c | |
| +++ src/configure.c | |
| @@ -82,11 +82,15 @@ | |
| 82 | { "project-description", CONFIGSET_PROJ }, |
| 83 | { "manifest", CONFIGSET_PROJ }, |
| 84 | { "ignore-glob", CONFIGSET_PROJ }, |
| 85 | { "crnl-glob", CONFIGSET_PROJ }, |
| 86 | { "empty-dirs", CONFIGSET_PROJ }, |
| 87 | { "allow-symlinks", CONFIGSET_PROJ }, |
| 88 | { "index-page", CONFIGSET_SKIN }, |
| 89 | #ifdef FOSSIL_ENABLE_TCL |
| 90 | { "tcl", CONFIGSET_SKIN|CONFIGSET_TKT }, |
| 91 | #endif |
| 92 | { "timeline-block-markup", CONFIGSET_SKIN }, |
| 93 | { "timeline-max-comment", CONFIGSET_SKIN }, |
| 94 | { "ticket-table", CONFIGSET_TKT }, |
| 95 | { "ticket-common", CONFIGSET_TKT }, |
| 96 | { "ticket-newpage", CONFIGSET_TKT }, |
| 97 |
+31
-5
| --- src/content.c | ||
| +++ src/content.c | ||
| @@ -828,12 +828,35 @@ | ||
| 828 | 828 | Stmt q; |
| 829 | 829 | Blob content; |
| 830 | 830 | Blob cksum; |
| 831 | 831 | int n1 = 0; |
| 832 | 832 | int n2 = 0; |
| 833 | + int nErr = 0; | |
| 833 | 834 | int total; |
| 834 | 835 | db_find_and_open_repository(OPEN_ANY_SCHEMA, 2); |
| 836 | + | |
| 837 | + /* Make sure no public artifact is a delta from a private artifact */ | |
| 838 | + db_prepare(&q, | |
| 839 | + "SELECT " | |
| 840 | + " rid, (SELECT uuid FROM blob WHERE rid=delta.rid)," | |
| 841 | + " srcid, (SELECT uuid FROM blob WHERE rid=delta.srcid)" | |
| 842 | + " FROM delta" | |
| 843 | + " WHERE srcid in private AND rid NOT IN private" | |
| 844 | + ); | |
| 845 | + while( db_step(&q)==SQLITE_ROW ){ | |
| 846 | + int rid = db_column_int(&q, 0); | |
| 847 | + const char *zId = db_column_text(&q, 1); | |
| 848 | + int srcid = db_column_int(&q, 2); | |
| 849 | + const char *zSrc = db_column_text(&q, 3); | |
| 850 | + fossil_print( | |
| 851 | + "public artifact %S (%d) is a delta from private artifact %S (%d)\n", | |
| 852 | + zId, rid, zSrc, srcid | |
| 853 | + ); | |
| 854 | + nErr++; | |
| 855 | + } | |
| 856 | + db_finalize(&q); | |
| 857 | + | |
| 835 | 858 | db_prepare(&q, "SELECT rid, uuid, size FROM blob ORDER BY rid"); |
| 836 | 859 | total = db_int(0, "SELECT max(rid) FROM blob"); |
| 837 | 860 | while( db_step(&q)==SQLITE_ROW ){ |
| 838 | 861 | int rid = db_column_int(&q, 0); |
| 839 | 862 | const char *zUuid = db_column_text(&q, 1); |
| @@ -845,20 +868,23 @@ | ||
| 845 | 868 | fossil_print("skip phantom %d %s\n", rid, zUuid); |
| 846 | 869 | continue; /* Ignore phantoms */ |
| 847 | 870 | } |
| 848 | 871 | content_get(rid, &content); |
| 849 | 872 | if( blob_size(&content)!=size ){ |
| 850 | - fossil_warning("size mismatch on blob rid=%d: %d vs %d", | |
| 851 | - rid, blob_size(&content), size); | |
| 873 | + fossil_print("size mismatch on artifact %d: wanted %d but got %d\n", | |
| 874 | + rid, size, blob_size(&content)); | |
| 875 | + nErr++; | |
| 852 | 876 | } |
| 853 | 877 | sha1sum_blob(&content, &cksum); |
| 854 | 878 | if( fossil_strcmp(blob_str(&cksum), zUuid)!=0 ){ |
| 855 | - fossil_fatal("checksum mismatch on blob rid=%d: %s vs %s", | |
| 856 | - rid, blob_str(&cksum), zUuid); | |
| 879 | + fossil_print("checksum mismatch on artifact %d: wanted %s but got %s\n", | |
| 880 | + rid, zUuid, blob_str(&cksum)); | |
| 881 | + nErr++; | |
| 857 | 882 | } |
| 858 | 883 | blob_reset(&cksum); |
| 859 | 884 | blob_reset(&content); |
| 860 | 885 | n2++; |
| 861 | 886 | } |
| 862 | 887 | db_finalize(&q); |
| 863 | - fossil_print("%d non-phantom blobs (out of %d total) verified\n", n2, n1); | |
| 888 | + fossil_print("%d non-phantom blobs (out of %d total) checked: %d errors\n", | |
| 889 | + n2, n1, nErr); | |
| 864 | 890 | } |
| 865 | 891 |
| --- src/content.c | |
| +++ src/content.c | |
| @@ -828,12 +828,35 @@ | |
| 828 | Stmt q; |
| 829 | Blob content; |
| 830 | Blob cksum; |
| 831 | int n1 = 0; |
| 832 | int n2 = 0; |
| 833 | int total; |
| 834 | db_find_and_open_repository(OPEN_ANY_SCHEMA, 2); |
| 835 | db_prepare(&q, "SELECT rid, uuid, size FROM blob ORDER BY rid"); |
| 836 | total = db_int(0, "SELECT max(rid) FROM blob"); |
| 837 | while( db_step(&q)==SQLITE_ROW ){ |
| 838 | int rid = db_column_int(&q, 0); |
| 839 | const char *zUuid = db_column_text(&q, 1); |
| @@ -845,20 +868,23 @@ | |
| 845 | fossil_print("skip phantom %d %s\n", rid, zUuid); |
| 846 | continue; /* Ignore phantoms */ |
| 847 | } |
| 848 | content_get(rid, &content); |
| 849 | if( blob_size(&content)!=size ){ |
| 850 | fossil_warning("size mismatch on blob rid=%d: %d vs %d", |
| 851 | rid, blob_size(&content), size); |
| 852 | } |
| 853 | sha1sum_blob(&content, &cksum); |
| 854 | if( fossil_strcmp(blob_str(&cksum), zUuid)!=0 ){ |
| 855 | fossil_fatal("checksum mismatch on blob rid=%d: %s vs %s", |
| 856 | rid, blob_str(&cksum), zUuid); |
| 857 | } |
| 858 | blob_reset(&cksum); |
| 859 | blob_reset(&content); |
| 860 | n2++; |
| 861 | } |
| 862 | db_finalize(&q); |
| 863 | fossil_print("%d non-phantom blobs (out of %d total) verified\n", n2, n1); |
| 864 | } |
| 865 |
| --- src/content.c | |
| +++ src/content.c | |
| @@ -828,12 +828,35 @@ | |
| 828 | Stmt q; |
| 829 | Blob content; |
| 830 | Blob cksum; |
| 831 | int n1 = 0; |
| 832 | int n2 = 0; |
| 833 | int nErr = 0; |
| 834 | int total; |
| 835 | db_find_and_open_repository(OPEN_ANY_SCHEMA, 2); |
| 836 | |
| 837 | /* Make sure no public artifact is a delta from a private artifact */ |
| 838 | db_prepare(&q, |
| 839 | "SELECT " |
| 840 | " rid, (SELECT uuid FROM blob WHERE rid=delta.rid)," |
| 841 | " srcid, (SELECT uuid FROM blob WHERE rid=delta.srcid)" |
| 842 | " FROM delta" |
| 843 | " WHERE srcid in private AND rid NOT IN private" |
| 844 | ); |
| 845 | while( db_step(&q)==SQLITE_ROW ){ |
| 846 | int rid = db_column_int(&q, 0); |
| 847 | const char *zId = db_column_text(&q, 1); |
| 848 | int srcid = db_column_int(&q, 2); |
| 849 | const char *zSrc = db_column_text(&q, 3); |
| 850 | fossil_print( |
| 851 | "public artifact %S (%d) is a delta from private artifact %S (%d)\n", |
| 852 | zId, rid, zSrc, srcid |
| 853 | ); |
| 854 | nErr++; |
| 855 | } |
| 856 | db_finalize(&q); |
| 857 | |
| 858 | db_prepare(&q, "SELECT rid, uuid, size FROM blob ORDER BY rid"); |
| 859 | total = db_int(0, "SELECT max(rid) FROM blob"); |
| 860 | while( db_step(&q)==SQLITE_ROW ){ |
| 861 | int rid = db_column_int(&q, 0); |
| 862 | const char *zUuid = db_column_text(&q, 1); |
| @@ -845,20 +868,23 @@ | |
| 868 | fossil_print("skip phantom %d %s\n", rid, zUuid); |
| 869 | continue; /* Ignore phantoms */ |
| 870 | } |
| 871 | content_get(rid, &content); |
| 872 | if( blob_size(&content)!=size ){ |
| 873 | fossil_print("size mismatch on artifact %d: wanted %d but got %d\n", |
| 874 | rid, size, blob_size(&content)); |
| 875 | nErr++; |
| 876 | } |
| 877 | sha1sum_blob(&content, &cksum); |
| 878 | if( fossil_strcmp(blob_str(&cksum), zUuid)!=0 ){ |
| 879 | fossil_print("checksum mismatch on artifact %d: wanted %s but got %s\n", |
| 880 | rid, zUuid, blob_str(&cksum)); |
| 881 | nErr++; |
| 882 | } |
| 883 | blob_reset(&cksum); |
| 884 | blob_reset(&content); |
| 885 | n2++; |
| 886 | } |
| 887 | db_finalize(&q); |
| 888 | fossil_print("%d non-phantom blobs (out of %d total) checked: %d errors\n", |
| 889 | n2, n1, nErr); |
| 890 | } |
| 891 |
+72
| --- src/cson_amalgamation.c | ||
| +++ src/cson_amalgamation.c | ||
| @@ -1396,10 +1396,11 @@ | ||
| 1396 | 1396 | /* end file parser/JSON_parser.c */ |
| 1397 | 1397 | /* begin file ./cson.c */ |
| 1398 | 1398 | #include <assert.h> |
| 1399 | 1399 | #include <stdlib.h> /* malloc()/free() */ |
| 1400 | 1400 | #include <string.h> |
| 1401 | +#include <errno.h> | |
| 1401 | 1402 | |
| 1402 | 1403 | #ifdef _MSC_VER |
| 1403 | 1404 | # if _MSC_VER >= 1400 /* Visual Studio 2005 and up */ |
| 1404 | 1405 | # pragma warning( push ) |
| 1405 | 1406 | # pragma warning(disable:4996) /* unsecure sscanf (but snscanf() isn't in c89) */ |
| @@ -4950,10 +4951,81 @@ | ||
| 4950 | 4951 | } |
| 4951 | 4952 | else continue; |
| 4952 | 4953 | } |
| 4953 | 4954 | return 0; |
| 4954 | 4955 | } |
| 4956 | + | |
| 4957 | +static cson_value * cson_guess_arg_type(char const *arg){ | |
| 4958 | + char * end = NULL; | |
| 4959 | + if(('0'<=*arg) && ('9'>=*arg)){ | |
| 4960 | + goto do_string; | |
| 4961 | + } | |
| 4962 | + { | |
| 4963 | + long const val = strtol(arg, &end, 10); | |
| 4964 | + if(!*end){ | |
| 4965 | + return cson_value_new_integer( (cson_int_t)val); | |
| 4966 | + } | |
| 4967 | + } | |
| 4968 | + { | |
| 4969 | + double const val = strtod(arg, &end); | |
| 4970 | + if(!*end){ | |
| 4971 | + return cson_value_new_double(val); | |
| 4972 | + } | |
| 4973 | + } | |
| 4974 | + | |
| 4975 | + | |
| 4976 | + do_string: | |
| 4977 | + return cson_value_new_string(arg, strlen(arg)); | |
| 4978 | +} | |
| 4979 | + | |
| 4980 | + | |
| 4981 | +int cson_parse_argv_flags( int argc, char const * const * argv, | |
| 4982 | + cson_object ** tgt, unsigned int * count ){ | |
| 4983 | + cson_object * o = NULL; | |
| 4984 | + int rc = 0; | |
| 4985 | + int i = 0; | |
| 4986 | + if(argc<1 || !argc || !tgt) return cson_rc.ArgError; | |
| 4987 | + o = *tgt ? *tgt : cson_new_object(); | |
| 4988 | + if(count) *count = 0; | |
| 4989 | + for( i = 0; i < argc; ++i ){ | |
| 4990 | + char const * arg = argv[i]; | |
| 4991 | + char const * key = arg; | |
| 4992 | + char const * pos; | |
| 4993 | + cson_string * k = NULL; | |
| 4994 | + cson_value * v = NULL; | |
| 4995 | + if('-' != *arg) continue; | |
| 4996 | + while('-'==*key) ++key; | |
| 4997 | + if(!*key) continue; | |
| 4998 | + pos = key; | |
| 4999 | + while( *pos && ('=' != *pos)) ++pos; | |
| 5000 | + k = cson_new_string(key, pos-key); | |
| 5001 | + if(!k){ | |
| 5002 | + rc = cson_rc.AllocError; | |
| 5003 | + break; | |
| 5004 | + } | |
| 5005 | + if(!*pos){ /** --key */ | |
| 5006 | + v = cson_value_true(); | |
| 5007 | + }else{ /** --key=...*/ | |
| 5008 | + assert('=' == *pos); | |
| 5009 | + ++pos /*skip '='*/; | |
| 5010 | + v = *pos | |
| 5011 | + ? cson_guess_arg_type(pos) | |
| 5012 | + : cson_value_null(); | |
| 5013 | + } | |
| 5014 | + if(0 != (rc=cson_object_set_s(o, k, v))){ | |
| 5015 | + cson_free_string(k); | |
| 5016 | + cson_value_free(v); | |
| 5017 | + break; | |
| 5018 | + } | |
| 5019 | + else if(count) ++*count; | |
| 5020 | + } | |
| 5021 | + if(o != *tgt){ | |
| 5022 | + if(rc) cson_free_object(o); | |
| 5023 | + else *tgt = o; | |
| 5024 | + } | |
| 5025 | + return rc; | |
| 5026 | +} | |
| 4955 | 5027 | |
| 4956 | 5028 | #if defined(__cplusplus) |
| 4957 | 5029 | } /*extern "C"*/ |
| 4958 | 5030 | #endif |
| 4959 | 5031 | |
| 4960 | 5032 |
| --- src/cson_amalgamation.c | |
| +++ src/cson_amalgamation.c | |
| @@ -1396,10 +1396,11 @@ | |
| 1396 | /* end file parser/JSON_parser.c */ |
| 1397 | /* begin file ./cson.c */ |
| 1398 | #include <assert.h> |
| 1399 | #include <stdlib.h> /* malloc()/free() */ |
| 1400 | #include <string.h> |
| 1401 | |
| 1402 | #ifdef _MSC_VER |
| 1403 | # if _MSC_VER >= 1400 /* Visual Studio 2005 and up */ |
| 1404 | # pragma warning( push ) |
| 1405 | # pragma warning(disable:4996) /* unsecure sscanf (but snscanf() isn't in c89) */ |
| @@ -4950,10 +4951,81 @@ | |
| 4950 | } |
| 4951 | else continue; |
| 4952 | } |
| 4953 | return 0; |
| 4954 | } |
| 4955 | |
| 4956 | #if defined(__cplusplus) |
| 4957 | } /*extern "C"*/ |
| 4958 | #endif |
| 4959 | |
| 4960 |
| --- src/cson_amalgamation.c | |
| +++ src/cson_amalgamation.c | |
| @@ -1396,10 +1396,11 @@ | |
| 1396 | /* end file parser/JSON_parser.c */ |
| 1397 | /* begin file ./cson.c */ |
| 1398 | #include <assert.h> |
| 1399 | #include <stdlib.h> /* malloc()/free() */ |
| 1400 | #include <string.h> |
| 1401 | #include <errno.h> |
| 1402 | |
| 1403 | #ifdef _MSC_VER |
| 1404 | # if _MSC_VER >= 1400 /* Visual Studio 2005 and up */ |
| 1405 | # pragma warning( push ) |
| 1406 | # pragma warning(disable:4996) /* unsecure sscanf (but snscanf() isn't in c89) */ |
| @@ -4950,10 +4951,81 @@ | |
| 4951 | } |
| 4952 | else continue; |
| 4953 | } |
| 4954 | return 0; |
| 4955 | } |
| 4956 | |
| 4957 | static cson_value * cson_guess_arg_type(char const *arg){ |
| 4958 | char * end = NULL; |
| 4959 | if(('0'<=*arg) && ('9'>=*arg)){ |
| 4960 | goto do_string; |
| 4961 | } |
| 4962 | { |
| 4963 | long const val = strtol(arg, &end, 10); |
| 4964 | if(!*end){ |
| 4965 | return cson_value_new_integer( (cson_int_t)val); |
| 4966 | } |
| 4967 | } |
| 4968 | { |
| 4969 | double const val = strtod(arg, &end); |
| 4970 | if(!*end){ |
| 4971 | return cson_value_new_double(val); |
| 4972 | } |
| 4973 | } |
| 4974 | |
| 4975 | |
| 4976 | do_string: |
| 4977 | return cson_value_new_string(arg, strlen(arg)); |
| 4978 | } |
| 4979 | |
| 4980 | |
| 4981 | int cson_parse_argv_flags( int argc, char const * const * argv, |
| 4982 | cson_object ** tgt, unsigned int * count ){ |
| 4983 | cson_object * o = NULL; |
| 4984 | int rc = 0; |
| 4985 | int i = 0; |
| 4986 | if(argc<1 || !argc || !tgt) return cson_rc.ArgError; |
| 4987 | o = *tgt ? *tgt : cson_new_object(); |
| 4988 | if(count) *count = 0; |
| 4989 | for( i = 0; i < argc; ++i ){ |
| 4990 | char const * arg = argv[i]; |
| 4991 | char const * key = arg; |
| 4992 | char const * pos; |
| 4993 | cson_string * k = NULL; |
| 4994 | cson_value * v = NULL; |
| 4995 | if('-' != *arg) continue; |
| 4996 | while('-'==*key) ++key; |
| 4997 | if(!*key) continue; |
| 4998 | pos = key; |
| 4999 | while( *pos && ('=' != *pos)) ++pos; |
| 5000 | k = cson_new_string(key, pos-key); |
| 5001 | if(!k){ |
| 5002 | rc = cson_rc.AllocError; |
| 5003 | break; |
| 5004 | } |
| 5005 | if(!*pos){ /** --key */ |
| 5006 | v = cson_value_true(); |
| 5007 | }else{ /** --key=...*/ |
| 5008 | assert('=' == *pos); |
| 5009 | ++pos /*skip '='*/; |
| 5010 | v = *pos |
| 5011 | ? cson_guess_arg_type(pos) |
| 5012 | : cson_value_null(); |
| 5013 | } |
| 5014 | if(0 != (rc=cson_object_set_s(o, k, v))){ |
| 5015 | cson_free_string(k); |
| 5016 | cson_value_free(v); |
| 5017 | break; |
| 5018 | } |
| 5019 | else if(count) ++*count; |
| 5020 | } |
| 5021 | if(o != *tgt){ |
| 5022 | if(rc) cson_free_object(o); |
| 5023 | else *tgt = o; |
| 5024 | } |
| 5025 | return rc; |
| 5026 | } |
| 5027 | |
| 5028 | #if defined(__cplusplus) |
| 5029 | } /*extern "C"*/ |
| 5030 | #endif |
| 5031 | |
| 5032 |
+54
-1
| --- src/cson_amalgamation.h | ||
| +++ src/cson_amalgamation.h | ||
| @@ -2108,10 +2108,64 @@ | ||
| 2108 | 2108 | necessarily increase when a new item is inserted into it. An interesting |
| 2109 | 2109 | side-effect of this is that when cson_clone()ing an array or object, the |
| 2110 | 2110 | size of the clone can actually be less than the original. |
| 2111 | 2111 | */ |
| 2112 | 2112 | unsigned int cson_value_msize(cson_value const * v); |
| 2113 | + | |
| 2114 | +/** | |
| 2115 | + Parses command-line-style arguments into a JSON object. | |
| 2116 | + | |
| 2117 | + It expects arguments to be in any of these forms, and any number | |
| 2118 | + of leading dashes are treated identically: | |
| 2119 | + | |
| 2120 | + --key : Treats key as a boolean with a true value. | |
| 2121 | + | |
| 2122 | + --key=VAL : Treats VAL as either a double, integer, or string. | |
| 2123 | + | |
| 2124 | + --key= : Treats key as a JSON null (not literal NULL) value. | |
| 2125 | + | |
| 2126 | + Arguments not starting with a dash are skipped. | |
| 2127 | + | |
| 2128 | + Each key/value pair is inserted into an object. If a given key | |
| 2129 | + appears more than once then only the final entry is actually | |
| 2130 | + stored. | |
| 2131 | + | |
| 2132 | + argc and argv are expected to be values from main() (or similar, | |
| 2133 | + possibly adjusted to remove argv[0]). | |
| 2134 | + | |
| 2135 | + tgt must be either a pointer to NULL or a pointer to a | |
| 2136 | + client-provided Object. If (NULL==*tgt) then this function | |
| 2137 | + allocates a new object and on success it stores the new object in | |
| 2138 | + *tgt (it is owned by the caller). If (NULL!=*tgt) then it is | |
| 2139 | + assumed to be a properly allocated object. DO NOT pass a pointer to | |
| 2140 | + an unitialized pointer, as that will fool this function into | |
| 2141 | + thinking it is a valid object and Undefined Behaviour will ensue. | |
| 2142 | + | |
| 2143 | + If count is not NULL then the number of arugments parsed by this | |
| 2144 | + function are assigned to it. On error, count will be the number of | |
| 2145 | + options successfully parsed before the error was encountered. | |
| 2146 | + | |
| 2147 | + On success: | |
| 2148 | + | |
| 2149 | + - 0 is returned. | |
| 2150 | + | |
| 2151 | + - If (*tgt==NULL) then *tgt is assigned to a newly-allocated | |
| 2152 | + object, owned by the caller. Note that even if no arguments are | |
| 2153 | + parsed, the object is still created. | |
| 2154 | + | |
| 2155 | + On error: | |
| 2156 | + | |
| 2157 | + - non-0 is returned | |
| 2158 | + | |
| 2159 | + - If (*tgt==NULL) then it is not modified. | |
| 2160 | + | |
| 2161 | + - If (*tgt!=NULL) (i.e., the caller provides his own object) then | |
| 2162 | + it might contain partial results. | |
| 2163 | +*/ | |
| 2164 | +int cson_parse_argv_flags( int argc, char const * const * argv, | |
| 2165 | + cson_object ** tgt, unsigned int * count ); | |
| 2166 | + | |
| 2113 | 2167 | |
| 2114 | 2168 | /* LICENSE |
| 2115 | 2169 | |
| 2116 | 2170 | This software's source code, including accompanying documentation and |
| 2117 | 2171 | demonstration applications, are licensed under the following |
| @@ -2382,7 +2436,6 @@ | ||
| 2382 | 2436 | #endif |
| 2383 | 2437 | |
| 2384 | 2438 | #endif /* CSON_ENABLE_SQLITE3 */ |
| 2385 | 2439 | #endif /* WANDERINGHORSE_NET_CSON_SQLITE3_H_INCLUDED */ |
| 2386 | 2440 | /* end file include/wh/cson/cson_sqlite3.h */ |
| 2387 | - | |
| 2388 | 2441 | #endif /* FOSSIL_ENABLE_JSON */ |
| 2389 | 2442 |
| --- src/cson_amalgamation.h | |
| +++ src/cson_amalgamation.h | |
| @@ -2108,10 +2108,64 @@ | |
| 2108 | necessarily increase when a new item is inserted into it. An interesting |
| 2109 | side-effect of this is that when cson_clone()ing an array or object, the |
| 2110 | size of the clone can actually be less than the original. |
| 2111 | */ |
| 2112 | unsigned int cson_value_msize(cson_value const * v); |
| 2113 | |
| 2114 | /* LICENSE |
| 2115 | |
| 2116 | This software's source code, including accompanying documentation and |
| 2117 | demonstration applications, are licensed under the following |
| @@ -2382,7 +2436,6 @@ | |
| 2382 | #endif |
| 2383 | |
| 2384 | #endif /* CSON_ENABLE_SQLITE3 */ |
| 2385 | #endif /* WANDERINGHORSE_NET_CSON_SQLITE3_H_INCLUDED */ |
| 2386 | /* end file include/wh/cson/cson_sqlite3.h */ |
| 2387 | |
| 2388 | #endif /* FOSSIL_ENABLE_JSON */ |
| 2389 |
| --- src/cson_amalgamation.h | |
| +++ src/cson_amalgamation.h | |
| @@ -2108,10 +2108,64 @@ | |
| 2108 | necessarily increase when a new item is inserted into it. An interesting |
| 2109 | side-effect of this is that when cson_clone()ing an array or object, the |
| 2110 | size of the clone can actually be less than the original. |
| 2111 | */ |
| 2112 | unsigned int cson_value_msize(cson_value const * v); |
| 2113 | |
| 2114 | /** |
| 2115 | Parses command-line-style arguments into a JSON object. |
| 2116 | |
| 2117 | It expects arguments to be in any of these forms, and any number |
| 2118 | of leading dashes are treated identically: |
| 2119 | |
| 2120 | --key : Treats key as a boolean with a true value. |
| 2121 | |
| 2122 | --key=VAL : Treats VAL as either a double, integer, or string. |
| 2123 | |
| 2124 | --key= : Treats key as a JSON null (not literal NULL) value. |
| 2125 | |
| 2126 | Arguments not starting with a dash are skipped. |
| 2127 | |
| 2128 | Each key/value pair is inserted into an object. If a given key |
| 2129 | appears more than once then only the final entry is actually |
| 2130 | stored. |
| 2131 | |
| 2132 | argc and argv are expected to be values from main() (or similar, |
| 2133 | possibly adjusted to remove argv[0]). |
| 2134 | |
| 2135 | tgt must be either a pointer to NULL or a pointer to a |
| 2136 | client-provided Object. If (NULL==*tgt) then this function |
| 2137 | allocates a new object and on success it stores the new object in |
| 2138 | *tgt (it is owned by the caller). If (NULL!=*tgt) then it is |
| 2139 | assumed to be a properly allocated object. DO NOT pass a pointer to |
| 2140 | an unitialized pointer, as that will fool this function into |
| 2141 | thinking it is a valid object and Undefined Behaviour will ensue. |
| 2142 | |
| 2143 | If count is not NULL then the number of arugments parsed by this |
| 2144 | function are assigned to it. On error, count will be the number of |
| 2145 | options successfully parsed before the error was encountered. |
| 2146 | |
| 2147 | On success: |
| 2148 | |
| 2149 | - 0 is returned. |
| 2150 | |
| 2151 | - If (*tgt==NULL) then *tgt is assigned to a newly-allocated |
| 2152 | object, owned by the caller. Note that even if no arguments are |
| 2153 | parsed, the object is still created. |
| 2154 | |
| 2155 | On error: |
| 2156 | |
| 2157 | - non-0 is returned |
| 2158 | |
| 2159 | - If (*tgt==NULL) then it is not modified. |
| 2160 | |
| 2161 | - If (*tgt!=NULL) (i.e., the caller provides his own object) then |
| 2162 | it might contain partial results. |
| 2163 | */ |
| 2164 | int cson_parse_argv_flags( int argc, char const * const * argv, |
| 2165 | cson_object ** tgt, unsigned int * count ); |
| 2166 | |
| 2167 | |
| 2168 | /* LICENSE |
| 2169 | |
| 2170 | This software's source code, including accompanying documentation and |
| 2171 | demonstration applications, are licensed under the following |
| @@ -2382,7 +2436,6 @@ | |
| 2436 | #endif |
| 2437 | |
| 2438 | #endif /* CSON_ENABLE_SQLITE3 */ |
| 2439 | #endif /* WANDERINGHORSE_NET_CSON_SQLITE3_H_INCLUDED */ |
| 2440 | /* end file include/wh/cson/cson_sqlite3.h */ |
| 2441 | #endif /* FOSSIL_ENABLE_JSON */ |
| 2442 |
+23
-17
| --- src/finfo.c | ||
| +++ src/finfo.c | ||
| @@ -39,22 +39,25 @@ | ||
| 39 | 39 | ** In the -p form, there's an optional flag "-r|--revision REVISION". |
| 40 | 40 | ** The specified version (or the latest checked out version) is printed |
| 41 | 41 | ** to stdout. |
| 42 | 42 | ** |
| 43 | 43 | ** Options: |
| 44 | -** --brief|-b display a brief (one line / revision) summary | |
| 45 | -** --limit N display the first N changes | |
| 46 | -** --log|-l select log mode (the default) | |
| 47 | -** --offset P skip P changes | |
| 48 | -** -p select print mode | |
| 49 | -** --revision|-r R print the given revision (or ckout, if none is given) | |
| 50 | -** to stdout (only in print mode) | |
| 51 | -** -s select status mode (print a status indicator for FILE) | |
| 44 | +** --brief|-b display a brief (one line / revision) summary | |
| 45 | +** --limit N display the first N changes | |
| 46 | +** --log|-l select log mode (the default) | |
| 47 | +** --offset P skip P changes | |
| 48 | +** -p select print mode | |
| 49 | +** --revision|-r R print the given revision (or ckout, if none is given) | |
| 50 | +** to stdout (only in print mode) | |
| 51 | +** -s select status mode (print a status indicator for FILE) | |
| 52 | +** --case-sensitive B Enable or disable case-sensitive filenames. B is a | |
| 53 | +** boolean: "yes", "no", "true", "false", etc. | |
| 52 | 54 | ** |
| 53 | 55 | ** See also: descendants, info, leaves |
| 54 | 56 | */ |
| 55 | 57 | void finfo_cmd(void){ |
| 58 | + capture_case_sensitive_option(); | |
| 56 | 59 | db_must_be_within_tree(); |
| 57 | 60 | if (find_option("status","s",0)) { |
| 58 | 61 | Stmt q; |
| 59 | 62 | Blob line; |
| 60 | 63 | Blob fname; |
| @@ -67,11 +70,12 @@ | ||
| 67 | 70 | } |
| 68 | 71 | vfile_check_signature(vid, 1, 0); |
| 69 | 72 | file_tree_name(g.argv[2], &fname, 1); |
| 70 | 73 | db_prepare(&q, |
| 71 | 74 | "SELECT pathname, deleted, rid, chnged, coalesce(origname!=pathname,0)" |
| 72 | - " FROM vfile WHERE vfile.pathname=%B", &fname); | |
| 75 | + " FROM vfile WHERE vfile.pathname=%B %s", | |
| 76 | + &fname, filename_collation()); | |
| 73 | 77 | blob_zero(&line); |
| 74 | 78 | if ( db_step(&q)==SQLITE_ROW ) { |
| 75 | 79 | Blob uuid; |
| 76 | 80 | int isDeleted = db_column_int(&q, 1); |
| 77 | 81 | int isNew = db_column_int(&q,2) == 0; |
| @@ -80,12 +84,12 @@ | ||
| 80 | 84 | |
| 81 | 85 | blob_zero(&uuid); |
| 82 | 86 | db_blob(&uuid, |
| 83 | 87 | "SELECT uuid FROM blob, mlink, vfile WHERE " |
| 84 | 88 | "blob.rid = mlink.mid AND mlink.fid = vfile.rid AND " |
| 85 | - "vfile.pathname=%B", | |
| 86 | - &fname | |
| 89 | + "vfile.pathname=%B %s", | |
| 90 | + &fname, filename_collation() | |
| 87 | 91 | ); |
| 88 | 92 | if( isNew ){ |
| 89 | 93 | blob_appendf(&line, "new"); |
| 90 | 94 | }else if( isDeleted ){ |
| 91 | 95 | blob_appendf(&line, "deleted"); |
| @@ -113,11 +117,12 @@ | ||
| 113 | 117 | |
| 114 | 118 | file_tree_name(g.argv[2], &fname, 1); |
| 115 | 119 | if( zRevision ){ |
| 116 | 120 | historical_version_of_file(zRevision, blob_str(&fname), &record, 0, 0, 0); |
| 117 | 121 | }else{ |
| 118 | - int rid = db_int(0, "SELECT rid FROM vfile WHERE pathname=%B", &fname); | |
| 122 | + int rid = db_int(0, "SELECT rid FROM vfile WHERE pathname=%B %s", | |
| 123 | + &fname, filename_collation()); | |
| 119 | 124 | if( rid==0 ){ |
| 120 | 125 | fossil_fatal("no history for file: %b", &fname); |
| 121 | 126 | } |
| 122 | 127 | content_get(rid, &record); |
| 123 | 128 | } |
| @@ -144,27 +149,28 @@ | ||
| 144 | 149 | iBrief = (find_option("brief","b",0) == 0); |
| 145 | 150 | if( g.argc!=3 ){ |
| 146 | 151 | usage("?-l|--log? ?-b|--brief? FILENAME"); |
| 147 | 152 | } |
| 148 | 153 | file_tree_name(g.argv[2], &fname, 1); |
| 149 | - rid = db_int(0, "SELECT rid FROM vfile WHERE pathname=%B", &fname); | |
| 154 | + rid = db_int(0, "SELECT rid FROM vfile WHERE pathname=%B %s", | |
| 155 | + &fname, filename_collation()); | |
| 150 | 156 | if( rid==0 ){ |
| 151 | 157 | fossil_fatal("no history for file: %b", &fname); |
| 152 | 158 | } |
| 153 | 159 | zFilename = blob_str(&fname); |
| 154 | 160 | db_prepare(&q, |
| 155 | 161 | "SELECT b.uuid, ci.uuid, date(event.mtime,'localtime')," |
| 156 | 162 | " coalesce(event.ecomment, event.comment)," |
| 157 | 163 | " coalesce(event.euser, event.user)" |
| 158 | 164 | " FROM mlink, blob b, event, blob ci, filename" |
| 159 | - " WHERE filename.name=%Q" | |
| 165 | + " WHERE filename.name=%Q %s" | |
| 160 | 166 | " AND mlink.fnid=filename.fnid" |
| 161 | 167 | " AND b.rid=mlink.fid" |
| 162 | 168 | " AND event.objid=mlink.mid" |
| 163 | 169 | " AND event.objid=ci.rid" |
| 164 | 170 | " ORDER BY event.mtime DESC LIMIT %d OFFSET %d", |
| 165 | - zFilename, iLimit, iOffset | |
| 171 | + zFilename, filename_collation(), iLimit, iOffset | |
| 166 | 172 | ); |
| 167 | 173 | blob_zero(&line); |
| 168 | 174 | if( iBrief ){ |
| 169 | 175 | fossil_print("History of %s\n", blob_str(&fname)); |
| 170 | 176 | } |
| @@ -243,14 +249,14 @@ | ||
| 243 | 249 | " (SELECT uuid FROM blob WHERE rid=mlink.mid)," /* Check-in uuid */ |
| 244 | 250 | " event.bgcolor," /* Background color */ |
| 245 | 251 | " (SELECT value FROM tagxref WHERE tagid=%d AND tagtype>0" |
| 246 | 252 | " AND tagxref.rid=mlink.mid)" /* Tags */ |
| 247 | 253 | " FROM mlink, event" |
| 248 | - " WHERE mlink.fnid=(SELECT fnid FROM filename WHERE name=%Q)" | |
| 254 | + " WHERE mlink.fnid IN (SELECT fnid FROM filename WHERE name=%Q %s)" | |
| 249 | 255 | " AND event.objid=mlink.mid", |
| 250 | 256 | TAG_BRANCH, |
| 251 | - zFilename | |
| 257 | + zFilename, filename_collation() | |
| 252 | 258 | ); |
| 253 | 259 | if( (zA = P("a"))!=0 ){ |
| 254 | 260 | blob_appendf(&sql, " AND event.mtime>=julianday('%q')", zA); |
| 255 | 261 | } |
| 256 | 262 | if( (zB = P("b"))!=0 ){ |
| 257 | 263 |
| --- src/finfo.c | |
| +++ src/finfo.c | |
| @@ -39,22 +39,25 @@ | |
| 39 | ** In the -p form, there's an optional flag "-r|--revision REVISION". |
| 40 | ** The specified version (or the latest checked out version) is printed |
| 41 | ** to stdout. |
| 42 | ** |
| 43 | ** Options: |
| 44 | ** --brief|-b display a brief (one line / revision) summary |
| 45 | ** --limit N display the first N changes |
| 46 | ** --log|-l select log mode (the default) |
| 47 | ** --offset P skip P changes |
| 48 | ** -p select print mode |
| 49 | ** --revision|-r R print the given revision (or ckout, if none is given) |
| 50 | ** to stdout (only in print mode) |
| 51 | ** -s select status mode (print a status indicator for FILE) |
| 52 | ** |
| 53 | ** See also: descendants, info, leaves |
| 54 | */ |
| 55 | void finfo_cmd(void){ |
| 56 | db_must_be_within_tree(); |
| 57 | if (find_option("status","s",0)) { |
| 58 | Stmt q; |
| 59 | Blob line; |
| 60 | Blob fname; |
| @@ -67,11 +70,12 @@ | |
| 67 | } |
| 68 | vfile_check_signature(vid, 1, 0); |
| 69 | file_tree_name(g.argv[2], &fname, 1); |
| 70 | db_prepare(&q, |
| 71 | "SELECT pathname, deleted, rid, chnged, coalesce(origname!=pathname,0)" |
| 72 | " FROM vfile WHERE vfile.pathname=%B", &fname); |
| 73 | blob_zero(&line); |
| 74 | if ( db_step(&q)==SQLITE_ROW ) { |
| 75 | Blob uuid; |
| 76 | int isDeleted = db_column_int(&q, 1); |
| 77 | int isNew = db_column_int(&q,2) == 0; |
| @@ -80,12 +84,12 @@ | |
| 80 | |
| 81 | blob_zero(&uuid); |
| 82 | db_blob(&uuid, |
| 83 | "SELECT uuid FROM blob, mlink, vfile WHERE " |
| 84 | "blob.rid = mlink.mid AND mlink.fid = vfile.rid AND " |
| 85 | "vfile.pathname=%B", |
| 86 | &fname |
| 87 | ); |
| 88 | if( isNew ){ |
| 89 | blob_appendf(&line, "new"); |
| 90 | }else if( isDeleted ){ |
| 91 | blob_appendf(&line, "deleted"); |
| @@ -113,11 +117,12 @@ | |
| 113 | |
| 114 | file_tree_name(g.argv[2], &fname, 1); |
| 115 | if( zRevision ){ |
| 116 | historical_version_of_file(zRevision, blob_str(&fname), &record, 0, 0, 0); |
| 117 | }else{ |
| 118 | int rid = db_int(0, "SELECT rid FROM vfile WHERE pathname=%B", &fname); |
| 119 | if( rid==0 ){ |
| 120 | fossil_fatal("no history for file: %b", &fname); |
| 121 | } |
| 122 | content_get(rid, &record); |
| 123 | } |
| @@ -144,27 +149,28 @@ | |
| 144 | iBrief = (find_option("brief","b",0) == 0); |
| 145 | if( g.argc!=3 ){ |
| 146 | usage("?-l|--log? ?-b|--brief? FILENAME"); |
| 147 | } |
| 148 | file_tree_name(g.argv[2], &fname, 1); |
| 149 | rid = db_int(0, "SELECT rid FROM vfile WHERE pathname=%B", &fname); |
| 150 | if( rid==0 ){ |
| 151 | fossil_fatal("no history for file: %b", &fname); |
| 152 | } |
| 153 | zFilename = blob_str(&fname); |
| 154 | db_prepare(&q, |
| 155 | "SELECT b.uuid, ci.uuid, date(event.mtime,'localtime')," |
| 156 | " coalesce(event.ecomment, event.comment)," |
| 157 | " coalesce(event.euser, event.user)" |
| 158 | " FROM mlink, blob b, event, blob ci, filename" |
| 159 | " WHERE filename.name=%Q" |
| 160 | " AND mlink.fnid=filename.fnid" |
| 161 | " AND b.rid=mlink.fid" |
| 162 | " AND event.objid=mlink.mid" |
| 163 | " AND event.objid=ci.rid" |
| 164 | " ORDER BY event.mtime DESC LIMIT %d OFFSET %d", |
| 165 | zFilename, iLimit, iOffset |
| 166 | ); |
| 167 | blob_zero(&line); |
| 168 | if( iBrief ){ |
| 169 | fossil_print("History of %s\n", blob_str(&fname)); |
| 170 | } |
| @@ -243,14 +249,14 @@ | |
| 243 | " (SELECT uuid FROM blob WHERE rid=mlink.mid)," /* Check-in uuid */ |
| 244 | " event.bgcolor," /* Background color */ |
| 245 | " (SELECT value FROM tagxref WHERE tagid=%d AND tagtype>0" |
| 246 | " AND tagxref.rid=mlink.mid)" /* Tags */ |
| 247 | " FROM mlink, event" |
| 248 | " WHERE mlink.fnid=(SELECT fnid FROM filename WHERE name=%Q)" |
| 249 | " AND event.objid=mlink.mid", |
| 250 | TAG_BRANCH, |
| 251 | zFilename |
| 252 | ); |
| 253 | if( (zA = P("a"))!=0 ){ |
| 254 | blob_appendf(&sql, " AND event.mtime>=julianday('%q')", zA); |
| 255 | } |
| 256 | if( (zB = P("b"))!=0 ){ |
| 257 |
| --- src/finfo.c | |
| +++ src/finfo.c | |
| @@ -39,22 +39,25 @@ | |
| 39 | ** In the -p form, there's an optional flag "-r|--revision REVISION". |
| 40 | ** The specified version (or the latest checked out version) is printed |
| 41 | ** to stdout. |
| 42 | ** |
| 43 | ** Options: |
| 44 | ** --brief|-b display a brief (one line / revision) summary |
| 45 | ** --limit N display the first N changes |
| 46 | ** --log|-l select log mode (the default) |
| 47 | ** --offset P skip P changes |
| 48 | ** -p select print mode |
| 49 | ** --revision|-r R print the given revision (or ckout, if none is given) |
| 50 | ** to stdout (only in print mode) |
| 51 | ** -s select status mode (print a status indicator for FILE) |
| 52 | ** --case-sensitive B Enable or disable case-sensitive filenames. B is a |
| 53 | ** boolean: "yes", "no", "true", "false", etc. |
| 54 | ** |
| 55 | ** See also: descendants, info, leaves |
| 56 | */ |
| 57 | void finfo_cmd(void){ |
| 58 | capture_case_sensitive_option(); |
| 59 | db_must_be_within_tree(); |
| 60 | if (find_option("status","s",0)) { |
| 61 | Stmt q; |
| 62 | Blob line; |
| 63 | Blob fname; |
| @@ -67,11 +70,12 @@ | |
| 70 | } |
| 71 | vfile_check_signature(vid, 1, 0); |
| 72 | file_tree_name(g.argv[2], &fname, 1); |
| 73 | db_prepare(&q, |
| 74 | "SELECT pathname, deleted, rid, chnged, coalesce(origname!=pathname,0)" |
| 75 | " FROM vfile WHERE vfile.pathname=%B %s", |
| 76 | &fname, filename_collation()); |
| 77 | blob_zero(&line); |
| 78 | if ( db_step(&q)==SQLITE_ROW ) { |
| 79 | Blob uuid; |
| 80 | int isDeleted = db_column_int(&q, 1); |
| 81 | int isNew = db_column_int(&q,2) == 0; |
| @@ -80,12 +84,12 @@ | |
| 84 | |
| 85 | blob_zero(&uuid); |
| 86 | db_blob(&uuid, |
| 87 | "SELECT uuid FROM blob, mlink, vfile WHERE " |
| 88 | "blob.rid = mlink.mid AND mlink.fid = vfile.rid AND " |
| 89 | "vfile.pathname=%B %s", |
| 90 | &fname, filename_collation() |
| 91 | ); |
| 92 | if( isNew ){ |
| 93 | blob_appendf(&line, "new"); |
| 94 | }else if( isDeleted ){ |
| 95 | blob_appendf(&line, "deleted"); |
| @@ -113,11 +117,12 @@ | |
| 117 | |
| 118 | file_tree_name(g.argv[2], &fname, 1); |
| 119 | if( zRevision ){ |
| 120 | historical_version_of_file(zRevision, blob_str(&fname), &record, 0, 0, 0); |
| 121 | }else{ |
| 122 | int rid = db_int(0, "SELECT rid FROM vfile WHERE pathname=%B %s", |
| 123 | &fname, filename_collation()); |
| 124 | if( rid==0 ){ |
| 125 | fossil_fatal("no history for file: %b", &fname); |
| 126 | } |
| 127 | content_get(rid, &record); |
| 128 | } |
| @@ -144,27 +149,28 @@ | |
| 149 | iBrief = (find_option("brief","b",0) == 0); |
| 150 | if( g.argc!=3 ){ |
| 151 | usage("?-l|--log? ?-b|--brief? FILENAME"); |
| 152 | } |
| 153 | file_tree_name(g.argv[2], &fname, 1); |
| 154 | rid = db_int(0, "SELECT rid FROM vfile WHERE pathname=%B %s", |
| 155 | &fname, filename_collation()); |
| 156 | if( rid==0 ){ |
| 157 | fossil_fatal("no history for file: %b", &fname); |
| 158 | } |
| 159 | zFilename = blob_str(&fname); |
| 160 | db_prepare(&q, |
| 161 | "SELECT b.uuid, ci.uuid, date(event.mtime,'localtime')," |
| 162 | " coalesce(event.ecomment, event.comment)," |
| 163 | " coalesce(event.euser, event.user)" |
| 164 | " FROM mlink, blob b, event, blob ci, filename" |
| 165 | " WHERE filename.name=%Q %s" |
| 166 | " AND mlink.fnid=filename.fnid" |
| 167 | " AND b.rid=mlink.fid" |
| 168 | " AND event.objid=mlink.mid" |
| 169 | " AND event.objid=ci.rid" |
| 170 | " ORDER BY event.mtime DESC LIMIT %d OFFSET %d", |
| 171 | zFilename, filename_collation(), iLimit, iOffset |
| 172 | ); |
| 173 | blob_zero(&line); |
| 174 | if( iBrief ){ |
| 175 | fossil_print("History of %s\n", blob_str(&fname)); |
| 176 | } |
| @@ -243,14 +249,14 @@ | |
| 249 | " (SELECT uuid FROM blob WHERE rid=mlink.mid)," /* Check-in uuid */ |
| 250 | " event.bgcolor," /* Background color */ |
| 251 | " (SELECT value FROM tagxref WHERE tagid=%d AND tagtype>0" |
| 252 | " AND tagxref.rid=mlink.mid)" /* Tags */ |
| 253 | " FROM mlink, event" |
| 254 | " WHERE mlink.fnid IN (SELECT fnid FROM filename WHERE name=%Q %s)" |
| 255 | " AND event.objid=mlink.mid", |
| 256 | TAG_BRANCH, |
| 257 | zFilename, filename_collation() |
| 258 | ); |
| 259 | if( (zA = P("a"))!=0 ){ |
| 260 | blob_appendf(&sql, " AND event.mtime>=julianday('%q')", zA); |
| 261 | } |
| 262 | if( (zB = P("b"))!=0 ){ |
| 263 |
+1
-1
| --- src/http.c | ||
| +++ src/http.c | ||
| @@ -111,11 +111,11 @@ | ||
| 111 | 111 | fossil_free(zEncoded); |
| 112 | 112 | fossil_free(zCredentials); |
| 113 | 113 | } |
| 114 | 114 | blob_appendf(pHdr, "Host: %s\r\n", g.urlHostname); |
| 115 | 115 | blob_appendf(pHdr, "User-Agent: Fossil/" RELEASE_VERSION |
| 116 | - "-" MANIFEST_VERSION "\r\n"); | |
| 116 | + " (" MANIFEST_DATE " " MANIFEST_VERSION ")\r\n"); | |
| 117 | 117 | if( g.fHttpTrace ){ |
| 118 | 118 | blob_appendf(pHdr, "Content-Type: application/x-fossil-debug\r\n"); |
| 119 | 119 | }else{ |
| 120 | 120 | blob_appendf(pHdr, "Content-Type: application/x-fossil\r\n"); |
| 121 | 121 | } |
| 122 | 122 |
| --- src/http.c | |
| +++ src/http.c | |
| @@ -111,11 +111,11 @@ | |
| 111 | fossil_free(zEncoded); |
| 112 | fossil_free(zCredentials); |
| 113 | } |
| 114 | blob_appendf(pHdr, "Host: %s\r\n", g.urlHostname); |
| 115 | blob_appendf(pHdr, "User-Agent: Fossil/" RELEASE_VERSION |
| 116 | "-" MANIFEST_VERSION "\r\n"); |
| 117 | if( g.fHttpTrace ){ |
| 118 | blob_appendf(pHdr, "Content-Type: application/x-fossil-debug\r\n"); |
| 119 | }else{ |
| 120 | blob_appendf(pHdr, "Content-Type: application/x-fossil\r\n"); |
| 121 | } |
| 122 |
| --- src/http.c | |
| +++ src/http.c | |
| @@ -111,11 +111,11 @@ | |
| 111 | fossil_free(zEncoded); |
| 112 | fossil_free(zCredentials); |
| 113 | } |
| 114 | blob_appendf(pHdr, "Host: %s\r\n", g.urlHostname); |
| 115 | blob_appendf(pHdr, "User-Agent: Fossil/" RELEASE_VERSION |
| 116 | " (" MANIFEST_DATE " " MANIFEST_VERSION ")\r\n"); |
| 117 | if( g.fHttpTrace ){ |
| 118 | blob_appendf(pHdr, "Content-Type: application/x-fossil-debug\r\n"); |
| 119 | }else{ |
| 120 | blob_appendf(pHdr, "Content-Type: application/x-fossil\r\n"); |
| 121 | } |
| 122 |
+18
-2
| --- src/json_login.c | ||
| +++ src/json_login.c | ||
| @@ -155,13 +155,29 @@ | ||
| 155 | 155 | payload = cson_value_new_object(); |
| 156 | 156 | po = cson_value_get_object(payload); |
| 157 | 157 | cson_object_set(po, "authToken", json_new_string(cookie)); |
| 158 | 158 | free(cookie); |
| 159 | 159 | cson_object_set(po, "name", json_new_string(name)); |
| 160 | - cap = db_text(NULL, "SELECT cap FROM user WHERE login=%Q",name); | |
| 161 | - cson_object_set(po, "capabilities", json_new_string(cap)); | |
| 160 | + cap = db_text(NULL, "SELECT cap FROM user WHERE login=%Q", name); | |
| 161 | + cson_object_set(po, "capabilities", cap ? json_new_string(cap) : cson_value_null() ); | |
| 162 | 162 | free(cap); |
| 163 | + cson_object_set(po, "loginCookieName", json_new_string( login_cookie_name() ) ); | |
| 164 | + /* TODO: add loginExpiryTime to the payload. To do this properly | |
| 165 | + we "should" add an ([unsigned] int *) to | |
| 166 | + login_set_user_cookie() and login_set_anon_cookie(), to which | |
| 167 | + the expiry time is assigned. (Remember that JSON doesn't do | |
| 168 | + unsigned int.) | |
| 169 | + | |
| 170 | + For non-anonymous users we could also simply query the | |
| 171 | + user.cexpire db field after calling login_set_user_cookie(), | |
| 172 | + but for anonymous we need to get the time when the cookie is | |
| 173 | + set because anon does not get a db entry like normal users | |
| 174 | + do. Anonyous cookies currently have a hard-coded lifetime in | |
| 175 | + login_set_anon_cookie() (currently 6 hours), which we "should | |
| 176 | + arguably" change to use the time configured for non-anonymous | |
| 177 | + users (see login_set_user_cookie() for details). | |
| 178 | + */ | |
| 163 | 179 | return payload; |
| 164 | 180 | } |
| 165 | 181 | } |
| 166 | 182 | |
| 167 | 183 | /* |
| 168 | 184 |
| --- src/json_login.c | |
| +++ src/json_login.c | |
| @@ -155,13 +155,29 @@ | |
| 155 | payload = cson_value_new_object(); |
| 156 | po = cson_value_get_object(payload); |
| 157 | cson_object_set(po, "authToken", json_new_string(cookie)); |
| 158 | free(cookie); |
| 159 | cson_object_set(po, "name", json_new_string(name)); |
| 160 | cap = db_text(NULL, "SELECT cap FROM user WHERE login=%Q",name); |
| 161 | cson_object_set(po, "capabilities", json_new_string(cap)); |
| 162 | free(cap); |
| 163 | return payload; |
| 164 | } |
| 165 | } |
| 166 | |
| 167 | /* |
| 168 |
| --- src/json_login.c | |
| +++ src/json_login.c | |
| @@ -155,13 +155,29 @@ | |
| 155 | payload = cson_value_new_object(); |
| 156 | po = cson_value_get_object(payload); |
| 157 | cson_object_set(po, "authToken", json_new_string(cookie)); |
| 158 | free(cookie); |
| 159 | cson_object_set(po, "name", json_new_string(name)); |
| 160 | cap = db_text(NULL, "SELECT cap FROM user WHERE login=%Q", name); |
| 161 | cson_object_set(po, "capabilities", cap ? json_new_string(cap) : cson_value_null() ); |
| 162 | free(cap); |
| 163 | cson_object_set(po, "loginCookieName", json_new_string( login_cookie_name() ) ); |
| 164 | /* TODO: add loginExpiryTime to the payload. To do this properly |
| 165 | we "should" add an ([unsigned] int *) to |
| 166 | login_set_user_cookie() and login_set_anon_cookie(), to which |
| 167 | the expiry time is assigned. (Remember that JSON doesn't do |
| 168 | unsigned int.) |
| 169 | |
| 170 | For non-anonymous users we could also simply query the |
| 171 | user.cexpire db field after calling login_set_user_cookie(), |
| 172 | but for anonymous we need to get the time when the cookie is |
| 173 | set because anon does not get a db entry like normal users |
| 174 | do. Anonyous cookies currently have a hard-coded lifetime in |
| 175 | login_set_anon_cookie() (currently 6 hours), which we "should |
| 176 | arguably" change to use the time configured for non-anonymous |
| 177 | users (see login_set_user_cookie() for details). |
| 178 | */ |
| 179 | return payload; |
| 180 | } |
| 181 | } |
| 182 | |
| 183 | /* |
| 184 |
+31
-6
| --- src/login.c | ||
| +++ src/login.c | ||
| @@ -352,25 +352,50 @@ | ||
| 352 | 352 | ** downstream problems here. We could alternately use "" here. |
| 353 | 353 | */ |
| 354 | 354 | ; |
| 355 | 355 | } |
| 356 | 356 | } |
| 357 | + | |
| 358 | +/* | |
| 359 | +** Return true if the prefix of zStr matches zPattern. Return false if | |
| 360 | +** they are different. | |
| 361 | +** | |
| 362 | +** A lowercase character in zPattern will match either upper or lower | |
| 363 | +** case in zStr. But an uppercase in zPattern will only match an | |
| 364 | +** uppercase in zStr. | |
| 365 | +*/ | |
| 366 | +static int prefix_match(const char *zPattern, const char *zStr){ | |
| 367 | + int i; | |
| 368 | + char c; | |
| 369 | + for(i=0; (c = zPattern[i])!=0; i++){ | |
| 370 | + if( zStr[i]!=c && fossil_tolower(zStr[i])!=c ) return 0; | |
| 371 | + } | |
| 372 | + return 1; | |
| 373 | +} | |
| 357 | 374 | |
| 358 | 375 | /* |
| 359 | 376 | ** Look at the HTTP_USER_AGENT parameter and try to determine if the user agent |
| 360 | -** is a manually operated browser or a bot. When in doubt, assume a bot. Return | |
| 361 | -** true if we believe the agent is a real person. | |
| 377 | +** is a manually operated browser or a bot. When in doubt, assume a bot. | |
| 378 | +** Return true if we believe the agent is a real person. | |
| 362 | 379 | */ |
| 363 | 380 | static int isHuman(const char *zAgent){ |
| 364 | 381 | int i; |
| 365 | - if( zAgent==0 ) return 0; | |
| 382 | + if( zAgent==0 ) return 0; /* If not UserAgent, the probably a bot */ | |
| 366 | 383 | for(i=0; zAgent[i]; i++){ |
| 367 | - if( zAgent[i]=='b' && memcmp(&zAgent[i],"bot",3)==0 ) return 0; | |
| 368 | - if( zAgent[i]=='s' && memcmp(&zAgent[i],"spider",6)==0 ) return 0; | |
| 384 | + if( prefix_match("bot", zAgent+i) ) return 0; | |
| 385 | + if( prefix_match("spider", zAgent+i) ) return 0; | |
| 386 | + if( prefix_match("crawl", zAgent+i) ) return 0; | |
| 387 | + /* If a URI appears in the User-Agent, it is probably a bot */ | |
| 388 | + if( memcmp("http", zAgent+i,4)==0 ) return 0; | |
| 369 | 389 | } |
| 370 | 390 | if( memcmp(zAgent, "Mozilla/", 8)==0 ){ |
| 371 | - return atoi(&zAgent[8])>=4; | |
| 391 | + if( atoi(&zAgent[8])<4 ) return 0; /* Many bots advertise as Mozilla/3 */ | |
| 392 | + if( strglob("*Firefox/[1-9]*", zAgent) ) return 1; | |
| 393 | + if( strglob("*Chrome/[1-9]*", zAgent) ) return 1; | |
| 394 | + if( strglob("*(compatible;?MSIE?[1-9]*", zAgent) ) return 1; | |
| 395 | + if( strglob("*AppleWebKit/[1-9]*(KHTML*", zAgent) ) return 1; | |
| 396 | + return 0; | |
| 372 | 397 | } |
| 373 | 398 | if( memcmp(zAgent, "Opera/", 6)==0 ) return 1; |
| 374 | 399 | if( memcmp(zAgent, "Safari/", 7)==0 ) return 1; |
| 375 | 400 | if( memcmp(zAgent, "Lynx/", 5)==0 ) return 1; |
| 376 | 401 | return 0; |
| 377 | 402 |
| --- src/login.c | |
| +++ src/login.c | |
| @@ -352,25 +352,50 @@ | |
| 352 | ** downstream problems here. We could alternately use "" here. |
| 353 | */ |
| 354 | ; |
| 355 | } |
| 356 | } |
| 357 | |
| 358 | /* |
| 359 | ** Look at the HTTP_USER_AGENT parameter and try to determine if the user agent |
| 360 | ** is a manually operated browser or a bot. When in doubt, assume a bot. Return |
| 361 | ** true if we believe the agent is a real person. |
| 362 | */ |
| 363 | static int isHuman(const char *zAgent){ |
| 364 | int i; |
| 365 | if( zAgent==0 ) return 0; |
| 366 | for(i=0; zAgent[i]; i++){ |
| 367 | if( zAgent[i]=='b' && memcmp(&zAgent[i],"bot",3)==0 ) return 0; |
| 368 | if( zAgent[i]=='s' && memcmp(&zAgent[i],"spider",6)==0 ) return 0; |
| 369 | } |
| 370 | if( memcmp(zAgent, "Mozilla/", 8)==0 ){ |
| 371 | return atoi(&zAgent[8])>=4; |
| 372 | } |
| 373 | if( memcmp(zAgent, "Opera/", 6)==0 ) return 1; |
| 374 | if( memcmp(zAgent, "Safari/", 7)==0 ) return 1; |
| 375 | if( memcmp(zAgent, "Lynx/", 5)==0 ) return 1; |
| 376 | return 0; |
| 377 |
| --- src/login.c | |
| +++ src/login.c | |
| @@ -352,25 +352,50 @@ | |
| 352 | ** downstream problems here. We could alternately use "" here. |
| 353 | */ |
| 354 | ; |
| 355 | } |
| 356 | } |
| 357 | |
| 358 | /* |
| 359 | ** Return true if the prefix of zStr matches zPattern. Return false if |
| 360 | ** they are different. |
| 361 | ** |
| 362 | ** A lowercase character in zPattern will match either upper or lower |
| 363 | ** case in zStr. But an uppercase in zPattern will only match an |
| 364 | ** uppercase in zStr. |
| 365 | */ |
| 366 | static int prefix_match(const char *zPattern, const char *zStr){ |
| 367 | int i; |
| 368 | char c; |
| 369 | for(i=0; (c = zPattern[i])!=0; i++){ |
| 370 | if( zStr[i]!=c && fossil_tolower(zStr[i])!=c ) return 0; |
| 371 | } |
| 372 | return 1; |
| 373 | } |
| 374 | |
| 375 | /* |
| 376 | ** Look at the HTTP_USER_AGENT parameter and try to determine if the user agent |
| 377 | ** is a manually operated browser or a bot. When in doubt, assume a bot. |
| 378 | ** Return true if we believe the agent is a real person. |
| 379 | */ |
| 380 | static int isHuman(const char *zAgent){ |
| 381 | int i; |
| 382 | if( zAgent==0 ) return 0; /* If not UserAgent, the probably a bot */ |
| 383 | for(i=0; zAgent[i]; i++){ |
| 384 | if( prefix_match("bot", zAgent+i) ) return 0; |
| 385 | if( prefix_match("spider", zAgent+i) ) return 0; |
| 386 | if( prefix_match("crawl", zAgent+i) ) return 0; |
| 387 | /* If a URI appears in the User-Agent, it is probably a bot */ |
| 388 | if( memcmp("http", zAgent+i,4)==0 ) return 0; |
| 389 | } |
| 390 | if( memcmp(zAgent, "Mozilla/", 8)==0 ){ |
| 391 | if( atoi(&zAgent[8])<4 ) return 0; /* Many bots advertise as Mozilla/3 */ |
| 392 | if( strglob("*Firefox/[1-9]*", zAgent) ) return 1; |
| 393 | if( strglob("*Chrome/[1-9]*", zAgent) ) return 1; |
| 394 | if( strglob("*(compatible;?MSIE?[1-9]*", zAgent) ) return 1; |
| 395 | if( strglob("*AppleWebKit/[1-9]*(KHTML*", zAgent) ) return 1; |
| 396 | return 0; |
| 397 | } |
| 398 | if( memcmp(zAgent, "Opera/", 6)==0 ) return 1; |
| 399 | if( memcmp(zAgent, "Safari/", 7)==0 ) return 1; |
| 400 | if( memcmp(zAgent, "Lynx/", 5)==0 ) return 1; |
| 401 | return 0; |
| 402 |
+28
| --- src/manifest.c | ||
| +++ src/manifest.c | ||
| @@ -1223,10 +1223,38 @@ | ||
| 1223 | 1223 | fetch_baseline(p, 1); |
| 1224 | 1224 | pFile = manifest_file_seek_base(p->pBaseline, zName); |
| 1225 | 1225 | } |
| 1226 | 1226 | return pFile; |
| 1227 | 1227 | } |
| 1228 | + | |
| 1229 | +/* | |
| 1230 | +** Look for a file in a manifest, taking the case-sensitive option | |
| 1231 | +** into account. If case-sensitive is off, then files in any case | |
| 1232 | +** will match. | |
| 1233 | +*/ | |
| 1234 | +ManifestFile *manifest_file_find(Manifest *p, const char *zName){ | |
| 1235 | + int i, n; | |
| 1236 | + Manifest *pBase; | |
| 1237 | + if( filenames_are_case_sensitive() ){ | |
| 1238 | + return manifest_file_seek(p, zName); | |
| 1239 | + } | |
| 1240 | + for(i=0; i<p->nFile; i++){ | |
| 1241 | + if( fossil_stricmp(zName, p->aFile[i].zName)==0 ){ | |
| 1242 | + return &p->aFile[i]; | |
| 1243 | + } | |
| 1244 | + } | |
| 1245 | + if( p->zBaseline==0 ) return 0; | |
| 1246 | + fetch_baseline(p, 1); | |
| 1247 | + pBase = p->pBaseline; | |
| 1248 | + if( pBase==0 ) return 0; | |
| 1249 | + for(i=0; i<pBase->nFile; i++){ | |
| 1250 | + if( fossil_stricmp(zName, p->aFile[i].zName)==0 ){ | |
| 1251 | + return &p->aFile[i]; | |
| 1252 | + } | |
| 1253 | + } | |
| 1254 | + return 0; | |
| 1255 | +} | |
| 1228 | 1256 | |
| 1229 | 1257 | /* |
| 1230 | 1258 | ** Add mlink table entries associated with manifest cid, pChild. The |
| 1231 | 1259 | ** parent manifest is pid, pParent. One of either pChild or pParent |
| 1232 | 1260 | ** will be NULL and it will be computed based on cid/pid. |
| 1233 | 1261 |
| --- src/manifest.c | |
| +++ src/manifest.c | |
| @@ -1223,10 +1223,38 @@ | |
| 1223 | fetch_baseline(p, 1); |
| 1224 | pFile = manifest_file_seek_base(p->pBaseline, zName); |
| 1225 | } |
| 1226 | return pFile; |
| 1227 | } |
| 1228 | |
| 1229 | /* |
| 1230 | ** Add mlink table entries associated with manifest cid, pChild. The |
| 1231 | ** parent manifest is pid, pParent. One of either pChild or pParent |
| 1232 | ** will be NULL and it will be computed based on cid/pid. |
| 1233 |
| --- src/manifest.c | |
| +++ src/manifest.c | |
| @@ -1223,10 +1223,38 @@ | |
| 1223 | fetch_baseline(p, 1); |
| 1224 | pFile = manifest_file_seek_base(p->pBaseline, zName); |
| 1225 | } |
| 1226 | return pFile; |
| 1227 | } |
| 1228 | |
| 1229 | /* |
| 1230 | ** Look for a file in a manifest, taking the case-sensitive option |
| 1231 | ** into account. If case-sensitive is off, then files in any case |
| 1232 | ** will match. |
| 1233 | */ |
| 1234 | ManifestFile *manifest_file_find(Manifest *p, const char *zName){ |
| 1235 | int i, n; |
| 1236 | Manifest *pBase; |
| 1237 | if( filenames_are_case_sensitive() ){ |
| 1238 | return manifest_file_seek(p, zName); |
| 1239 | } |
| 1240 | for(i=0; i<p->nFile; i++){ |
| 1241 | if( fossil_stricmp(zName, p->aFile[i].zName)==0 ){ |
| 1242 | return &p->aFile[i]; |
| 1243 | } |
| 1244 | } |
| 1245 | if( p->zBaseline==0 ) return 0; |
| 1246 | fetch_baseline(p, 1); |
| 1247 | pBase = p->pBaseline; |
| 1248 | if( pBase==0 ) return 0; |
| 1249 | for(i=0; i<pBase->nFile; i++){ |
| 1250 | if( fossil_stricmp(zName, p->aFile[i].zName)==0 ){ |
| 1251 | return &p->aFile[i]; |
| 1252 | } |
| 1253 | } |
| 1254 | return 0; |
| 1255 | } |
| 1256 | |
| 1257 | /* |
| 1258 | ** Add mlink table entries associated with manifest cid, pChild. The |
| 1259 | ** parent manifest is pid, pParent. One of either pChild or pParent |
| 1260 | ** will be NULL and it will be computed based on cid/pid. |
| 1261 |
+13
-10
| --- src/sqlite3.c | ||
| +++ src/sqlite3.c | ||
| @@ -649,11 +649,11 @@ | ||
| 649 | 649 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 650 | 650 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 651 | 651 | */ |
| 652 | 652 | #define SQLITE_VERSION "3.7.9" |
| 653 | 653 | #define SQLITE_VERSION_NUMBER 3007009 |
| 654 | -#define SQLITE_SOURCE_ID "2011-10-29 19:25:08 5b82ec6fbbd2f4195ad06dd911de3817373ad5bf" | |
| 654 | +#define SQLITE_SOURCE_ID "2011-11-14 02:53:54 54cc11981127b52145e39f551d958580b1d45169" | |
| 655 | 655 | |
| 656 | 656 | /* |
| 657 | 657 | ** CAPI3REF: Run-Time Library Version Numbers |
| 658 | 658 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 659 | 659 | ** |
| @@ -1286,11 +1286,11 @@ | ||
| 1286 | 1286 | ** |
| 1287 | 1287 | ** ^The [SQLITE_FCNTL_WIN32_AV_RETRY] opcode is used to configure automatic |
| 1288 | 1288 | ** retry counts and intervals for certain disk I/O operations for the |
| 1289 | 1289 | ** windows [VFS] in order to work to provide robustness against |
| 1290 | 1290 | ** anti-virus programs. By default, the windows VFS will retry file read, |
| 1291 | -** file write, and file delete opertions up to 10 times, with a delay | |
| 1291 | +** file write, and file delete operations up to 10 times, with a delay | |
| 1292 | 1292 | ** of 25 milliseconds before the first retry and with the delay increasing |
| 1293 | 1293 | ** by an additional 25 milliseconds with each subsequent retry. This |
| 1294 | 1294 | ** opcode allows those to values (10 retries and 25 milliseconds of delay) |
| 1295 | 1295 | ** to be adjusted. The values are changed for all database connections |
| 1296 | 1296 | ** within the same process. The argument is a pointer to an array of two |
| @@ -82100,23 +82100,26 @@ | ||
| 82100 | 82100 | ** Allocate the index structure. |
| 82101 | 82101 | */ |
| 82102 | 82102 | nName = sqlite3Strlen30(zName); |
| 82103 | 82103 | nCol = pList->nExpr; |
| 82104 | 82104 | pIndex = sqlite3DbMallocZero(db, |
| 82105 | - sizeof(Index) + /* Index structure */ | |
| 82106 | - sizeof(tRowcnt)*(nCol+1) + /* Index.aiRowEst */ | |
| 82107 | - sizeof(int)*nCol + /* Index.aiColumn */ | |
| 82108 | - sizeof(char *)*nCol + /* Index.azColl */ | |
| 82109 | - sizeof(u8)*nCol + /* Index.aSortOrder */ | |
| 82110 | - nName + 1 + /* Index.zName */ | |
| 82111 | - nExtra /* Collation sequence names */ | |
| 82105 | + sizeof(Index) + /* Index structure */ | |
| 82106 | + ROUND8(sizeof(tRowcnt)*(nCol+1)) + /* Index.aiRowEst */ | |
| 82107 | + sizeof(char *)*nCol + /* Index.azColl */ | |
| 82108 | + sizeof(int)*nCol + /* Index.aiColumn */ | |
| 82109 | + sizeof(u8)*nCol + /* Index.aSortOrder */ | |
| 82110 | + nName + 1 + /* Index.zName */ | |
| 82111 | + nExtra /* Collation sequence names */ | |
| 82112 | 82112 | ); |
| 82113 | 82113 | if( db->mallocFailed ){ |
| 82114 | 82114 | goto exit_create_index; |
| 82115 | 82115 | } |
| 82116 | 82116 | pIndex->aiRowEst = (tRowcnt*)(&pIndex[1]); |
| 82117 | - pIndex->azColl = (char**)(&pIndex->aiRowEst[nCol+1]); | |
| 82117 | + pIndex->azColl = (char**) | |
| 82118 | + ((char*)pIndex->aiRowEst + ROUND8(sizeof(tRowcnt)*nCol+1)); | |
| 82119 | + assert( EIGHT_BYTE_ALIGNMENT(pIndex->aiRowEst) ); | |
| 82120 | + assert( EIGHT_BYTE_ALIGNMENT(pIndex->azColl) ); | |
| 82118 | 82121 | pIndex->aiColumn = (int *)(&pIndex->azColl[nCol]); |
| 82119 | 82122 | pIndex->aSortOrder = (u8 *)(&pIndex->aiColumn[nCol]); |
| 82120 | 82123 | pIndex->zName = (char *)(&pIndex->aSortOrder[nCol]); |
| 82121 | 82124 | zExtra = (char *)(&pIndex->zName[nName+1]); |
| 82122 | 82125 | memcpy(pIndex->zName, zName, nName+1); |
| 82123 | 82126 |
| --- src/sqlite3.c | |
| +++ src/sqlite3.c | |
| @@ -649,11 +649,11 @@ | |
| 649 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 650 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 651 | */ |
| 652 | #define SQLITE_VERSION "3.7.9" |
| 653 | #define SQLITE_VERSION_NUMBER 3007009 |
| 654 | #define SQLITE_SOURCE_ID "2011-10-29 19:25:08 5b82ec6fbbd2f4195ad06dd911de3817373ad5bf" |
| 655 | |
| 656 | /* |
| 657 | ** CAPI3REF: Run-Time Library Version Numbers |
| 658 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 659 | ** |
| @@ -1286,11 +1286,11 @@ | |
| 1286 | ** |
| 1287 | ** ^The [SQLITE_FCNTL_WIN32_AV_RETRY] opcode is used to configure automatic |
| 1288 | ** retry counts and intervals for certain disk I/O operations for the |
| 1289 | ** windows [VFS] in order to work to provide robustness against |
| 1290 | ** anti-virus programs. By default, the windows VFS will retry file read, |
| 1291 | ** file write, and file delete opertions up to 10 times, with a delay |
| 1292 | ** of 25 milliseconds before the first retry and with the delay increasing |
| 1293 | ** by an additional 25 milliseconds with each subsequent retry. This |
| 1294 | ** opcode allows those to values (10 retries and 25 milliseconds of delay) |
| 1295 | ** to be adjusted. The values are changed for all database connections |
| 1296 | ** within the same process. The argument is a pointer to an array of two |
| @@ -82100,23 +82100,26 @@ | |
| 82100 | ** Allocate the index structure. |
| 82101 | */ |
| 82102 | nName = sqlite3Strlen30(zName); |
| 82103 | nCol = pList->nExpr; |
| 82104 | pIndex = sqlite3DbMallocZero(db, |
| 82105 | sizeof(Index) + /* Index structure */ |
| 82106 | sizeof(tRowcnt)*(nCol+1) + /* Index.aiRowEst */ |
| 82107 | sizeof(int)*nCol + /* Index.aiColumn */ |
| 82108 | sizeof(char *)*nCol + /* Index.azColl */ |
| 82109 | sizeof(u8)*nCol + /* Index.aSortOrder */ |
| 82110 | nName + 1 + /* Index.zName */ |
| 82111 | nExtra /* Collation sequence names */ |
| 82112 | ); |
| 82113 | if( db->mallocFailed ){ |
| 82114 | goto exit_create_index; |
| 82115 | } |
| 82116 | pIndex->aiRowEst = (tRowcnt*)(&pIndex[1]); |
| 82117 | pIndex->azColl = (char**)(&pIndex->aiRowEst[nCol+1]); |
| 82118 | pIndex->aiColumn = (int *)(&pIndex->azColl[nCol]); |
| 82119 | pIndex->aSortOrder = (u8 *)(&pIndex->aiColumn[nCol]); |
| 82120 | pIndex->zName = (char *)(&pIndex->aSortOrder[nCol]); |
| 82121 | zExtra = (char *)(&pIndex->zName[nName+1]); |
| 82122 | memcpy(pIndex->zName, zName, nName+1); |
| 82123 |
| --- src/sqlite3.c | |
| +++ src/sqlite3.c | |
| @@ -649,11 +649,11 @@ | |
| 649 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 650 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 651 | */ |
| 652 | #define SQLITE_VERSION "3.7.9" |
| 653 | #define SQLITE_VERSION_NUMBER 3007009 |
| 654 | #define SQLITE_SOURCE_ID "2011-11-14 02:53:54 54cc11981127b52145e39f551d958580b1d45169" |
| 655 | |
| 656 | /* |
| 657 | ** CAPI3REF: Run-Time Library Version Numbers |
| 658 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 659 | ** |
| @@ -1286,11 +1286,11 @@ | |
| 1286 | ** |
| 1287 | ** ^The [SQLITE_FCNTL_WIN32_AV_RETRY] opcode is used to configure automatic |
| 1288 | ** retry counts and intervals for certain disk I/O operations for the |
| 1289 | ** windows [VFS] in order to work to provide robustness against |
| 1290 | ** anti-virus programs. By default, the windows VFS will retry file read, |
| 1291 | ** file write, and file delete operations up to 10 times, with a delay |
| 1292 | ** of 25 milliseconds before the first retry and with the delay increasing |
| 1293 | ** by an additional 25 milliseconds with each subsequent retry. This |
| 1294 | ** opcode allows those to values (10 retries and 25 milliseconds of delay) |
| 1295 | ** to be adjusted. The values are changed for all database connections |
| 1296 | ** within the same process. The argument is a pointer to an array of two |
| @@ -82100,23 +82100,26 @@ | |
| 82100 | ** Allocate the index structure. |
| 82101 | */ |
| 82102 | nName = sqlite3Strlen30(zName); |
| 82103 | nCol = pList->nExpr; |
| 82104 | pIndex = sqlite3DbMallocZero(db, |
| 82105 | sizeof(Index) + /* Index structure */ |
| 82106 | ROUND8(sizeof(tRowcnt)*(nCol+1)) + /* Index.aiRowEst */ |
| 82107 | sizeof(char *)*nCol + /* Index.azColl */ |
| 82108 | sizeof(int)*nCol + /* Index.aiColumn */ |
| 82109 | sizeof(u8)*nCol + /* Index.aSortOrder */ |
| 82110 | nName + 1 + /* Index.zName */ |
| 82111 | nExtra /* Collation sequence names */ |
| 82112 | ); |
| 82113 | if( db->mallocFailed ){ |
| 82114 | goto exit_create_index; |
| 82115 | } |
| 82116 | pIndex->aiRowEst = (tRowcnt*)(&pIndex[1]); |
| 82117 | pIndex->azColl = (char**) |
| 82118 | ((char*)pIndex->aiRowEst + ROUND8(sizeof(tRowcnt)*nCol+1)); |
| 82119 | assert( EIGHT_BYTE_ALIGNMENT(pIndex->aiRowEst) ); |
| 82120 | assert( EIGHT_BYTE_ALIGNMENT(pIndex->azColl) ); |
| 82121 | pIndex->aiColumn = (int *)(&pIndex->azColl[nCol]); |
| 82122 | pIndex->aSortOrder = (u8 *)(&pIndex->aiColumn[nCol]); |
| 82123 | pIndex->zName = (char *)(&pIndex->aSortOrder[nCol]); |
| 82124 | zExtra = (char *)(&pIndex->zName[nName+1]); |
| 82125 | memcpy(pIndex->zName, zName, nName+1); |
| 82126 |
+2
-2
| --- 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.7.9" |
| 111 | 111 | #define SQLITE_VERSION_NUMBER 3007009 |
| 112 | -#define SQLITE_SOURCE_ID "2011-10-29 19:25:08 5b82ec6fbbd2f4195ad06dd911de3817373ad5bf" | |
| 112 | +#define SQLITE_SOURCE_ID "2011-11-14 02:53:54 54cc11981127b52145e39f551d958580b1d45169" | |
| 113 | 113 | |
| 114 | 114 | /* |
| 115 | 115 | ** CAPI3REF: Run-Time Library Version Numbers |
| 116 | 116 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 117 | 117 | ** |
| @@ -744,11 +744,11 @@ | ||
| 744 | 744 | ** |
| 745 | 745 | ** ^The [SQLITE_FCNTL_WIN32_AV_RETRY] opcode is used to configure automatic |
| 746 | 746 | ** retry counts and intervals for certain disk I/O operations for the |
| 747 | 747 | ** windows [VFS] in order to work to provide robustness against |
| 748 | 748 | ** anti-virus programs. By default, the windows VFS will retry file read, |
| 749 | -** file write, and file delete opertions up to 10 times, with a delay | |
| 749 | +** file write, and file delete operations up to 10 times, with a delay | |
| 750 | 750 | ** of 25 milliseconds before the first retry and with the delay increasing |
| 751 | 751 | ** by an additional 25 milliseconds with each subsequent retry. This |
| 752 | 752 | ** opcode allows those to values (10 retries and 25 milliseconds of delay) |
| 753 | 753 | ** to be adjusted. The values are changed for all database connections |
| 754 | 754 | ** within the same process. The argument is a pointer to an array of two |
| 755 | 755 |
| --- 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.7.9" |
| 111 | #define SQLITE_VERSION_NUMBER 3007009 |
| 112 | #define SQLITE_SOURCE_ID "2011-10-29 19:25:08 5b82ec6fbbd2f4195ad06dd911de3817373ad5bf" |
| 113 | |
| 114 | /* |
| 115 | ** CAPI3REF: Run-Time Library Version Numbers |
| 116 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 117 | ** |
| @@ -744,11 +744,11 @@ | |
| 744 | ** |
| 745 | ** ^The [SQLITE_FCNTL_WIN32_AV_RETRY] opcode is used to configure automatic |
| 746 | ** retry counts and intervals for certain disk I/O operations for the |
| 747 | ** windows [VFS] in order to work to provide robustness against |
| 748 | ** anti-virus programs. By default, the windows VFS will retry file read, |
| 749 | ** file write, and file delete opertions up to 10 times, with a delay |
| 750 | ** of 25 milliseconds before the first retry and with the delay increasing |
| 751 | ** by an additional 25 milliseconds with each subsequent retry. This |
| 752 | ** opcode allows those to values (10 retries and 25 milliseconds of delay) |
| 753 | ** to be adjusted. The values are changed for all database connections |
| 754 | ** within the same process. The argument is a pointer to an array of two |
| 755 |
| --- 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.7.9" |
| 111 | #define SQLITE_VERSION_NUMBER 3007009 |
| 112 | #define SQLITE_SOURCE_ID "2011-11-14 02:53:54 54cc11981127b52145e39f551d958580b1d45169" |
| 113 | |
| 114 | /* |
| 115 | ** CAPI3REF: Run-Time Library Version Numbers |
| 116 | ** KEYWORDS: sqlite3_version, sqlite3_sourceid |
| 117 | ** |
| @@ -744,11 +744,11 @@ | |
| 744 | ** |
| 745 | ** ^The [SQLITE_FCNTL_WIN32_AV_RETRY] opcode is used to configure automatic |
| 746 | ** retry counts and intervals for certain disk I/O operations for the |
| 747 | ** windows [VFS] in order to work to provide robustness against |
| 748 | ** anti-virus programs. By default, the windows VFS will retry file read, |
| 749 | ** file write, and file delete operations up to 10 times, with a delay |
| 750 | ** of 25 milliseconds before the first retry and with the delay increasing |
| 751 | ** by an additional 25 milliseconds with each subsequent retry. This |
| 752 | ** opcode allows those to values (10 retries and 25 milliseconds of delay) |
| 753 | ** to be adjusted. The values are changed for all database connections |
| 754 | ** within the same process. The argument is a pointer to an array of two |
| 755 |
+1
| --- src/style.c | ||
| +++ src/style.c | ||
| @@ -893,10 +893,11 @@ | ||
| 893 | 893 | zCap[i] = 0; |
| 894 | 894 | @ g.userUid = %d(g.userUid)<br /> |
| 895 | 895 | @ g.zLogin = %h(g.zLogin)<br /> |
| 896 | 896 | @ capabilities = %s(zCap)<br /> |
| 897 | 897 | @ <hr> |
| 898 | + P("HTTP_USER_AGENT"); | |
| 898 | 899 | cgi_print_all(atoi(PD("showall","0"))); |
| 899 | 900 | if( g.perm.Setup ){ |
| 900 | 901 | const char *zRedir = P("redirect"); |
| 901 | 902 | if( zRedir ) cgi_redirect(zRedir); |
| 902 | 903 | } |
| 903 | 904 |
| --- src/style.c | |
| +++ src/style.c | |
| @@ -893,10 +893,11 @@ | |
| 893 | zCap[i] = 0; |
| 894 | @ g.userUid = %d(g.userUid)<br /> |
| 895 | @ g.zLogin = %h(g.zLogin)<br /> |
| 896 | @ capabilities = %s(zCap)<br /> |
| 897 | @ <hr> |
| 898 | cgi_print_all(atoi(PD("showall","0"))); |
| 899 | if( g.perm.Setup ){ |
| 900 | const char *zRedir = P("redirect"); |
| 901 | if( zRedir ) cgi_redirect(zRedir); |
| 902 | } |
| 903 |
| --- src/style.c | |
| +++ src/style.c | |
| @@ -893,10 +893,11 @@ | |
| 893 | zCap[i] = 0; |
| 894 | @ g.userUid = %d(g.userUid)<br /> |
| 895 | @ g.zLogin = %h(g.zLogin)<br /> |
| 896 | @ capabilities = %s(zCap)<br /> |
| 897 | @ <hr> |
| 898 | P("HTTP_USER_AGENT"); |
| 899 | cgi_print_all(atoi(PD("showall","0"))); |
| 900 | if( g.perm.Setup ){ |
| 901 | const char *zRedir = P("redirect"); |
| 902 | if( zRedir ) cgi_redirect(zRedir); |
| 903 | } |
| 904 |
+1
-1
| --- src/update.c | ||
| +++ src/update.c | ||
| @@ -575,11 +575,11 @@ | ||
| 575 | 575 | fossil_fatal("no such checkin: %s", revision); |
| 576 | 576 | } |
| 577 | 577 | pManifest = manifest_get(rid, CFTYPE_MANIFEST); |
| 578 | 578 | |
| 579 | 579 | if( pManifest ){ |
| 580 | - pFile = manifest_file_seek(pManifest, file); | |
| 580 | + pFile = manifest_file_find(pManifest, file); | |
| 581 | 581 | if( pFile ){ |
| 582 | 582 | rid = uuid_to_rid(pFile->zUuid, 0); |
| 583 | 583 | if( pIsExe ) *pIsExe = ( manifest_file_mperm(pFile)==PERM_EXE ); |
| 584 | 584 | if( pIsLink ) *pIsLink = ( manifest_file_mperm(pFile)==PERM_LNK ); |
| 585 | 585 | manifest_destroy(pManifest); |
| 586 | 586 |
| --- src/update.c | |
| +++ src/update.c | |
| @@ -575,11 +575,11 @@ | |
| 575 | fossil_fatal("no such checkin: %s", revision); |
| 576 | } |
| 577 | pManifest = manifest_get(rid, CFTYPE_MANIFEST); |
| 578 | |
| 579 | if( pManifest ){ |
| 580 | pFile = manifest_file_seek(pManifest, file); |
| 581 | if( pFile ){ |
| 582 | rid = uuid_to_rid(pFile->zUuid, 0); |
| 583 | if( pIsExe ) *pIsExe = ( manifest_file_mperm(pFile)==PERM_EXE ); |
| 584 | if( pIsLink ) *pIsLink = ( manifest_file_mperm(pFile)==PERM_LNK ); |
| 585 | manifest_destroy(pManifest); |
| 586 |
| --- src/update.c | |
| +++ src/update.c | |
| @@ -575,11 +575,11 @@ | |
| 575 | fossil_fatal("no such checkin: %s", revision); |
| 576 | } |
| 577 | pManifest = manifest_get(rid, CFTYPE_MANIFEST); |
| 578 | |
| 579 | if( pManifest ){ |
| 580 | pFile = manifest_file_find(pManifest, file); |
| 581 | if( pFile ){ |
| 582 | rid = uuid_to_rid(pFile->zUuid, 0); |
| 583 | if( pIsExe ) *pIsExe = ( manifest_file_mperm(pFile)==PERM_EXE ); |
| 584 | if( pIsLink ) *pIsLink = ( manifest_file_mperm(pFile)==PERM_LNK ); |
| 585 | manifest_destroy(pManifest); |
| 586 |
+21
-8
| --- src/xfer.c | ||
| +++ src/xfer.c | ||
| @@ -443,43 +443,56 @@ | ||
| 443 | 443 | const char *zDelta; |
| 444 | 444 | int szU; |
| 445 | 445 | int szC; |
| 446 | 446 | int rc; |
| 447 | 447 | int isPrivate; |
| 448 | + int srcIsPrivate; | |
| 448 | 449 | static Stmt q1; |
| 450 | + Blob fullContent; | |
| 449 | 451 | |
| 450 | 452 | isPrivate = content_is_private(rid); |
| 451 | 453 | if( isPrivate && pXfer->syncPrivate==0 ) return; |
| 452 | 454 | db_static_prepare(&q1, |
| 453 | - "SELECT uuid, size, content," | |
| 454 | - " (SELECT uuid FROM delta, blob" | |
| 455 | - " WHERE delta.rid=:rid AND delta.srcid=blob.rid)" | |
| 456 | - " FROM blob" | |
| 457 | - " WHERE rid=:rid" | |
| 458 | - " AND size>=0" | |
| 455 | + "SELECT uuid, size, content, delta.srcid IN private," | |
| 456 | + " (SELECT uuid FROM blob WHERE rid=delta.srcid)" | |
| 457 | + " FROM blob LEFT JOIN delta ON (blob.rid=delta.rid)" | |
| 458 | + " WHERE blob.rid=:rid" | |
| 459 | + " AND blob.size>=0" | |
| 459 | 460 | " AND NOT EXISTS(SELECT 1 FROM shun WHERE shun.uuid=blob.uuid)" |
| 460 | 461 | ); |
| 461 | 462 | db_bind_int(&q1, ":rid", rid); |
| 462 | 463 | rc = db_step(&q1); |
| 463 | 464 | if( rc==SQLITE_ROW ){ |
| 464 | 465 | zUuid = db_column_text(&q1, 0); |
| 465 | 466 | szU = db_column_int(&q1, 1); |
| 466 | 467 | szC = db_column_bytes(&q1, 2); |
| 467 | 468 | zContent = db_column_raw(&q1, 2); |
| 468 | - zDelta = db_column_text(&q1, 3); | |
| 469 | + srcIsPrivate = db_column_int(&q1, 3); | |
| 470 | + zDelta = db_column_text(&q1, 4); | |
| 469 | 471 | if( isPrivate ) blob_append(pXfer->pOut, "private\n", -1); |
| 470 | 472 | blob_appendf(pXfer->pOut, "cfile %s ", zUuid); |
| 471 | - if( zDelta ){ | |
| 473 | + if( !isPrivate && srcIsPrivate ){ | |
| 474 | + content_get(rid, &fullContent); | |
| 475 | + szU = blob_size(&fullContent); | |
| 476 | + blob_compress(&fullContent, &fullContent); | |
| 477 | + szC = blob_size(&fullContent); | |
| 478 | + zContent = blob_buffer(&fullContent); | |
| 479 | + zDelta = 0; | |
| 480 | + } | |
| 481 | + if( zDelta ){ | |
| 472 | 482 | blob_appendf(pXfer->pOut, "%s ", zDelta); |
| 473 | 483 | pXfer->nDeltaSent++; |
| 474 | 484 | }else{ |
| 475 | 485 | pXfer->nFileSent++; |
| 476 | 486 | } |
| 477 | 487 | blob_appendf(pXfer->pOut, "%d %d\n", szU, szC); |
| 478 | 488 | blob_append(pXfer->pOut, zContent, szC); |
| 479 | 489 | if( blob_buffer(pXfer->pOut)[blob_size(pXfer->pOut)-1]!='\n' ){ |
| 480 | 490 | blob_appendf(pXfer->pOut, "\n", 1); |
| 491 | + } | |
| 492 | + if( !isPrivate && srcIsPrivate ){ | |
| 493 | + blob_reset(&fullContent); | |
| 481 | 494 | } |
| 482 | 495 | } |
| 483 | 496 | db_reset(&q1); |
| 484 | 497 | } |
| 485 | 498 | |
| 486 | 499 |
| --- src/xfer.c | |
| +++ src/xfer.c | |
| @@ -443,43 +443,56 @@ | |
| 443 | const char *zDelta; |
| 444 | int szU; |
| 445 | int szC; |
| 446 | int rc; |
| 447 | int isPrivate; |
| 448 | static Stmt q1; |
| 449 | |
| 450 | isPrivate = content_is_private(rid); |
| 451 | if( isPrivate && pXfer->syncPrivate==0 ) return; |
| 452 | db_static_prepare(&q1, |
| 453 | "SELECT uuid, size, content," |
| 454 | " (SELECT uuid FROM delta, blob" |
| 455 | " WHERE delta.rid=:rid AND delta.srcid=blob.rid)" |
| 456 | " FROM blob" |
| 457 | " WHERE rid=:rid" |
| 458 | " AND size>=0" |
| 459 | " AND NOT EXISTS(SELECT 1 FROM shun WHERE shun.uuid=blob.uuid)" |
| 460 | ); |
| 461 | db_bind_int(&q1, ":rid", rid); |
| 462 | rc = db_step(&q1); |
| 463 | if( rc==SQLITE_ROW ){ |
| 464 | zUuid = db_column_text(&q1, 0); |
| 465 | szU = db_column_int(&q1, 1); |
| 466 | szC = db_column_bytes(&q1, 2); |
| 467 | zContent = db_column_raw(&q1, 2); |
| 468 | zDelta = db_column_text(&q1, 3); |
| 469 | if( isPrivate ) blob_append(pXfer->pOut, "private\n", -1); |
| 470 | blob_appendf(pXfer->pOut, "cfile %s ", zUuid); |
| 471 | if( zDelta ){ |
| 472 | blob_appendf(pXfer->pOut, "%s ", zDelta); |
| 473 | pXfer->nDeltaSent++; |
| 474 | }else{ |
| 475 | pXfer->nFileSent++; |
| 476 | } |
| 477 | blob_appendf(pXfer->pOut, "%d %d\n", szU, szC); |
| 478 | blob_append(pXfer->pOut, zContent, szC); |
| 479 | if( blob_buffer(pXfer->pOut)[blob_size(pXfer->pOut)-1]!='\n' ){ |
| 480 | blob_appendf(pXfer->pOut, "\n", 1); |
| 481 | } |
| 482 | } |
| 483 | db_reset(&q1); |
| 484 | } |
| 485 | |
| 486 |
| --- src/xfer.c | |
| +++ src/xfer.c | |
| @@ -443,43 +443,56 @@ | |
| 443 | const char *zDelta; |
| 444 | int szU; |
| 445 | int szC; |
| 446 | int rc; |
| 447 | int isPrivate; |
| 448 | int srcIsPrivate; |
| 449 | static Stmt q1; |
| 450 | Blob fullContent; |
| 451 | |
| 452 | isPrivate = content_is_private(rid); |
| 453 | if( isPrivate && pXfer->syncPrivate==0 ) return; |
| 454 | db_static_prepare(&q1, |
| 455 | "SELECT uuid, size, content, delta.srcid IN private," |
| 456 | " (SELECT uuid FROM blob WHERE rid=delta.srcid)" |
| 457 | " FROM blob LEFT JOIN delta ON (blob.rid=delta.rid)" |
| 458 | " WHERE blob.rid=:rid" |
| 459 | " AND blob.size>=0" |
| 460 | " AND NOT EXISTS(SELECT 1 FROM shun WHERE shun.uuid=blob.uuid)" |
| 461 | ); |
| 462 | db_bind_int(&q1, ":rid", rid); |
| 463 | rc = db_step(&q1); |
| 464 | if( rc==SQLITE_ROW ){ |
| 465 | zUuid = db_column_text(&q1, 0); |
| 466 | szU = db_column_int(&q1, 1); |
| 467 | szC = db_column_bytes(&q1, 2); |
| 468 | zContent = db_column_raw(&q1, 2); |
| 469 | srcIsPrivate = db_column_int(&q1, 3); |
| 470 | zDelta = db_column_text(&q1, 4); |
| 471 | if( isPrivate ) blob_append(pXfer->pOut, "private\n", -1); |
| 472 | blob_appendf(pXfer->pOut, "cfile %s ", zUuid); |
| 473 | if( !isPrivate && srcIsPrivate ){ |
| 474 | content_get(rid, &fullContent); |
| 475 | szU = blob_size(&fullContent); |
| 476 | blob_compress(&fullContent, &fullContent); |
| 477 | szC = blob_size(&fullContent); |
| 478 | zContent = blob_buffer(&fullContent); |
| 479 | zDelta = 0; |
| 480 | } |
| 481 | if( zDelta ){ |
| 482 | blob_appendf(pXfer->pOut, "%s ", zDelta); |
| 483 | pXfer->nDeltaSent++; |
| 484 | }else{ |
| 485 | pXfer->nFileSent++; |
| 486 | } |
| 487 | blob_appendf(pXfer->pOut, "%d %d\n", szU, szC); |
| 488 | blob_append(pXfer->pOut, zContent, szC); |
| 489 | if( blob_buffer(pXfer->pOut)[blob_size(pXfer->pOut)-1]!='\n' ){ |
| 490 | blob_appendf(pXfer->pOut, "\n", 1); |
| 491 | } |
| 492 | if( !isPrivate && srcIsPrivate ){ |
| 493 | blob_reset(&fullContent); |
| 494 | } |
| 495 | } |
| 496 | db_reset(&q1); |
| 497 | } |
| 498 | |
| 499 |
+25
| --- www/changes.wiki | ||
| +++ www/changes.wiki | ||
| @@ -1,6 +1,31 @@ | ||
| 1 | 1 | <title>Change Log</title> |
| 2 | + | |
| 3 | +<h2>Changes For Version 1.21 (2011-12-02)</h2> | |
| 4 | + * Added side-by-side diffs in the command-line interface | |
| 5 | + * Automatically enable hyperlinks if the UserAgent string in the | |
| 6 | + HTTP header suggests that the requestor is a human and not a bot. | |
| 7 | + * Show only commonly used commands with "fossil help". Use | |
| 8 | + "fossil help --all" to see the complete list now. | |
| 9 | + * Improvements to the "stash" command: (1) Stash all files, not just | |
| 10 | + those below the working directory. (2) Add the --detail option to | |
| 11 | + "list". (3) Confirm before "drop --all". (4) Add the "help" | |
| 12 | + subcommand. | |
| 13 | + * Add an Admin/Access setting to change the number of octets of the | |
| 14 | + IP address that are saved in login cookies - allowing this setting | |
| 15 | + to be changed to zero | |
| 16 | + * Promote the "test-md5sum" command to "md5sum". | |
| 17 | + * Added the "whatis" command. | |
| 18 | + * Stop showing the server-code in status outputs - it is no longer used | |
| 19 | + for anything. | |
| 20 | + * Added a compile-time option (--with-tcl) to build in the full | |
| 21 | + TCL interpreter to augment TH1. | |
| 22 | + * Merged the JSON branch into trunk. Disabled by default. Enabled | |
| 23 | + by a compile-time option. Probably it will be enabled by default | |
| 24 | + in some future release. | |
| 25 | + * Update to use SQLite version 3.7.9 plus the alignment fix for Sparc. | |
| 26 | + align | |
| 2 | 27 | |
| 3 | 28 | <h2>Changes For Version 1.20 (2011-10-21)</h2> |
| 4 | 29 | * Added side-by-side diffs in HTML interface. [0bde74ea1e] |
| 5 | 30 | * Added support for symlinks. (Controlled by "allow-symlinks" setting, |
| 6 | 31 | off by default). [e4f1c1fe95] |
| 7 | 32 |
| --- www/changes.wiki | |
| +++ www/changes.wiki | |
| @@ -1,6 +1,31 @@ | |
| 1 | <title>Change Log</title> |
| 2 | |
| 3 | <h2>Changes For Version 1.20 (2011-10-21)</h2> |
| 4 | * Added side-by-side diffs in HTML interface. [0bde74ea1e] |
| 5 | * Added support for symlinks. (Controlled by "allow-symlinks" setting, |
| 6 | off by default). [e4f1c1fe95] |
| 7 |
| --- www/changes.wiki | |
| +++ www/changes.wiki | |
| @@ -1,6 +1,31 @@ | |
| 1 | <title>Change Log</title> |
| 2 | |
| 3 | <h2>Changes For Version 1.21 (2011-12-02)</h2> |
| 4 | * Added side-by-side diffs in the command-line interface |
| 5 | * Automatically enable hyperlinks if the UserAgent string in the |
| 6 | HTTP header suggests that the requestor is a human and not a bot. |
| 7 | * Show only commonly used commands with "fossil help". Use |
| 8 | "fossil help --all" to see the complete list now. |
| 9 | * Improvements to the "stash" command: (1) Stash all files, not just |
| 10 | those below the working directory. (2) Add the --detail option to |
| 11 | "list". (3) Confirm before "drop --all". (4) Add the "help" |
| 12 | subcommand. |
| 13 | * Add an Admin/Access setting to change the number of octets of the |
| 14 | IP address that are saved in login cookies - allowing this setting |
| 15 | to be changed to zero |
| 16 | * Promote the "test-md5sum" command to "md5sum". |
| 17 | * Added the "whatis" command. |
| 18 | * Stop showing the server-code in status outputs - it is no longer used |
| 19 | for anything. |
| 20 | * Added a compile-time option (--with-tcl) to build in the full |
| 21 | TCL interpreter to augment TH1. |
| 22 | * Merged the JSON branch into trunk. Disabled by default. Enabled |
| 23 | by a compile-time option. Probably it will be enabled by default |
| 24 | in some future release. |
| 25 | * Update to use SQLite version 3.7.9 plus the alignment fix for Sparc. |
| 26 | align |
| 27 | |
| 28 | <h2>Changes For Version 1.20 (2011-10-21)</h2> |
| 29 | * Added side-by-side diffs in HTML interface. [0bde74ea1e] |
| 30 | * Added support for symlinks. (Controlled by "allow-symlinks" setting, |
| 31 | off by default). [e4f1c1fe95] |
| 32 |