Fossil

Check-in [4d392366]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:merge with latest trunk
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | mgagnon_fix
Files: files | file ages | folders
SHA1:4d39236638ccacfdad3d6a979f37dfb93ae333c4
User & Date: mgagnon 2011-12-08 02:05:13
Original User & Date: meeks 2011-12-08 02:05:13
Context
2012-01-22
22:02
merge with trunk check-in: e1c424cb user: mgagnon tags: mgagnon_fix
2011-12-08
02:05
merge with latest trunk check-in: 4d392366 user: mgagnon tags: mgagnon_fix
2011-12-06
00:09
The finfo command and the file browsing pages of the web UI now honor the case-sensitive option and merge filenames that differ only in case as requested. check-in: 9c90b0f0 user: drh tags: trunk
2011-11-11
12:13
Start a branch with fix to make work consistently a local checkout directly on root ("/"). check-in: 518e1f8d user: mgagnon tags: mgagnon_fix
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to VERSION.

1
1.20
|
1
1.21

Changes to ajax/js/whajaj.js.

101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
    
    FIXME: for keys in the form "name[]", build an array of results,
    like PHP does.
 
*/
WhAjaj.processUrlArgs = function(str) {
    if( 0 === arguments.length ) {
        if( (undefined === typeof window) ||
            !window.location ||
            !window.location.search )  return false;
        else str = (''+window.location.search).substring(1);
    }
    if( ! str ) return false;
    var args = {};
    var sp = str.split(/&+/);







|







101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
    
    FIXME: for keys in the form "name[]", build an array of results,
    like PHP does.
 
*/
WhAjaj.processUrlArgs = function(str) {
    if( 0 === arguments.length ) {
        if( ('undefined' === typeof window) ||
            !window.location ||
            !window.location.search )  return false;
        else str = (''+window.location.search).substring(1);
    }
    if( ! str ) return false;
    var args = {};
    var sp = str.split(/&+/);

Changes to auto.def.

85
86
87
88
89
90
91

92
93






94
95

96
97
98
99




100
101
102
103
104
105
106
107
108



109
110
111

112
113
114
115
116
117
118
}
if {![cc-check-includes zlib.h] || ![cc-check-function-in-lib inflateEnd z]} {
    user-error "zlib not found please install it or specify the location with --with-zlib"
}

set tclpath [opt-val with-tcl]
if {$tclpath ne ""} {

    if {$tclpath ne "1"} {
        cc-with [list -cflags [list -I$tclpath/include -L$tclpath/lib]]






    }
    if {![cc-check-includes tcl.h]} {

        user-error "Cannot find tcl.h"
    }
    foreach tlib {tcl8.6 tcl8.5 tcl notfound} {
        if {$tlib=="notfound"} {




            user-error "Cannot find a usable libtcl"
        }
        if {[cc-check-function-in-lib Tcl_CreateInterp $tlib]} {
            define-append LIBS -l$tlib
            break
        }
    }
    define FOSSIL_ENABLE_TCL
    if {$tclpath ne "1"} {



        define-append EXTRA_CFLAGS -I$tclpath/include
        define-append EXTRA_LDFLAGS -L$tclpath/lib
    }

}

# Helper for openssl checking
proc check-for-openssl {msg {cflags {}}} {
    msg-checking "Checking for $msg..."
    set rc 0
    msg-quiet cc-with [list -cflags $cflags -libs {-lssl -lcrypto}] {







>
|
<
>
>
>
>
>
>
|
<
>
|
|
<
<
>
>
>
>
|
|
<
<
<
|
<
<
<
>
>
>
|
|
|
>







85
86
87
88
89
90
91
92
93

94
95
96
97
98
99
100

101
102
103


104
105
106
107
108
109



110



111
112
113
114
115
116
117
118
119
120
121
122
123
124
}
if {![cc-check-includes zlib.h] || ![cc-check-function-in-lib inflateEnd z]} {
    user-error "zlib not found please install it or specify the location with --with-zlib"
}

set tclpath [opt-val with-tcl]
if {$tclpath ne ""} {
	# Note parse-tclconfig-sh is in autosetup/local.tcl
    if {$tclpath eq "1"} {

        # Use the system Tcl. Look in some likely places.
        array set tclconfig [parse-tclconfig-sh /usr /usr/local /usr/share /opt/local]
		set msg "on your system"
	} else {
        array set tclconfig [parse-tclconfig-sh $tclpath]
		set msg "at $tclpath"
	}

	if {![info exists tclconfig(TCL_INCLUDE_SPEC)]} {
		user-error "Cannot find Tcl $msg"
	}


	set cflags $tclconfig(TCL_INCLUDE_SPEC)
	set libs "$tclconfig(TCL_LIB_SPEC) $tclconfig(TCL_LIBS)"
	cc-with [list -cflags $cflags -libs $libs] {
		if {![cc-check-functions Tcl_CreateInterp]} {
			user-error "Cannot find a usable Tcl $msg"
		}



	}



	set version $tclconfig(TCL_VERSION)$tclconfig(TCL_PATCH_LEVEL)
	msg-result "Found Tcl $version at $tclconfig(TCL_PREFIX)"
	define-append LIBS $libs
	define-append EXTRA_CFLAGS $cflags
	define-append EXTRA_LDFLAGS $tclconfig(TCL_LD_FLAGS)

    define FOSSIL_ENABLE_TCL
}

# Helper for openssl checking
proc check-for-openssl {msg {cflags {}}} {
    msg-checking "Checking for $msg..."
    set rc 0
    msg-quiet cc-with [list -cflags $cflags -libs {-lssl -lcrypto}] {

Changes to autosetup/local.tcl.

1
2



























# For this project, disable the pager for --help
set useropts(nopager) 1





























>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# For this project, disable the pager for --help
set useropts(nopager) 1

# Searches for a usable Tcl (prefer 8.6, 8.5, 8.4) in the given paths
# Returns a dictionary of the contents of the tclConfig.sh file, or
# empty if not found
proc parse-tclconfig-sh {args} {
	foreach p $args {
		# Allow pointing directly to the path containing tclConfig.sh
		if {[file exists $p/tclConfig.sh]} {
			return [parse-tclconfig-sh-file $p/tclConfig.sh]
		}
		# Some systems allow for multiple versions
		foreach libpath {lib/tcl8.6 lib/tcl8.5 lib/tcl8.4 lib/tcl tcl lib}  {
			if {[file exists $p/$libpath/tclConfig.sh]} {
				return [parse-tclconfig-sh-file $p/$libpath/tclConfig.sh]
			}
		}
	}
}

proc parse-tclconfig-sh-file {filename} {
	foreach line [split [readfile $filename] \n] {
		if {[regexp {^(TCL_[^=]*)=(.*)$} $line -> name value]} {
			set tclconfig($name) [string trim $value ']
		}
	}
	return [array get tclconfig]
}

Changes to src/add.c.

335
336
337
338
339
340
341
342

343


344
345
346
347
348
349
350
351
352

353
354
355











356
357
358
359
360
361
362
** the case-sensitive setting is undefined, then case sensitivity
** defaults on for Mac and Windows and off for all other unix.
**
** The --case-sensitive BOOLEAN command-line option overrides any
** setting.
*/
int filenames_are_case_sensitive(void){
  int caseSensitive;




  if( zCaseSensitive ){
    caseSensitive = is_truth(zCaseSensitive);
  }else{
#if !defined(_WIN32) && !defined(__DARWIN__) && !defined(__APPLE__)
    caseSensitive = 1;
#else
    caseSensitive = 0;
#endif
    caseSensitive = db_get_boolean("case-sensitive",caseSensitive);

  }
  return caseSensitive;
}












/*
** COMMAND: addremove
**
** Usage: %fossil addremove ?OPTIONS?
**
** Do all necessary "add" and "rm" commands to synchronize the repository







|
>

>
>
|
|
|

|

|

|
>



>
>
>
>
>
>
>
>
>
>
>







335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
** the case-sensitive setting is undefined, then case sensitivity
** defaults on for Mac and Windows and off for all other unix.
**
** The --case-sensitive BOOLEAN command-line option overrides any
** setting.
*/
int filenames_are_case_sensitive(void){
  static int caseSensitive;
  static int once = 1;

  if( once ){
    once = 0;
    if( zCaseSensitive ){
      caseSensitive = is_truth(zCaseSensitive);
    }else{
#if !defined(_WIN32) && !defined(__DARWIN__) && !defined(__APPLE__)
      caseSensitive = 1;  /* Unix */
#else
      caseSensitive = 0;  /* Windows and Mac */
#endif
      caseSensitive = db_get_boolean("case-sensitive",caseSensitive);
    }
  }
  return caseSensitive;
}

/*
** Return one of two things:
**
**   ""                 (empty string) if filenames are case sensitive
**
**   "COLLATE nocase"   if filenames are not case sensitive.
*/
const char *filename_collation(void){
  return filenames_are_case_sensitive() ? "" : "COLLATE nocase";
}

/*
** COMMAND: addremove
**
** Usage: %fossil addremove ?OPTIONS?
**
** Do all necessary "add" and "rm" commands to synchronize the repository

Changes to src/browse.c.

194
195
196
197
198
199
200
201

202
203
204
205
206
207
208
...
229
230
231
232
233
234
235

236
237
238
239
240
241








242
243
244
245
246
247
248
  ** of all files and subdirectories in the zD[] directory.  
  **
  ** Subdirectory names begin with "/".  This causes them to sort
  ** first and it also gives us an easy way to distinguish files
  ** from directories in the loop that follows.
  */
  db_multi_exec(
     "CREATE TEMP TABLE localfiles(x UNIQUE NOT NULL, u);"

  );
  if( zCI ){
    Stmt ins;
    ManifestFile *pFile;
    ManifestFile *pPrev = 0;
    int nPrev = 0;
    int c;
................................................................................
      db_reset(&ins);
      pPrev = pFile;
      for(nPrev=0; (c=pPrev->zName[nD+nPrev]) && c!='/'; nPrev++){}
      if( c=='/' ) nPrev++;
    }
    db_finalize(&ins);
  }else if( zD ){

    db_multi_exec(
      "INSERT OR IGNORE INTO localfiles"
      " SELECT pathelement(name,%d), NULL FROM filename"
      "  WHERE name GLOB '%q/*'",
      nD, zD
    );








  }else{
    db_multi_exec(
      "INSERT OR IGNORE INTO localfiles"
      " SELECT pathelement(name,0), NULL FROM filename"
    );
  }








|
>







 







>
|
|
|
|
|
|
>
>
>
>
>
>
>
>







194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
...
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
  ** of all files and subdirectories in the zD[] directory.  
  **
  ** Subdirectory names begin with "/".  This causes them to sort
  ** first and it also gives us an easy way to distinguish files
  ** from directories in the loop that follows.
  */
  db_multi_exec(
     "CREATE TEMP TABLE localfiles(x UNIQUE NOT NULL %s, u);",
     filename_collation()
  );
  if( zCI ){
    Stmt ins;
    ManifestFile *pFile;
    ManifestFile *pPrev = 0;
    int nPrev = 0;
    int c;
................................................................................
      db_reset(&ins);
      pPrev = pFile;
      for(nPrev=0; (c=pPrev->zName[nD+nPrev]) && c!='/'; nPrev++){}
      if( c=='/' ) nPrev++;
    }
    db_finalize(&ins);
  }else if( zD ){
    if( filenames_are_case_sensitive() ){
      db_multi_exec(
        "INSERT OR IGNORE INTO localfiles"
        " SELECT pathelement(name,%d), NULL FROM filename"
        "  WHERE name GLOB '%q/*'",
        nD, zD
      );
    }else{
      db_multi_exec(
        "INSERT OR IGNORE INTO localfiles"
        " SELECT pathelement(name,%d), NULL FROM filename"
        "  WHERE name LIKE '%q/%%'",
        nD, zD
      );
    }
  }else{
    db_multi_exec(
      "INSERT OR IGNORE INTO localfiles"
      " SELECT pathelement(name,0), NULL FROM filename"
    );
  }

Changes to src/configure.c.

80
81
82
83
84
85
86

87



88
89
90
91
92
93
94
  { "logo-image",             CONFIGSET_SKIN },
  { "project-name",           CONFIGSET_PROJ },
  { "project-description",    CONFIGSET_PROJ },
  { "manifest",               CONFIGSET_PROJ },
  { "ignore-glob",            CONFIGSET_PROJ },
  { "crnl-glob",              CONFIGSET_PROJ },
  { "empty-dirs",             CONFIGSET_PROJ },

  { "index-page",             CONFIGSET_SKIN },



  { "timeline-block-markup",  CONFIGSET_SKIN },
  { "timeline-max-comment",   CONFIGSET_SKIN },
  { "ticket-table",           CONFIGSET_TKT  },
  { "ticket-common",          CONFIGSET_TKT  },
  { "ticket-newpage",         CONFIGSET_TKT  },
  { "ticket-viewpage",        CONFIGSET_TKT  },
  { "ticket-editpage",        CONFIGSET_TKT  },







>

>
>
>







80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
  { "logo-image",             CONFIGSET_SKIN },
  { "project-name",           CONFIGSET_PROJ },
  { "project-description",    CONFIGSET_PROJ },
  { "manifest",               CONFIGSET_PROJ },
  { "ignore-glob",            CONFIGSET_PROJ },
  { "crnl-glob",              CONFIGSET_PROJ },
  { "empty-dirs",             CONFIGSET_PROJ },
  { "allow-symlinks",         CONFIGSET_PROJ },
  { "index-page",             CONFIGSET_SKIN },
#ifdef FOSSIL_ENABLE_TCL
  { "tcl",                    CONFIGSET_SKIN|CONFIGSET_TKT },
#endif
  { "timeline-block-markup",  CONFIGSET_SKIN },
  { "timeline-max-comment",   CONFIGSET_SKIN },
  { "ticket-table",           CONFIGSET_TKT  },
  { "ticket-common",          CONFIGSET_TKT  },
  { "ticket-newpage",         CONFIGSET_TKT  },
  { "ticket-viewpage",        CONFIGSET_TKT  },
  { "ticket-editpage",        CONFIGSET_TKT  },

Changes to src/content.c.

826
827
828
829
830
831
832

833
834






















835
836
837
838
839
840
841
...
843
844
845
846
847
848
849
850
851

852
853
854
855
856

857
858
859
860
861
862
863

864
*/
void test_integrity(void){
  Stmt q;
  Blob content;
  Blob cksum;
  int n1 = 0;
  int n2 = 0;

  int total;
  db_find_and_open_repository(OPEN_ANY_SCHEMA, 2);






















  db_prepare(&q, "SELECT rid, uuid, size FROM blob ORDER BY rid");
  total = db_int(0, "SELECT max(rid) FROM blob");
  while( db_step(&q)==SQLITE_ROW ){
    int rid = db_column_int(&q, 0);
    const char *zUuid = db_column_text(&q, 1);
    int size = db_column_int(&q, 2);
    n1++;
................................................................................
    fflush(stdout);
    if( size<0 ){
      fossil_print("skip phantom %d %s\n", rid, zUuid);
      continue;  /* Ignore phantoms */
    }
    content_get(rid, &content);
    if( blob_size(&content)!=size ){
      fossil_warning("size mismatch on blob rid=%d:  %d vs %d",
                     rid, blob_size(&content), size);

    }
    sha1sum_blob(&content, &cksum);
    if( fossil_strcmp(blob_str(&cksum), zUuid)!=0 ){
      fossil_fatal("checksum mismatch on blob rid=%d: %s vs %s",
                   rid, blob_str(&cksum), zUuid);

    }
    blob_reset(&cksum);
    blob_reset(&content);
    n2++;
  }
  db_finalize(&q);
  fossil_print("%d non-phantom blobs (out of %d total) verified\n", n2, n1);

}







>


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







|
|
>



|
|
>






|
>

826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
...
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
*/
void test_integrity(void){
  Stmt q;
  Blob content;
  Blob cksum;
  int n1 = 0;
  int n2 = 0;
  int nErr = 0;
  int total;
  db_find_and_open_repository(OPEN_ANY_SCHEMA, 2);

  /* Make sure no public artifact is a delta from a private artifact */
  db_prepare(&q,
    "SELECT "
    "   rid, (SELECT uuid FROM blob WHERE rid=delta.rid),"
    "   srcid, (SELECT uuid FROM blob WHERE rid=delta.srcid)"
    "  FROM delta"
    " WHERE srcid in private AND rid NOT IN private"
  );
  while( db_step(&q)==SQLITE_ROW ){
    int rid = db_column_int(&q, 0);
    const char *zId = db_column_text(&q, 1);
    int srcid = db_column_int(&q, 2);
    const char *zSrc = db_column_text(&q, 3);
    fossil_print(
      "public artifact %S (%d) is a delta from private artifact %S (%d)\n",
      zId, rid, zSrc, srcid
    );
    nErr++;
  }
  db_finalize(&q);
    
  db_prepare(&q, "SELECT rid, uuid, size FROM blob ORDER BY rid");
  total = db_int(0, "SELECT max(rid) FROM blob");
  while( db_step(&q)==SQLITE_ROW ){
    int rid = db_column_int(&q, 0);
    const char *zUuid = db_column_text(&q, 1);
    int size = db_column_int(&q, 2);
    n1++;
................................................................................
    fflush(stdout);
    if( size<0 ){
      fossil_print("skip phantom %d %s\n", rid, zUuid);
      continue;  /* Ignore phantoms */
    }
    content_get(rid, &content);
    if( blob_size(&content)!=size ){
      fossil_print("size mismatch on artifact %d: wanted %d but got %d\n",
                     rid, size, blob_size(&content));
      nErr++;
    }
    sha1sum_blob(&content, &cksum);
    if( fossil_strcmp(blob_str(&cksum), zUuid)!=0 ){
      fossil_print("checksum mismatch on artifact %d: wanted %s but got %s\n",
                   rid, zUuid, blob_str(&cksum));
      nErr++;
    }
    blob_reset(&cksum);
    blob_reset(&content);
    n2++;
  }
  db_finalize(&q);
  fossil_print("%d non-phantom blobs (out of %d total) checked:  %d errors\n",
               n2, n1, nErr);
}

Changes to src/cson_amalgamation.c.

1394
1395
1396
1397
1398
1399
1400

1401
1402
1403
1404
1405
1406
1407
....
4948
4949
4950
4951
4952
4953
4954







































































4955
4956
4957
4958
4959
4960
4961
    }
}
/* end file parser/JSON_parser.c */
/* begin file ./cson.c */
#include <assert.h>
#include <stdlib.h> /* malloc()/free() */
#include <string.h>


#ifdef _MSC_VER
#   if _MSC_VER >= 1400 /* Visual Studio 2005 and up */
#     pragma warning( push )
#     pragma warning(disable:4996) /* unsecure sscanf (but snscanf() isn't in c89) */
#     pragma warning(disable:4244) /* complaining about data loss due
                                      to integer precision in the
................................................................................
            }
            else continue;
        }
        else continue;
    }
    return 0;
}








































































#if defined(__cplusplus)
} /*extern "C"*/
#endif

#undef MARKER
#undef CSON_OBJECT_PROPS_SORT







>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
....
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959
4960
4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
4974
4975
4976
4977
4978
4979
4980
4981
4982
4983
4984
4985
4986
4987
4988
4989
4990
4991
4992
4993
4994
4995
4996
4997
4998
4999
5000
5001
5002
5003
5004
5005
5006
5007
5008
5009
5010
5011
5012
5013
5014
5015
5016
5017
5018
5019
5020
5021
5022
5023
5024
5025
5026
5027
5028
5029
5030
5031
5032
5033
    }
}
/* end file parser/JSON_parser.c */
/* begin file ./cson.c */
#include <assert.h>
#include <stdlib.h> /* malloc()/free() */
#include <string.h>
#include <errno.h>

#ifdef _MSC_VER
#   if _MSC_VER >= 1400 /* Visual Studio 2005 and up */
#     pragma warning( push )
#     pragma warning(disable:4996) /* unsecure sscanf (but snscanf() isn't in c89) */
#     pragma warning(disable:4244) /* complaining about data loss due
                                      to integer precision in the
................................................................................
            }
            else continue;
        }
        else continue;
    }
    return 0;
}

static cson_value * cson_guess_arg_type(char const *arg){
    char * end = NULL;
    if(('0'<=*arg) && ('9'>=*arg)){
        goto do_string;
    }
    {
        long const val = strtol(arg, &end, 10);
        if(!*end){
            return cson_value_new_integer( (cson_int_t)val);
        }
    }
    {
        double const val = strtod(arg, &end);
        if(!*end){
            return cson_value_new_double(val);
        }
    }

    
    do_string:
    return cson_value_new_string(arg, strlen(arg));
}


int cson_parse_argv_flags( int argc, char const * const * argv,
                           cson_object ** tgt, unsigned int * count ){
    cson_object * o = NULL;
    int rc = 0;
    int i = 0;
    if(argc<1 || !argc || !tgt) return cson_rc.ArgError;
    o = *tgt ? *tgt : cson_new_object();
    if(count) *count = 0;
    for( i = 0; i < argc; ++i ){
        char const * arg = argv[i];
        char const * key = arg;
        char const * pos;
        cson_string * k = NULL;
        cson_value * v = NULL;
        if('-' != *arg) continue;
        while('-'==*key) ++key;
        if(!*key) continue;
        pos = key;
        while( *pos && ('=' != *pos)) ++pos;
        k = cson_new_string(key, pos-key);
        if(!k){
            rc = cson_rc.AllocError;
            break;
        }
        if(!*pos){ /** --key */
            v = cson_value_true();
        }else{ /** --key=...*/
            assert('=' == *pos);
            ++pos /*skip '='*/;
            v = *pos
                ? cson_guess_arg_type(pos)
                : cson_value_null();
        }
        if(0 != (rc=cson_object_set_s(o, k, v))){
            cson_free_string(k);
            cson_value_free(v);
            break;
        }
        else if(count) ++*count;
    }
    if(o != *tgt){
        if(rc) cson_free_object(o);
        else *tgt = o;
    }
    return rc;
}

#if defined(__cplusplus)
} /*extern "C"*/
#endif

#undef MARKER
#undef CSON_OBJECT_PROPS_SORT

Changes to src/cson_amalgamation.h.

2106
2107
2108
2109
2110
2111
2112






















































2113
2114
2115
2116
2117
2118
2119
....
2380
2381
2382
2383
2384
2385
2386
2387
2388
   Note that because arrays and objects might have more internal slots
   allocated than used, the alloced size of a container does not
   necessarily increase when a new item is inserted into it. An interesting
   side-effect of this is that when cson_clone()ing an array or object, the
   size of the clone can actually be less than the original.
*/
unsigned int cson_value_msize(cson_value const * v);























































/* LICENSE

This software's source code, including accompanying documentation and
demonstration applications, are licensed under the following
conditions...

................................................................................
#if defined(__cplusplus)
} /*extern "C"*/
#endif
    
#endif /* CSON_ENABLE_SQLITE3 */
#endif /* WANDERINGHORSE_NET_CSON_SQLITE3_H_INCLUDED */
/* end file include/wh/cson/cson_sqlite3.h */

#endif /* FOSSIL_ENABLE_JSON */







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







<

2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
....
2434
2435
2436
2437
2438
2439
2440

2441
   Note that because arrays and objects might have more internal slots
   allocated than used, the alloced size of a container does not
   necessarily increase when a new item is inserted into it. An interesting
   side-effect of this is that when cson_clone()ing an array or object, the
   size of the clone can actually be less than the original.
*/
unsigned int cson_value_msize(cson_value const * v);

/**
   Parses command-line-style arguments into a JSON object.

   It expects arguments to be in any of these forms, and any number
   of leading dashes are treated identically:

   --key : Treats key as a boolean with a true value.

   --key=VAL : Treats VAL as either a double, integer, or string.

   --key= : Treats key as a JSON null (not literal NULL) value.

   Arguments not starting with a dash are skipped.
   
   Each key/value pair is inserted into an object.  If a given key
   appears more than once then only the final entry is actually
   stored.

   argc and argv are expected to be values from main() (or similar,
   possibly adjusted to remove argv[0]).

   tgt must be either a pointer to NULL or a pointer to a
   client-provided Object. If (NULL==*tgt) then this function
   allocates a new object and on success it stores the new object in
   *tgt (it is owned by the caller). If (NULL!=*tgt) then it is
   assumed to be a properly allocated object. DO NOT pass a pointer to
   an unitialized pointer, as that will fool this function into
   thinking it is a valid object and Undefined Behaviour will ensue.

   If count is not NULL then the number of arugments parsed by this
   function are assigned to it. On error, count will be the number of
   options successfully parsed before the error was encountered.

   On success:

   - 0 is returned.

   - If (*tgt==NULL) then *tgt is assigned to a newly-allocated
   object, owned by the caller. Note that even if no arguments are
   parsed, the object is still created.

   On error:

   - non-0 is returned

   - If (*tgt==NULL) then it is not modified.

   - If (*tgt!=NULL) (i.e., the caller provides his own object) then
   it might contain partial results.
*/
int cson_parse_argv_flags( int argc, char const * const * argv,
                           cson_object ** tgt, unsigned int * count );


/* LICENSE

This software's source code, including accompanying documentation and
demonstration applications, are licensed under the following
conditions...

................................................................................
#if defined(__cplusplus)
} /*extern "C"*/
#endif
    
#endif /* CSON_ENABLE_SQLITE3 */
#endif /* WANDERINGHORSE_NET_CSON_SQLITE3_H_INCLUDED */
/* end file include/wh/cson/cson_sqlite3.h */

#endif /* FOSSIL_ENABLE_JSON */

Changes to src/finfo.c.

37
38
39
40
41
42
43
44
45
46
47
48
49
50
51


52
53
54
55

56
57
58
59
60
61
62
..
65
66
67
68
69
70
71
72

73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
...
111
112
113
114
115
116
117
118

119
120
121
122
123
124
125
...
142
143
144
145
146
147
148
149

150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
...
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
** a quick status and does not check for up-to-date-ness of the file.
**
** In the -p form, there's an optional flag "-r|--revision REVISION".
** The specified version (or the latest checked out version) is printed
** to stdout.
**
** Options:
**   --brief|-b          display a brief (one line / revision) summary
**   --limit N           display the first N changes
**   --log|-l            select log mode (the default)
**   --offset P          skip P changes
**   -p                  select print mode
**   --revision|-r R     print the given revision (or ckout, if none is given)
**                       to stdout (only in print mode)
**   -s                  select status mode (print a status indicator for FILE)


**
** See also: descendants, info, leaves
*/
void finfo_cmd(void){

  db_must_be_within_tree();
  if (find_option("status","s",0)) {
    Stmt q;
    Blob line;
    Blob fname;
    int vid;

................................................................................
    if( vid==0 ){
      fossil_panic("no checkout to finfo files in");
    }
    vfile_check_signature(vid, 1, 0);
    file_tree_name(g.argv[2], &fname, 1);
    db_prepare(&q,
        "SELECT pathname, deleted, rid, chnged, coalesce(origname!=pathname,0)"
        "  FROM vfile WHERE vfile.pathname=%B", &fname);

    blob_zero(&line);
    if ( db_step(&q)==SQLITE_ROW ) {
      Blob uuid;
      int isDeleted = db_column_int(&q, 1);
      int isNew = db_column_int(&q,2) == 0;
      int chnged = db_column_int(&q,3);
      int renamed = db_column_int(&q,4);

      blob_zero(&uuid);
      db_blob(&uuid,
           "SELECT uuid FROM blob, mlink, vfile WHERE "
           "blob.rid = mlink.mid AND mlink.fid = vfile.rid AND "
           "vfile.pathname=%B",
           &fname
      );
      if( isNew ){
        blob_appendf(&line, "new");
      }else if( isDeleted ){
        blob_appendf(&line, "deleted");
      }else if( renamed ){
        blob_appendf(&line, "renamed");
................................................................................
    Blob fname;
    const char *zRevision = find_option("revision", "r", 1);

    file_tree_name(g.argv[2], &fname, 1);
    if( zRevision ){
      historical_version_of_file(zRevision, blob_str(&fname), &record, 0, 0, 0);
    }else{
      int rid = db_int(0, "SELECT rid FROM vfile WHERE pathname=%B", &fname);

      if( rid==0 ){
        fossil_fatal("no history for file: %b", &fname);
      }
      content_get(rid, &record);
    }
    blob_write_to_file(&record, "-");
    blob_reset(&record);
................................................................................
    zOffset = find_option("offset",0,1);
    iOffset = zOffset ? atoi(zOffset) : 0;
    iBrief = (find_option("brief","b",0) == 0);
    if( g.argc!=3 ){
      usage("?-l|--log? ?-b|--brief? FILENAME");
    }
    file_tree_name(g.argv[2], &fname, 1);
    rid = db_int(0, "SELECT rid FROM vfile WHERE pathname=%B", &fname);

    if( rid==0 ){
      fossil_fatal("no history for file: %b", &fname);
    }
    zFilename = blob_str(&fname);
    db_prepare(&q,
        "SELECT b.uuid, ci.uuid, date(event.mtime,'localtime'),"
        "       coalesce(event.ecomment, event.comment),"
        "       coalesce(event.euser, event.user)"
        "  FROM mlink, blob b, event, blob ci, filename"
        " WHERE filename.name=%Q"
        "   AND mlink.fnid=filename.fnid"
        "   AND b.rid=mlink.fid"
        "   AND event.objid=mlink.mid"
        "   AND event.objid=ci.rid"
        " ORDER BY event.mtime DESC LIMIT %d OFFSET %d",
        zFilename, iLimit, iOffset
    );
    blob_zero(&line);
    if( iBrief ){
      fossil_print("History of %s\n", blob_str(&fname));
    }
    while( db_step(&q)==SQLITE_ROW ){
      const char *zFileUuid = db_column_text(&q, 0);
................................................................................
    " (SELECT uuid FROM blob WHERE rid=mlink.pid),"  /* Parent file uuid */
    " (SELECT uuid FROM blob WHERE rid=mlink.fid),"  /* Current file uuid */
    " (SELECT uuid FROM blob WHERE rid=mlink.mid),"  /* Check-in uuid */
    " event.bgcolor,"                                /* Background color */
    " (SELECT value FROM tagxref WHERE tagid=%d AND tagtype>0"
                                " AND tagxref.rid=mlink.mid)" /* Tags */
    "  FROM mlink, event"
    " WHERE mlink.fnid=(SELECT fnid FROM filename WHERE name=%Q)"
    "   AND event.objid=mlink.mid",
    TAG_BRANCH,
    zFilename
  );
  if( (zA = P("a"))!=0 ){
    blob_appendf(&sql, " AND event.mtime>=julianday('%q')", zA);
  }
  if( (zB = P("b"))!=0 ){
    blob_appendf(&sql, " AND event.mtime<=julianday('%q')", zB);
  }







|
|
|
|
|
|
|
|
>
>




>







 







|
>












|
|







 







|
>







 







|
>









|





|







 







|


|







37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
..
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
...
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
...
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
...
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
** a quick status and does not check for up-to-date-ness of the file.
**
** In the -p form, there's an optional flag "-r|--revision REVISION".
** The specified version (or the latest checked out version) is printed
** to stdout.
**
** Options:
**   --brief|-b           display a brief (one line / revision) summary
**   --limit N            display the first N changes
**   --log|-l             select log mode (the default)
**   --offset P           skip P changes
**   -p                   select print mode
**   --revision|-r R      print the given revision (or ckout, if none is given)
**                        to stdout (only in print mode)
**   -s                   select status mode (print a status indicator for FILE)
**   --case-sensitive B   Enable or disable case-sensitive filenames.  B is a
**                        boolean: "yes", "no", "true", "false", etc.
**
** See also: descendants, info, leaves
*/
void finfo_cmd(void){
  capture_case_sensitive_option();
  db_must_be_within_tree();
  if (find_option("status","s",0)) {
    Stmt q;
    Blob line;
    Blob fname;
    int vid;

................................................................................
    if( vid==0 ){
      fossil_panic("no checkout to finfo files in");
    }
    vfile_check_signature(vid, 1, 0);
    file_tree_name(g.argv[2], &fname, 1);
    db_prepare(&q,
        "SELECT pathname, deleted, rid, chnged, coalesce(origname!=pathname,0)"
        "  FROM vfile WHERE vfile.pathname=%B %s",
        &fname, filename_collation());
    blob_zero(&line);
    if ( db_step(&q)==SQLITE_ROW ) {
      Blob uuid;
      int isDeleted = db_column_int(&q, 1);
      int isNew = db_column_int(&q,2) == 0;
      int chnged = db_column_int(&q,3);
      int renamed = db_column_int(&q,4);

      blob_zero(&uuid);
      db_blob(&uuid,
           "SELECT uuid FROM blob, mlink, vfile WHERE "
           "blob.rid = mlink.mid AND mlink.fid = vfile.rid AND "
           "vfile.pathname=%B %s",
           &fname, filename_collation()
      );
      if( isNew ){
        blob_appendf(&line, "new");
      }else if( isDeleted ){
        blob_appendf(&line, "deleted");
      }else if( renamed ){
        blob_appendf(&line, "renamed");
................................................................................
    Blob fname;
    const char *zRevision = find_option("revision", "r", 1);

    file_tree_name(g.argv[2], &fname, 1);
    if( zRevision ){
      historical_version_of_file(zRevision, blob_str(&fname), &record, 0, 0, 0);
    }else{
      int rid = db_int(0, "SELECT rid FROM vfile WHERE pathname=%B %s",
                       &fname, filename_collation());
      if( rid==0 ){
        fossil_fatal("no history for file: %b", &fname);
      }
      content_get(rid, &record);
    }
    blob_write_to_file(&record, "-");
    blob_reset(&record);
................................................................................
    zOffset = find_option("offset",0,1);
    iOffset = zOffset ? atoi(zOffset) : 0;
    iBrief = (find_option("brief","b",0) == 0);
    if( g.argc!=3 ){
      usage("?-l|--log? ?-b|--brief? FILENAME");
    }
    file_tree_name(g.argv[2], &fname, 1);
    rid = db_int(0, "SELECT rid FROM vfile WHERE pathname=%B %s",
                 &fname, filename_collation());
    if( rid==0 ){
      fossil_fatal("no history for file: %b", &fname);
    }
    zFilename = blob_str(&fname);
    db_prepare(&q,
        "SELECT b.uuid, ci.uuid, date(event.mtime,'localtime'),"
        "       coalesce(event.ecomment, event.comment),"
        "       coalesce(event.euser, event.user)"
        "  FROM mlink, blob b, event, blob ci, filename"
        " WHERE filename.name=%Q %s"
        "   AND mlink.fnid=filename.fnid"
        "   AND b.rid=mlink.fid"
        "   AND event.objid=mlink.mid"
        "   AND event.objid=ci.rid"
        " ORDER BY event.mtime DESC LIMIT %d OFFSET %d",
        zFilename, filename_collation(), iLimit, iOffset
    );
    blob_zero(&line);
    if( iBrief ){
      fossil_print("History of %s\n", blob_str(&fname));
    }
    while( db_step(&q)==SQLITE_ROW ){
      const char *zFileUuid = db_column_text(&q, 0);
................................................................................
    " (SELECT uuid FROM blob WHERE rid=mlink.pid),"  /* Parent file uuid */
    " (SELECT uuid FROM blob WHERE rid=mlink.fid),"  /* Current file uuid */
    " (SELECT uuid FROM blob WHERE rid=mlink.mid),"  /* Check-in uuid */
    " event.bgcolor,"                                /* Background color */
    " (SELECT value FROM tagxref WHERE tagid=%d AND tagtype>0"
                                " AND tagxref.rid=mlink.mid)" /* Tags */
    "  FROM mlink, event"
    " WHERE mlink.fnid IN (SELECT fnid FROM filename WHERE name=%Q %s)"
    "   AND event.objid=mlink.mid",
    TAG_BRANCH,
    zFilename, filename_collation()
  );
  if( (zA = P("a"))!=0 ){
    blob_appendf(&sql, " AND event.mtime>=julianday('%q')", zA);
  }
  if( (zB = P("b"))!=0 ){
    blob_appendf(&sql, " AND event.mtime<=julianday('%q')", zB);
  }

Changes to src/http.c.

109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
    char *zEncoded = encode64(zCredentials, -1);
    blob_appendf(pHdr, "Authorization: Basic %s\r\n", zEncoded);
    fossil_free(zEncoded);
    fossil_free(zCredentials);
  }
  blob_appendf(pHdr, "Host: %s\r\n", g.urlHostname);
  blob_appendf(pHdr, "User-Agent: Fossil/" RELEASE_VERSION 
                     "-" MANIFEST_VERSION "\r\n");
  if( g.fHttpTrace ){
    blob_appendf(pHdr, "Content-Type: application/x-fossil-debug\r\n");
  }else{
    blob_appendf(pHdr, "Content-Type: application/x-fossil\r\n");
  }
  blob_appendf(pHdr, "Content-Length: %d\r\n\r\n", blob_size(pPayload));
}







|







109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
    char *zEncoded = encode64(zCredentials, -1);
    blob_appendf(pHdr, "Authorization: Basic %s\r\n", zEncoded);
    fossil_free(zEncoded);
    fossil_free(zCredentials);
  }
  blob_appendf(pHdr, "Host: %s\r\n", g.urlHostname);
  blob_appendf(pHdr, "User-Agent: Fossil/" RELEASE_VERSION 
                     " (" MANIFEST_DATE " " MANIFEST_VERSION ")\r\n");
  if( g.fHttpTrace ){
    blob_appendf(pHdr, "Content-Type: application/x-fossil-debug\r\n");
  }else{
    blob_appendf(pHdr, "Content-Type: application/x-fossil\r\n");
  }
  blob_appendf(pHdr, "Content-Length: %d\r\n\r\n", blob_size(pPayload));
}

Changes to src/json_login.c.

153
154
155
156
157
158
159
160
161
162
















163
164
165
166
167
168
169
      login_set_user_cookie(name, uid, &cookie);
    }
    payload = cson_value_new_object();
    po = cson_value_get_object(payload);
    cson_object_set(po, "authToken", json_new_string(cookie));
    free(cookie);
    cson_object_set(po, "name", json_new_string(name));
    cap = db_text(NULL, "SELECT cap FROM user WHERE login=%Q",name);
    cson_object_set(po, "capabilities", json_new_string(cap));
    free(cap);        
















    return payload;
  }
}

/*
** Impl of /json/logout.
**







|
|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
      login_set_user_cookie(name, uid, &cookie);
    }
    payload = cson_value_new_object();
    po = cson_value_get_object(payload);
    cson_object_set(po, "authToken", json_new_string(cookie));
    free(cookie);
    cson_object_set(po, "name", json_new_string(name));
    cap = db_text(NULL, "SELECT cap FROM user WHERE login=%Q", name);
    cson_object_set(po, "capabilities", cap ? json_new_string(cap) : cson_value_null() );
    free(cap);        
    cson_object_set(po, "loginCookieName", json_new_string( login_cookie_name() ) );
    /* TODO: add loginExpiryTime to the payload. To do this properly
       we "should" add an ([unsigned] int *) to
       login_set_user_cookie() and login_set_anon_cookie(), to which
       the expiry time is assigned. (Remember that JSON doesn't do
       unsigned int.)

       For non-anonymous users we could also simply query the
       user.cexpire db field after calling login_set_user_cookie(),
       but for anonymous we need to get the time when the cookie is
       set because anon does not get a db entry like normal users
       do. Anonyous cookies currently have a hard-coded lifetime in
       login_set_anon_cookie() (currently 6 hours), which we "should
       arguably" change to use the time configured for non-anonymous
       users (see login_set_user_cookie() for details).
    */
    return payload;
  }
}

/*
** Impl of /json/logout.
**

Changes to src/login.c.

350
351
352
353
354
355
356

















357
358
359
360
361
362
363
364
365
366
367
368



369
370





371
372
373
374
375
376
377
378
      /* At the time of this writing, cgi_replace_parameter() was
      ** "NULL-value-safe", and i'm hoping the NULL doesn't cause any
      ** downstream problems here. We could alternately use "" here.
      */
      ;
  }
}


















/*
** Look at the HTTP_USER_AGENT parameter and try to determine if the user agent
** is a manually operated browser or a bot.  When in doubt, assume a bot.  Return
** true if we believe the agent is a real person.
*/
static int isHuman(const char *zAgent){
  int i;
  if( zAgent==0 ) return 0;
  for(i=0; zAgent[i]; i++){
    if( zAgent[i]=='b' && memcmp(&zAgent[i],"bot",3)==0 ) return 0;
    if( zAgent[i]=='s' && memcmp(&zAgent[i],"spider",6)==0 ) return 0;



  }
  if( memcmp(zAgent, "Mozilla/", 8)==0 ){





    return atoi(&zAgent[8])>=4;
  }
  if( memcmp(zAgent, "Opera/", 6)==0 ) return 1;
  if( memcmp(zAgent, "Safari/", 7)==0 ) return 1;
  if( memcmp(zAgent, "Lynx/", 5)==0 ) return 1;
  return 0;
}








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



|
|



|

|
|
>
>
>


>
>
>
>
>
|







350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
      /* At the time of this writing, cgi_replace_parameter() was
      ** "NULL-value-safe", and i'm hoping the NULL doesn't cause any
      ** downstream problems here. We could alternately use "" here.
      */
      ;
  }
}

/*
** Return true if the prefix of zStr matches zPattern.  Return false if
** they are different.
**
** A lowercase character in zPattern will match either upper or lower
** case in zStr.  But an uppercase in zPattern will only match an
** uppercase in zStr.
*/
static int prefix_match(const char *zPattern, const char *zStr){
  int i;
  char c;
  for(i=0; (c = zPattern[i])!=0; i++){
    if( zStr[i]!=c && fossil_tolower(zStr[i])!=c ) return 0;
  }
  return 1;
}

/*
** Look at the HTTP_USER_AGENT parameter and try to determine if the user agent
** is a manually operated browser or a bot.  When in doubt, assume a bot.
** Return true if we believe the agent is a real person.
*/
static int isHuman(const char *zAgent){
  int i;
  if( zAgent==0 ) return 0;  /* If not UserAgent, the probably a bot */
  for(i=0; zAgent[i]; i++){
    if( prefix_match("bot", zAgent+i) ) return 0;
    if( prefix_match("spider", zAgent+i) ) return 0;
    if( prefix_match("crawl", zAgent+i) ) return 0;
    /* If a URI appears in the User-Agent, it is probably a bot */
    if( memcmp("http", zAgent+i,4)==0 ) return 0;
  }
  if( memcmp(zAgent, "Mozilla/", 8)==0 ){
    if( atoi(&zAgent[8])<4 ) return 0;  /* Many bots advertise as Mozilla/3 */
    if( strglob("*Firefox/[1-9]*", zAgent) ) return 1;
    if( strglob("*Chrome/[1-9]*", zAgent) ) return 1;
    if( strglob("*(compatible;?MSIE?[1-9]*", zAgent) ) return 1;
    if( strglob("*AppleWebKit/[1-9]*(KHTML*", zAgent) ) return 1;
    return 0;
  }
  if( memcmp(zAgent, "Opera/", 6)==0 ) return 1;
  if( memcmp(zAgent, "Safari/", 7)==0 ) return 1;
  if( memcmp(zAgent, "Lynx/", 5)==0 ) return 1;
  return 0;
}

Changes to src/manifest.c.

1221
1222
1223
1224
1225
1226
1227




























1228
1229
1230
1231
1232
1233
1234
  if( pFile && pFile->zUuid==0 ) return 0;
  if( pFile==0 && p->zBaseline ){
    fetch_baseline(p, 1);
    pFile = manifest_file_seek_base(p->pBaseline, zName);
  }
  return pFile;
}





























/*
** Add mlink table entries associated with manifest cid, pChild.  The
** parent manifest is pid, pParent.  One of either pChild or pParent
** will be NULL and it will be computed based on cid/pid.
**
** A single mlink entry is added for every file that changed content,







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
  if( pFile && pFile->zUuid==0 ) return 0;
  if( pFile==0 && p->zBaseline ){
    fetch_baseline(p, 1);
    pFile = manifest_file_seek_base(p->pBaseline, zName);
  }
  return pFile;
}

/*
** Look for a file in a manifest, taking the case-sensitive option
** into account.  If case-sensitive is off, then files in any case
** will match.
*/
ManifestFile *manifest_file_find(Manifest *p, const char *zName){
  int i, n;
  Manifest *pBase;
  if( filenames_are_case_sensitive() ){
    return manifest_file_seek(p, zName);
  }
  for(i=0; i<p->nFile; i++){
    if( fossil_stricmp(zName, p->aFile[i].zName)==0 ){
      return &p->aFile[i];
    }
  }
  if( p->zBaseline==0 ) return 0;
  fetch_baseline(p, 1);
  pBase = p->pBaseline;
  if( pBase==0 ) return 0;
  for(i=0; i<pBase->nFile; i++){
    if( fossil_stricmp(zName, p->aFile[i].zName)==0 ){
      return &p->aFile[i];
    }
  }
  return 0;
}

/*
** Add mlink table entries associated with manifest cid, pChild.  The
** parent manifest is pid, pParent.  One of either pChild or pParent
** will be NULL and it will be computed based on cid/pid.
**
** A single mlink entry is added for every file that changed content,

Changes to src/sqlite3.c.

647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
....
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
.....
82098
82099
82100
82101
82102
82103
82104
82105
82106
82107
82108
82109
82110
82111
82112
82113
82114
82115
82116
82117



82118
82119
82120
82121
82122
82123
82124
**
** See also: [sqlite3_libversion()],
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION        "3.7.9"
#define SQLITE_VERSION_NUMBER 3007009
#define SQLITE_SOURCE_ID      "2011-10-29 19:25:08 5b82ec6fbbd2f4195ad06dd911de3817373ad5bf"

/*
** CAPI3REF: Run-Time Library Version Numbers
** KEYWORDS: sqlite3_version, sqlite3_sourceid
**
** These interfaces provide the same information as the [SQLITE_VERSION],
** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros
................................................................................
** opcode as doing so may disrupt the operation of the specialized VFSes
** that do require it.  
**
** ^The [SQLITE_FCNTL_WIN32_AV_RETRY] opcode is used to configure automatic
** retry counts and intervals for certain disk I/O operations for the
** windows [VFS] in order to work to provide robustness against
** anti-virus programs.  By default, the windows VFS will retry file read,
** file write, and file delete opertions up to 10 times, with a delay
** of 25 milliseconds before the first retry and with the delay increasing
** by an additional 25 milliseconds with each subsequent retry.  This
** opcode allows those to values (10 retries and 25 milliseconds of delay)
** to be adjusted.  The values are changed for all database connections
** within the same process.  The argument is a pointer to an array of two
** integers where the first integer i the new retry count and the second
** integer is the delay.  If either integer is negative, then the setting
................................................................................

  /* 
  ** Allocate the index structure. 
  */
  nName = sqlite3Strlen30(zName);
  nCol = pList->nExpr;
  pIndex = sqlite3DbMallocZero(db, 
      sizeof(Index) +              /* Index structure  */
      sizeof(tRowcnt)*(nCol+1) +   /* Index.aiRowEst   */
      sizeof(int)*nCol +           /* Index.aiColumn   */
      sizeof(char *)*nCol +        /* Index.azColl     */
      sizeof(u8)*nCol +            /* Index.aSortOrder */
      nName + 1 +                  /* Index.zName      */
      nExtra                       /* Collation sequence names */
  );
  if( db->mallocFailed ){
    goto exit_create_index;
  }
  pIndex->aiRowEst = (tRowcnt*)(&pIndex[1]);
  pIndex->azColl = (char**)(&pIndex->aiRowEst[nCol+1]);



  pIndex->aiColumn = (int *)(&pIndex->azColl[nCol]);
  pIndex->aSortOrder = (u8 *)(&pIndex->aiColumn[nCol]);
  pIndex->zName = (char *)(&pIndex->aSortOrder[nCol]);
  zExtra = (char *)(&pIndex->zName[nName+1]);
  memcpy(pIndex->zName, zName, nName+1);
  pIndex->pTable = pTab;
  pIndex->nColumn = pList->nExpr;







|







 







|







 







|
|
|
|
|
|
|





|
>
>
>







647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
....
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
.....
82098
82099
82100
82101
82102
82103
82104
82105
82106
82107
82108
82109
82110
82111
82112
82113
82114
82115
82116
82117
82118
82119
82120
82121
82122
82123
82124
82125
82126
82127
**
** See also: [sqlite3_libversion()],
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION        "3.7.9"
#define SQLITE_VERSION_NUMBER 3007009
#define SQLITE_SOURCE_ID      "2011-11-14 02:53:54 54cc11981127b52145e39f551d958580b1d45169"

/*
** CAPI3REF: Run-Time Library Version Numbers
** KEYWORDS: sqlite3_version, sqlite3_sourceid
**
** These interfaces provide the same information as the [SQLITE_VERSION],
** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros
................................................................................
** opcode as doing so may disrupt the operation of the specialized VFSes
** that do require it.  
**
** ^The [SQLITE_FCNTL_WIN32_AV_RETRY] opcode is used to configure automatic
** retry counts and intervals for certain disk I/O operations for the
** windows [VFS] in order to work to provide robustness against
** anti-virus programs.  By default, the windows VFS will retry file read,
** file write, and file delete operations up to 10 times, with a delay
** of 25 milliseconds before the first retry and with the delay increasing
** by an additional 25 milliseconds with each subsequent retry.  This
** opcode allows those to values (10 retries and 25 milliseconds of delay)
** to be adjusted.  The values are changed for all database connections
** within the same process.  The argument is a pointer to an array of two
** integers where the first integer i the new retry count and the second
** integer is the delay.  If either integer is negative, then the setting
................................................................................

  /* 
  ** Allocate the index structure. 
  */
  nName = sqlite3Strlen30(zName);
  nCol = pList->nExpr;
  pIndex = sqlite3DbMallocZero(db, 
      sizeof(Index) +                      /* Index structure  */
      ROUND8(sizeof(tRowcnt)*(nCol+1)) +   /* Index.aiRowEst   */
      sizeof(char *)*nCol +                /* Index.azColl     */
      sizeof(int)*nCol +                   /* Index.aiColumn   */
      sizeof(u8)*nCol +                    /* Index.aSortOrder */
      nName + 1 +                          /* Index.zName      */
      nExtra                               /* Collation sequence names */
  );
  if( db->mallocFailed ){
    goto exit_create_index;
  }
  pIndex->aiRowEst = (tRowcnt*)(&pIndex[1]);
  pIndex->azColl = (char**)
     ((char*)pIndex->aiRowEst + ROUND8(sizeof(tRowcnt)*nCol+1));
  assert( EIGHT_BYTE_ALIGNMENT(pIndex->aiRowEst) );
  assert( EIGHT_BYTE_ALIGNMENT(pIndex->azColl) );
  pIndex->aiColumn = (int *)(&pIndex->azColl[nCol]);
  pIndex->aSortOrder = (u8 *)(&pIndex->aiColumn[nCol]);
  pIndex->zName = (char *)(&pIndex->aSortOrder[nCol]);
  zExtra = (char *)(&pIndex->zName[nName+1]);
  memcpy(pIndex->zName, zName, nName+1);
  pIndex->pTable = pTab;
  pIndex->nColumn = pList->nExpr;

Changes to src/sqlite3.h.

105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
...
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
**
** See also: [sqlite3_libversion()],
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION        "3.7.9"
#define SQLITE_VERSION_NUMBER 3007009
#define SQLITE_SOURCE_ID      "2011-10-29 19:25:08 5b82ec6fbbd2f4195ad06dd911de3817373ad5bf"

/*
** CAPI3REF: Run-Time Library Version Numbers
** KEYWORDS: sqlite3_version, sqlite3_sourceid
**
** These interfaces provide the same information as the [SQLITE_VERSION],
** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros
................................................................................
** opcode as doing so may disrupt the operation of the specialized VFSes
** that do require it.  
**
** ^The [SQLITE_FCNTL_WIN32_AV_RETRY] opcode is used to configure automatic
** retry counts and intervals for certain disk I/O operations for the
** windows [VFS] in order to work to provide robustness against
** anti-virus programs.  By default, the windows VFS will retry file read,
** file write, and file delete opertions up to 10 times, with a delay
** of 25 milliseconds before the first retry and with the delay increasing
** by an additional 25 milliseconds with each subsequent retry.  This
** opcode allows those to values (10 retries and 25 milliseconds of delay)
** to be adjusted.  The values are changed for all database connections
** within the same process.  The argument is a pointer to an array of two
** integers where the first integer i the new retry count and the second
** integer is the delay.  If either integer is negative, then the setting







|







 







|







105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
...
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
**
** See also: [sqlite3_libversion()],
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION        "3.7.9"
#define SQLITE_VERSION_NUMBER 3007009
#define SQLITE_SOURCE_ID      "2011-11-14 02:53:54 54cc11981127b52145e39f551d958580b1d45169"

/*
** CAPI3REF: Run-Time Library Version Numbers
** KEYWORDS: sqlite3_version, sqlite3_sourceid
**
** These interfaces provide the same information as the [SQLITE_VERSION],
** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros
................................................................................
** opcode as doing so may disrupt the operation of the specialized VFSes
** that do require it.  
**
** ^The [SQLITE_FCNTL_WIN32_AV_RETRY] opcode is used to configure automatic
** retry counts and intervals for certain disk I/O operations for the
** windows [VFS] in order to work to provide robustness against
** anti-virus programs.  By default, the windows VFS will retry file read,
** file write, and file delete operations up to 10 times, with a delay
** of 25 milliseconds before the first retry and with the delay increasing
** by an additional 25 milliseconds with each subsequent retry.  This
** opcode allows those to values (10 retries and 25 milliseconds of delay)
** to be adjusted.  The values are changed for all database connections
** within the same process.  The argument is a pointer to an array of two
** integers where the first integer i the new retry count and the second
** integer is the delay.  If either integer is negative, then the setting

Changes to src/style.c.

891
892
893
894
895
896
897

898
899
900
901
902
903
904
    if( login_has_capability(&c, 1) ) zCap[i++] = c;
  }
  zCap[i] = 0;
  @ g.userUid = %d(g.userUid)<br />
  @ g.zLogin = %h(g.zLogin)<br />
  @ capabilities = %s(zCap)<br />
  @ <hr>

  cgi_print_all(atoi(PD("showall","0")));
  if( g.perm.Setup ){
    const char *zRedir = P("redirect");
    if( zRedir ) cgi_redirect(zRedir);
  }
  style_footer();
}







>







891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
    if( login_has_capability(&c, 1) ) zCap[i++] = c;
  }
  zCap[i] = 0;
  @ g.userUid = %d(g.userUid)<br />
  @ g.zLogin = %h(g.zLogin)<br />
  @ capabilities = %s(zCap)<br />
  @ <hr>
  P("HTTP_USER_AGENT");
  cgi_print_all(atoi(PD("showall","0")));
  if( g.perm.Setup ){
    const char *zRedir = P("redirect");
    if( zRedir ) cgi_redirect(zRedir);
  }
  style_footer();
}

Changes to src/update.c.

573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
  if( !is_a_version(rid) ){
    if( errCode>0 ) return errCode;
    fossil_fatal("no such checkin: %s", revision);
  }
  pManifest = manifest_get(rid, CFTYPE_MANIFEST);
  
  if( pManifest ){
    pFile = manifest_file_seek(pManifest, file);
    if( pFile ){
      rid = uuid_to_rid(pFile->zUuid, 0);
      if( pIsExe ) *pIsExe = ( manifest_file_mperm(pFile)==PERM_EXE );
      if( pIsLink ) *pIsLink = ( manifest_file_mperm(pFile)==PERM_LNK );
      manifest_destroy(pManifest);
      return content_get(rid, content);
    }







|







573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
  if( !is_a_version(rid) ){
    if( errCode>0 ) return errCode;
    fossil_fatal("no such checkin: %s", revision);
  }
  pManifest = manifest_get(rid, CFTYPE_MANIFEST);
  
  if( pManifest ){
    pFile = manifest_file_find(pManifest, file);
    if( pFile ){
      rid = uuid_to_rid(pFile->zUuid, 0);
      if( pIsExe ) *pIsExe = ( manifest_file_mperm(pFile)==PERM_EXE );
      if( pIsLink ) *pIsLink = ( manifest_file_mperm(pFile)==PERM_LNK );
      manifest_destroy(pManifest);
      return content_get(rid, content);
    }

Changes to src/xfer.c.

441
442
443
444
445
446
447

448

449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467

468
469
470








471
472
473
474
475
476
477
478
479
480



481
482
483
484
485
486
487
  const char *zContent;
  const char *zUuid;
  const char *zDelta;
  int szU;
  int szC;
  int rc;
  int isPrivate;

  static Stmt q1;


  isPrivate = content_is_private(rid);
  if( isPrivate && pXfer->syncPrivate==0 ) return;
  db_static_prepare(&q1,
    "SELECT uuid, size, content,"
         "  (SELECT uuid FROM delta, blob"
         "    WHERE delta.rid=:rid AND delta.srcid=blob.rid)"
    " FROM blob"
    " WHERE rid=:rid"
    "   AND size>=0"
    "   AND NOT EXISTS(SELECT 1 FROM shun WHERE shun.uuid=blob.uuid)"
  );
  db_bind_int(&q1, ":rid", rid);
  rc = db_step(&q1);
  if( rc==SQLITE_ROW ){
    zUuid = db_column_text(&q1, 0);
    szU = db_column_int(&q1, 1);
    szC = db_column_bytes(&q1, 2);
    zContent = db_column_raw(&q1, 2);

    zDelta = db_column_text(&q1, 3);
    if( isPrivate ) blob_append(pXfer->pOut, "private\n", -1);
    blob_appendf(pXfer->pOut, "cfile %s ", zUuid);








     if( zDelta ){
      blob_appendf(pXfer->pOut, "%s ", zDelta);
      pXfer->nDeltaSent++;
    }else{
      pXfer->nFileSent++;
    }
    blob_appendf(pXfer->pOut, "%d %d\n", szU, szC);
    blob_append(pXfer->pOut, zContent, szC);
    if( blob_buffer(pXfer->pOut)[blob_size(pXfer->pOut)-1]!='\n' ){
      blob_appendf(pXfer->pOut, "\n", 1);



    }
  }
  db_reset(&q1);
}

/*
** Send a gimme message for every phantom.







>

>




|
|
|
<
|
|









>
|


>
>
>
>
>
>
>
>
|









>
>
>







441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457

458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
  const char *zContent;
  const char *zUuid;
  const char *zDelta;
  int szU;
  int szC;
  int rc;
  int isPrivate;
  int srcIsPrivate;
  static Stmt q1;
  Blob fullContent;

  isPrivate = content_is_private(rid);
  if( isPrivate && pXfer->syncPrivate==0 ) return;
  db_static_prepare(&q1,
    "SELECT uuid, size, content, delta.srcid IN private,"
         "  (SELECT uuid FROM blob WHERE rid=delta.srcid)"
    " FROM blob LEFT JOIN delta ON (blob.rid=delta.rid)"

    " WHERE blob.rid=:rid"
    "   AND blob.size>=0"
    "   AND NOT EXISTS(SELECT 1 FROM shun WHERE shun.uuid=blob.uuid)"
  );
  db_bind_int(&q1, ":rid", rid);
  rc = db_step(&q1);
  if( rc==SQLITE_ROW ){
    zUuid = db_column_text(&q1, 0);
    szU = db_column_int(&q1, 1);
    szC = db_column_bytes(&q1, 2);
    zContent = db_column_raw(&q1, 2);
    srcIsPrivate = db_column_int(&q1, 3);
    zDelta = db_column_text(&q1, 4);
    if( isPrivate ) blob_append(pXfer->pOut, "private\n", -1);
    blob_appendf(pXfer->pOut, "cfile %s ", zUuid);
    if( !isPrivate && srcIsPrivate ){
      content_get(rid, &fullContent);
      szU = blob_size(&fullContent);
      blob_compress(&fullContent, &fullContent);
      szC = blob_size(&fullContent);
      zContent = blob_buffer(&fullContent);
      zDelta = 0;
    }
    if( zDelta ){
      blob_appendf(pXfer->pOut, "%s ", zDelta);
      pXfer->nDeltaSent++;
    }else{
      pXfer->nFileSent++;
    }
    blob_appendf(pXfer->pOut, "%d %d\n", szU, szC);
    blob_append(pXfer->pOut, zContent, szC);
    if( blob_buffer(pXfer->pOut)[blob_size(pXfer->pOut)-1]!='\n' ){
      blob_appendf(pXfer->pOut, "\n", 1);
    }
    if( !isPrivate && srcIsPrivate ){
      blob_reset(&fullContent);
    }
  }
  db_reset(&q1);
}

/*
** Send a gimme message for every phantom.

Changes to www/changes.wiki.

1

























2
3
4
5
6
7
8
<title>Change Log</title>


























<h2>Changes For Version 1.20 (2011-10-21)</h2>
  *  Added side-by-side diffs in HTML interface. [0bde74ea1e]
  *  Added support for symlinks. (Controlled by "allow-symlinks" setting,
     off by default). [e4f1c1fe95]
  *  Fixed CLI annotate to show the proper file version in case there
     are multiple equal versions in history. [e161670939]

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<title>Change Log</title>

<h2>Changes For Version 1.21 (2011-12-02)</h2>
  *  Added side-by-side diffs in the command-line interface
  *  Automatically enable hyperlinks if the UserAgent string in the 
     HTTP header suggests that the requestor is a human and not a bot.
  *  Show only commonly used commands with "fossil help".  Use
     "fossil help --all" to see the complete list now.
  *  Improvements to the "stash" command:  (1) Stash all files, not just 
     those below the working directory. (2) Add the --detail option to 
     "list". (3) Confirm before "drop --all". (4) Add the "help" 
     subcommand.
  *  Add an Admin/Access setting to change the number of octets of the
     IP address that are saved in login cookies - allowing this setting
     to be changed to zero
  *  Promote the "test-md5sum" command to "md5sum".
  *  Added the "whatis" command.
  *  Stop showing the server-code in status outputs - it is no longer used
     for anything.
  *  Added a compile-time option (--with-tcl) to build in the full
     TCL interpreter to augment TH1.
  *  Merged the JSON branch into trunk.  Disabled by default.  Enabled
     by a compile-time option.  Probably it will be enabled by default
     in some future release.
  *  Update to use SQLite version 3.7.9 plus the alignment fix for Sparc.
     align

<h2>Changes For Version 1.20 (2011-10-21)</h2>
  *  Added side-by-side diffs in HTML interface. [0bde74ea1e]
  *  Added support for symlinks. (Controlled by "allow-symlinks" setting,
     off by default). [e4f1c1fe95]
  *  Fixed CLI annotate to show the proper file version in case there
     are multiple equal versions in history. [e161670939]