Fossil

Check-in [34359c3ad1]
Login

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

Overview
Comment:merged in trunk [272e304d3f].
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | json-multitag-test | json
Files: files | file ages | folders
SHA1: 34359c3ad1324acc56df349be331e221640d1da3
User & Date: stephan 2011-11-04 17:24:36.659
Context
2011-11-04
18:48
/json/user/save now allows mixing GET/CLI and POST.payload data sources. check-in: 92b163a069 user: json-demo tags: json-multitag-test, json
17:24
merged in trunk [272e304d3f]. check-in: 34359c3ad1 user: stephan tags: json-multitag-test, json
17:13
minor cleanup to the last commit, added a TODO note. check-in: 14ed707067 user: stephan tags: json-multitag-test, json
15:40
No longer display the server-code in info outputs as the server-code is no longer used for anything. Begin recording the location of local checkouts in the ~/.fossil database. check-in: 272e304d3f user: drh tags: trunk
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/add.c.
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272

  add_files_in_sfile(vid, caseSensitive);
  db_end_transaction(0);
}

/*
** COMMAND: rm
** COMMAND: delete
**
** Usage: %fossil rm FILE1 ?FILE2 ...?
**    or: %fossil delete FILE1 ?FILE2 ...?
**
** Remove one or more files or directories from the repository.
**
** This command does NOT remove the files from disk.  It just marks the







|







258
259
260
261
262
263
264
265
266
267
268
269
270
271
272

  add_files_in_sfile(vid, caseSensitive);
  db_end_transaction(0);
}

/*
** COMMAND: rm
** COMMAND: delete*
**
** Usage: %fossil rm FILE1 ?FILE2 ...?
**    or: %fossil delete FILE1 ?FILE2 ...?
**
** Remove one or more files or directories from the repository.
**
** This command does NOT remove the files from disk.  It just marks the
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
    "UPDATE vfile SET pathname='%s' WHERE pathname='%s' AND vid=%d",
    zNew, zOrig, vid
  );
}

/*
** COMMAND: mv
** COMMAND: rename
**
** Usage: %fossil mv|rename OLDNAME NEWNAME
**    or: %fossil mv|rename OLDNAME... DIR
**
** Move or rename one or more files or directories within the repository tree.
** You can either rename a file or directory or move it to another subdirectory.
**







|







471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
    "UPDATE vfile SET pathname='%s' WHERE pathname='%s' AND vid=%d",
    zNew, zOrig, vid
  );
}

/*
** COMMAND: mv
** COMMAND: rename*
**
** Usage: %fossil mv|rename OLDNAME NEWNAME
**    or: %fossil mv|rename OLDNAME... DIR
**
** Move or rename one or more files or directories within the repository tree.
** You can either rename a file or directory or move it to another subdirectory.
**
Changes to src/blob.c.
764
765
766
767
768
769
770




771






772


773
774
775
776
777
778
779
** Return the number of bytes written.
*/
int blob_write_to_file(Blob *pBlob, const char *zFilename){
  FILE *out;
  int wrote;

  if( zFilename[0]==0 || (zFilename[0]=='-' && zFilename[1]==0) ){




    fossil_puts(blob_str(pBlob), 0);






    return blob_size(pBlob);


  }else{
    int i, nName;
    char *zName, zBuf[1000];

    nName = strlen(zFilename);
    if( nName>=sizeof(zBuf) ){
      zName = mprintf("%s", zFilename);







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







764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
** Return the number of bytes written.
*/
int blob_write_to_file(Blob *pBlob, const char *zFilename){
  FILE *out;
  int wrote;

  if( zFilename[0]==0 || (zFilename[0]=='-' && zFilename[1]==0) ){
    int n;
#if defined(_WIN32)
    if( _isatty(fileno(stdout)) ){
      char *z;
      z = fossil_utf8_to_console(blob_str(pBlob));
      n = strlen(z);
      fwrite(z, 1, n, stdout);
      free(z);
      return n;
    }
#endif
    n = blob_size(pBlob);
    fwrite(blob_buffer(pBlob), 1, n, stdout);
    return n;
  }else{
    int i, nName;
    char *zName, zBuf[1000];

    nName = strlen(zFilename);
    if( nName>=sizeof(zBuf) ){
      zName = mprintf("%s", zFilename);
Changes to src/browse.c.
247
248
249
250
251
252
253

254
255
256
257
258
259
260
  }

  /* Generate a multi-column table listing the contents of zD[]
  ** directory.
  */
  mxLen = db_int(12, "SELECT max(length(x)) FROM localfiles /*scan*/");
  cnt = db_int(0, "SELECT count(*) FROM localfiles /*scan*/");

  nCol = 100/mxLen;
  if( nCol<1 ) nCol = 1;
  if( nCol>5 ) nCol = 5;
  nRow = (cnt+nCol-1)/nCol;
  db_prepare(&q, "SELECT x, u FROM localfiles ORDER BY x /*scan*/");
  @ <table class="browser"><tr><td class="browser"><ul class="browser">
  i = 0;







>







247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
  }

  /* Generate a multi-column table listing the contents of zD[]
  ** directory.
  */
  mxLen = db_int(12, "SELECT max(length(x)) FROM localfiles /*scan*/");
  cnt = db_int(0, "SELECT count(*) FROM localfiles /*scan*/");
  if( mxLen<12 ) mxLen = 12;
  nCol = 100/mxLen;
  if( nCol<1 ) nCol = 1;
  if( nCol>5 ) nCol = 5;
  nRow = (cnt+nCol-1)/nCol;
  db_prepare(&q, "SELECT x, u FROM localfiles ORDER BY x /*scan*/");
  @ <table class="browser"><tr><td class="browser"><ul class="browser">
  i = 0;
Changes to src/checkin.c.
180
181
182
183
184
185
186
187
188
189
190
191

192
193
194
195
196
197
198
*/
void status_cmd(void){
  int vid;
  db_must_be_within_tree();
       /* 012345678901234 */
  fossil_print("repository:   %s\n", db_lget("repository",""));
  fossil_print("local-root:   %s\n", g.zLocalRoot);
  fossil_print("server-code:  %s\n", db_get("server-code", ""));
  vid = db_lget_int("checkout", 0);
  if( vid ){
    show_common_info(vid, "checkout:", 1, 1);
  }

  changes_cmd();
}

/*
** COMMAND: ls
**
** Usage: %fossil ls ?OPTIONS?







<




>







180
181
182
183
184
185
186

187
188
189
190
191
192
193
194
195
196
197
198
*/
void status_cmd(void){
  int vid;
  db_must_be_within_tree();
       /* 012345678901234 */
  fossil_print("repository:   %s\n", db_lget("repository",""));
  fossil_print("local-root:   %s\n", g.zLocalRoot);

  vid = db_lget_int("checkout", 0);
  if( vid ){
    show_common_info(vid, "checkout:", 1, 1);
  }
  db_record_repository_filename(0);
  changes_cmd();
}

/*
** COMMAND: ls
**
** Usage: %fossil ls ?OPTIONS?
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
    }
    blob_reset(&ans);
    blob_reset(&fname);
  }
}

/*
** COMMAND: ci
** COMMAND: commit
**
** Usage: %fossil commit ?OPTIONS? ?FILE...?
**
** Create a new version containing all of the changes in the current
** checkout.  You will be prompted to enter a check-in comment unless
** the comment has been specified on the command-line using "-m" or a 







|







823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
    }
    blob_reset(&ans);
    blob_reset(&fname);
  }
}

/*
** COMMAND: ci*
** COMMAND: commit
**
** Usage: %fossil commit ?OPTIONS? ?FILE...?
**
** Create a new version containing all of the changes in the current
** checkout.  You will be prompted to enter a check-in comment unless
** the comment has been specified on the command-line using "-m" or a 
Changes to src/checkout.c.
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
      free(zManFile);
    }
  }
    
}

/*
** COMMAND: checkout
** COMMAND: co
**
** Usage: %fossil checkout ?VERSION | --latest? ?OPTIONS?
**    or: %fossil co ?VERSION | --latest? ?OPTIONS?
**
** Check out a version specified on the command-line.  This command
** will abort if there are edited files in the current checkout unless
** the --force option appears on the command-line.  The --keep option







|
|







159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
      free(zManFile);
    }
  }
    
}

/*
** COMMAND: checkout*
** COMMAND: co*
**
** Usage: %fossil checkout ?VERSION | --latest? ?OPTIONS?
**    or: %fossil co ?VERSION | --latest? ?OPTIONS?
**
** Check out a version specified on the command-line.  This command
** will abort if there are edited files in the current checkout unless
** the --force option appears on the command-line.  The --keep option
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
      file_delete(z);
      free(z);
    }
  }
}

/*
** COMMAND: close
**
** Usage: %fossil close ?OPTIONS?
**
** The opposite of "open".  Close the current database connection.
** Require a -f or --force flag if there are unsaved changed in the
** current check-out.
**







|







270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
      file_delete(z);
      free(z);
    }
  }
}

/*
** COMMAND: close*
**
** Usage: %fossil close ?OPTIONS?
**
** The opposite of "open".  Close the current database connection.
** Require a -f or --force flag if there are unsaved changed in the
** current check-out.
**
Changes to src/configure.c.
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
  configure_send_group(&out, groupMask, iStart);
  blob_write_to_file(&out, zFilename);
  blob_reset(&out);
}


/*
** COMMAND: configuration
**
** Usage: %fossil configuration METHOD ... ?OPTIONS?
**
** Where METHOD is one of: export import merge pull push reset.  All methods
** accept the -R or --repository option to specific a repository.
**
**    %fossil configuration export AREA FILENAME







|







722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
  configure_send_group(&out, groupMask, iStart);
  blob_write_to_file(&out, zFilename);
  blob_reset(&out);
}


/*
** COMMAND: configuration*
**
** Usage: %fossil configuration METHOD ... ?OPTIONS?
**
** Where METHOD is one of: export import merge pull push reset.  All methods
** accept the -R or --repository option to specific a repository.
**
**    %fossil configuration export AREA FILENAME
Changes to src/content.c.
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
  }else{
    bag_insert(&contentCache.available, rid);
  }
  return rc;
}

/*
** COMMAND: artifact
**
** Usage: %fossil artifact ARTIFACT-ID ?OUTPUT-FILENAME? ?OPTIONS?
**
** Extract an artifact by its SHA1 hash and write the results on
** standard output, or if the optional 4th argument is given, in
** the named output file.
**







|







301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
  }else{
    bag_insert(&contentCache.available, rid);
  }
  return rc;
}

/*
** COMMAND: artifact*
**
** Usage: %fossil artifact ARTIFACT-ID ?OUTPUT-FILENAME? ?OPTIONS?
**
** Extract an artifact by its SHA1 hash and write the results on
** standard output, or if the optional 4th argument is given, in
** the named output file.
**
Changes to src/db.c.
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
    blob_reset(&hash);
    rid = content_put(&manifest);
    manifest_crosslink(rid, &manifest);
  }
}

/*
** COMMAND: new
** COMMAND: init
**
** Usage: %fossil new ?OPTIONS? FILENAME
**    Or: %fossil init ?OPTIONS? FILENAME
**
** Create a repository for a new project in the file named FILENAME.
** This command is distinct from "clone".  The "clone" command makes







|







1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
    blob_reset(&hash);
    rid = content_put(&manifest);
    manifest_crosslink(rid, &manifest);
  }
}

/*
** COMMAND: new*
** COMMAND: init
**
** Usage: %fossil new ?OPTIONS? FILENAME
**    Or: %fossil init ?OPTIONS? FILENAME
**
** Create a repository for a new project in the file named FILENAME.
** This command is distinct from "clone".  The "clone" command makes
1641
1642
1643
1644
1645
1646
1647







1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661







1662
1663
1664
1665
1666
1667
1668
** Record the name of a local repository in the global_config() database.
** The repository filename %s is recorded as an entry with a "name" field
** of the following form:
**
**       repo:%s
**
** The value field is set to 1.







*/
void db_record_repository_filename(const char *zName){
  Blob full;
  if( zName==0 ){
    if( !g.localOpen ) return;
    zName = db_lget("repository", 0);
  }
  file_canonical_name(zName, &full);
  db_swap_connections();
  db_multi_exec(
     "INSERT OR IGNORE INTO global_config(name,value)"
     "VALUES('repo:%q',1)",
     blob_str(&full)
  );







  db_swap_connections();
  blob_reset(&full);
}

/*
** COMMAND: open
**







>
>
>
>
>
>
>














>
>
>
>
>
>
>







1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
** Record the name of a local repository in the global_config() database.
** The repository filename %s is recorded as an entry with a "name" field
** of the following form:
**
**       repo:%s
**
** The value field is set to 1.
**
** If running from a local checkout, also record the root of the checkout
** as follows:
**
**       ckout:%s
**
** Where %s is the checkout root.  The value is the repository file.
*/
void db_record_repository_filename(const char *zName){
  Blob full;
  if( zName==0 ){
    if( !g.localOpen ) return;
    zName = db_lget("repository", 0);
  }
  file_canonical_name(zName, &full);
  db_swap_connections();
  db_multi_exec(
     "INSERT OR IGNORE INTO global_config(name,value)"
     "VALUES('repo:%q',1)",
     blob_str(&full)
  );
  if( g.localOpen && g.zLocalRoot && g.zLocalRoot[0] ){
    db_multi_exec(
      "REPLACE INTO global_config(name, value)"
      "VALUES('ckout:%q','%q');",
      g.zLocalRoot, blob_str(&full)
    );
  }
  db_swap_connections();
  blob_reset(&full);
}

/*
** COMMAND: open
**
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
  { "web-browser",   0,               32, 0, ""                    },
  { "white-foreground", 0,             0, 0, "off"                 },
  { 0,0,0,0,0 }
};

/*
** COMMAND: settings
** COMMAND: unset
**
** %fossil settings ?PROPERTY? ?VALUE? ?-global?
** %fossil unset PROPERTY ?-global?
**
** The "settings" command with no arguments lists all properties and their
** values.  With just a property name it shows the value of that property.
** With a value argument it changes the property for the current repository.







|







1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
  { "web-browser",   0,               32, 0, ""                    },
  { "white-foreground", 0,             0, 0, "off"                 },
  { 0,0,0,0,0 }
};

/*
** COMMAND: settings
** COMMAND: unset*
**
** %fossil settings ?PROPERTY? ?VALUE? ?-global?
** %fossil unset PROPERTY ?-global?
**
** The "settings" command with no arguments lists all properties and their
** values.  With just a property name it shows the value of that property.
** With a value argument it changes the property for the current repository.
Changes to src/descendants.c.
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
  bag_clear(&seen);
  pqueue_clear(&queue);
  db_finalize(&ins);
  db_finalize(&q);
}

/*
** COMMAND:  descendants
**
** Usage: %fossil descendants ?BASELINE-ID? ?OPTIONS?
**
** Find all leaf descendants of the baseline specified or if the argument
** is omitted, of the baseline currently checked out.
**
** Options:







|







261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
  bag_clear(&seen);
  pqueue_clear(&queue);
  db_finalize(&ins);
  db_finalize(&q);
}

/*
** COMMAND: descendants*
**
** Usage: %fossil descendants ?BASELINE-ID? ?OPTIONS?
**
** Find all leaf descendants of the baseline specified or if the argument
** is omitted, of the baseline currently checked out.
**
** Options:
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
    timeline_query_for_tty()
  );
  print_timeline(&q, 20, 0);
  db_finalize(&q);
}

/*
** COMMAND:  leaves
**
** Usage: %fossil leaves ?OPTIONS?
**
** Find leaves of all branches.  By default show only open leaves.
** The --all flag causes all leaves (closed and open) to be shown.
** The --closed flag shows only closed leaves.
**







|







296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
    timeline_query_for_tty()
  );
  print_timeline(&q, 20, 0);
  db_finalize(&q);
}

/*
** COMMAND: leaves*
**
** Usage: %fossil leaves ?OPTIONS?
**
** Find leaves of all branches.  By default show only open leaves.
** The --all flag causes all leaves (closed and open) to be shown.
** The --closed flag shows only closed leaves.
**
Changes to src/doc.c.
365
366
367
368
369
370
371

372
373
374
375
376
377
378




379




380
381
382
383
384
385
386
  char zBaseline[UUID_SIZE+1];      /* Baseline UUID */

  login_check_credentials();
  if( !g.perm.Read ){ login_needed(); return; }
  zName = PD("name", "tip/index.wiki");
  for(i=0; zName[i] && zName[i]!='/'; i++){}
  if( zName[i]==0 || i>UUID_SIZE ){

    goto doc_not_found;
  }
  memcpy(zBaseline, zName, i);
  zBaseline[i] = 0;
  zName += i;
  while( zName[0]=='/' ){ zName++; }
  if( !file_is_simple_pathname(zName) ){




    goto doc_not_found;




  }
  if( fossil_strcmp(zBaseline,"ckout")==0 && db_open_local()==0 ){
    sqlite3_snprintf(sizeof(zBaseline), zBaseline, "tip");
  }
  if( fossil_strcmp(zBaseline,"ckout")==0 ){
    /* Read from the local checkout */
    char *zFullpath;







>







>
>
>
>
|
>
>
>
>







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
  char zBaseline[UUID_SIZE+1];      /* Baseline UUID */

  login_check_credentials();
  if( !g.perm.Read ){ login_needed(); return; }
  zName = PD("name", "tip/index.wiki");
  for(i=0; zName[i] && zName[i]!='/'; i++){}
  if( zName[i]==0 || i>UUID_SIZE ){
    zName = "index.html";
    goto doc_not_found;
  }
  memcpy(zBaseline, zName, i);
  zBaseline[i] = 0;
  zName += i;
  while( zName[0]=='/' ){ zName++; }
  if( !file_is_simple_pathname(zName) ){
    int n = strlen(zName);
    if( n>0 && zName[n-1]=='/' ){
      zName = mprintf("%sindex.html", zName);
      if( !file_is_simple_pathname(zName) ){
        goto doc_not_found;
      }
    }else{
      goto doc_not_found;
    }
  }
  if( fossil_strcmp(zBaseline,"ckout")==0 && db_open_local()==0 ){
    sqlite3_snprintf(sizeof(zBaseline), zBaseline, "tip");
  }
  if( fossil_strcmp(zBaseline,"ckout")==0 ){
    /* Read from the local checkout */
    char *zFullpath;
406
407
408
409
410
411
412


413
414
415
416
417
418
419
      "CREATE TABLE IF NOT EXISTS vcache(\n"
      "  vid INTEGER,         -- baseline ID\n"
      "  fname TEXT,          -- filename\n"
      "  rid INTEGER,         -- artifact ID\n"
      "  UNIQUE(vid,fname,rid)\n"
      ")"
    );



    /* Check to see if the documentation file artifact ID is contained
    ** in the baseline cache */
    rid = db_int(0, "SELECT rid FROM vcache"
                    " WHERE vid=%d AND fname=%Q", vid, zName);
    if( rid==0 && db_exists("SELECT 1 FROM vcache WHERE vid=%d", vid) ){
      goto doc_not_found;







>
>







415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
      "CREATE TABLE IF NOT EXISTS vcache(\n"
      "  vid INTEGER,         -- baseline ID\n"
      "  fname TEXT,          -- filename\n"
      "  rid INTEGER,         -- artifact ID\n"
      "  UNIQUE(vid,fname,rid)\n"
      ")"
    );



    /* Check to see if the documentation file artifact ID is contained
    ** in the baseline cache */
    rid = db_int(0, "SELECT rid FROM vcache"
                    " WHERE vid=%d AND fname=%Q", vid, zName);
    if( rid==0 && db_exists("SELECT 1 FROM vcache WHERE vid=%d", vid) ){
      goto doc_not_found;
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
  }
  return;

doc_not_found:
  /* Jump here when unable to locate the document */
  db_end_transaction(0);
  style_header("Document Not Found");
  @ <p>No such document: %h(PD("name","tip/index.wiki"))</p>
  style_footer();
  return;  
}

/*
** The default logo.
*/







|







508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
  }
  return;

doc_not_found:
  /* Jump here when unable to locate the document */
  db_end_transaction(0);
  style_header("Document Not Found");
  @ <p>No such document: %h(zName)</p>
  style_footer();
  return;  
}

/*
** The default logo.
*/
Changes to src/info.c.
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
173
174
175
176
177
178
179
  i64 fsize;
  if( g.argc==3 && (fsize = file_size(g.argv[2]))>0 && (fsize&0x1ff)==0 ){
    db_open_config(0);
    db_record_repository_filename(g.argv[2]);
    db_open_repository(g.argv[2]);
    fossil_print("project-name: %s\n", db_get("project-name", "<unnamed>"));
    fossil_print("project-code: %s\n", db_get("project-code", "<none>"));
    fossil_print("server-code:  %s\n", db_get("server-code", "<none>"));
    return;
  }
  db_find_and_open_repository(0,0);
  if( g.argc==2 ){
    int vid;
         /* 012345678901234 */
    db_record_repository_filename(0);
    fossil_print("project-name: %s\n", db_get("project-name", "<unnamed>"));
    if( g.localOpen ){
      fossil_print("repository:   %s\n", db_lget("repository", ""));
      fossil_print("local-root:   %s\n", g.zLocalRoot);
    }
#if defined(_WIN32)
    if( g.zHome ){
      fossil_print("user-home:    %s\n", g.zHome);
    }
#endif
    fossil_print("project-code: %s\n", db_get("project-code", ""));
    fossil_print("server-code:  %s\n", db_get("server-code", ""));
    vid = g.localOpen ? db_lget_int("checkout", 0) : 0;
    if( vid ){
      show_common_info(vid, "checkout:", 1, 1);
    }
  }else{
    int rid;
    rid = name_to_rid(g.argv[2]);







<


















<







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
173
174
175
176
177
  i64 fsize;
  if( g.argc==3 && (fsize = file_size(g.argv[2]))>0 && (fsize&0x1ff)==0 ){
    db_open_config(0);
    db_record_repository_filename(g.argv[2]);
    db_open_repository(g.argv[2]);
    fossil_print("project-name: %s\n", db_get("project-name", "<unnamed>"));
    fossil_print("project-code: %s\n", db_get("project-code", "<none>"));

    return;
  }
  db_find_and_open_repository(0,0);
  if( g.argc==2 ){
    int vid;
         /* 012345678901234 */
    db_record_repository_filename(0);
    fossil_print("project-name: %s\n", db_get("project-name", "<unnamed>"));
    if( g.localOpen ){
      fossil_print("repository:   %s\n", db_lget("repository", ""));
      fossil_print("local-root:   %s\n", g.zLocalRoot);
    }
#if defined(_WIN32)
    if( g.zHome ){
      fossil_print("user-home:    %s\n", g.zHome);
    }
#endif
    fossil_print("project-code: %s\n", db_get("project-code", ""));

    vid = g.localOpen ? db_lget_int("checkout", 0) : 0;
    if( vid ){
      show_common_info(vid, "checkout:", 1, 1);
    }
  }else{
    int rid;
    rid = name_to_rid(g.argv[2]);
Changes to src/main.c.
407
408
409
410
411
412
413

414
415
416

417

418
419
420
421
422
423
424
  argc = g.argc;
  argv = g.argv;
  for(i=0; i<argc; i++) g.argv[i] = fossil_mbcs_to_utf8(argv[i]);
  if( getenv("GATEWAY_INTERFACE")!=0 && !find_option("nocgi", 0, 0)){
    zCmdName = "cgi";
    g.isHTTP = 1;
  }else if( argc<2 ){

    fossil_fatal("Usage: %s COMMAND ...\n"
                 "\"%s help\" for a list of available commands\n"
                 "\"%s help COMMAND\" for specific details\n",

                 argv[0], argv[0], argv[0]);

  }else{
    g.isHTTP = 0;
    g.fQuiet = find_option("quiet", 0, 0)!=0;
    g.fSqlTrace = find_option("sqltrace", 0, 0)!=0;
    g.fSqlStats = find_option("sqlstats", 0, 0)!=0;
    g.fSystemTrace = find_option("systemtrace", 0, 0)!=0;
    if( g.fSqlTrace ) g.fSqlStats = 1;







>
|
|
|
>
|
>







407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
  argc = g.argc;
  argv = g.argv;
  for(i=0; i<argc; i++) g.argv[i] = fossil_mbcs_to_utf8(argv[i]);
  if( getenv("GATEWAY_INTERFACE")!=0 && !find_option("nocgi", 0, 0)){
    zCmdName = "cgi";
    g.isHTTP = 1;
  }else if( argc<2 ){
    fossil_print(
       "Usage: %s COMMAND ...\n"
       "   or: %s help           -- for a list of common commands\n"
       "   or: %s help COMMMAND  -- for help with the named command\n"
       "   or: %s commands       -- for a list of all commands\n",
       argv[0], argv[0], argv[0], argv[0]);
    fossil_exit(1);
  }else{
    g.isHTTP = 0;
    g.fQuiet = find_option("quiet", 0, 0)!=0;
    g.fSqlTrace = find_option("sqltrace", 0, 0)!=0;
    g.fSqlStats = find_option("sqlstats", 0, 0)!=0;
    g.fSystemTrace = find_option("systemtrace", 0, 0)!=0;
    if( g.fSqlTrace ) g.fSqlStats = 1;
451
452
453
454
455
456
457
458
459
460
461

462
463
464
465
466
467
468
    blob_zero(&couldbe);
    n = strlen(zCmdName);
    for(i=0; i<count(aCommand); i++){
      if( memcmp(zCmdName, aCommand[i].zName, n)==0 ){
        blob_appendf(&couldbe, " %s", aCommand[i].zName);
      }
    }
    fossil_fatal("%s: ambiguous command prefix: %s\n"
                 "%s: could be any of:%s\n"
                 "%s: use \"help\" for more information\n",
                 argv[0], zCmdName, argv[0], blob_str(&couldbe), argv[0]);

  }
  if(rc){
    fossil_fatal("%s: unrecoverable error while initializing JSON CGI bits: "
                 "cson error code #%d (%s)\n",
                 argv[0], rc, cson_rc_string(rc));
  }
  atexit( fossil_atexit );







|



>







454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
    blob_zero(&couldbe);
    n = strlen(zCmdName);
    for(i=0; i<count(aCommand); i++){
      if( memcmp(zCmdName, aCommand[i].zName, n)==0 ){
        blob_appendf(&couldbe, " %s", aCommand[i].zName);
      }
    }
    fossil_print("%s: ambiguous command prefix: %s\n"
                 "%s: could be any of:%s\n"
                 "%s: use \"help\" for more information\n",
                 argv[0], zCmdName, argv[0], blob_str(&couldbe), argv[0]);
    fossil_exit(1);
  }
  if(rc){
    fossil_fatal("%s: unrecoverable error while initializing JSON CGI bits: "
                 "cson error code #%d (%s)\n",
                 argv[0], rc, cson_rc_string(rc));
  }
  atexit( fossil_atexit );
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832

833


834
835
836
837
838


839
840




841
842
843
844
845
846
847
848
849
    fossil_print("\n");
  }
}

/*
** List of commands starting with zPrefix, or all commands if zPrefix is NULL.
*/
static void cmd_cmd_list(const char *zPrefix){
  int i, nCmd;
  int nPrefix = zPrefix ? strlen(zPrefix) : 0;
  const char *aCmd[count(aCommand)];
  for(i=nCmd=0; i<count(aCommand); i++){
    const char *z = aCommand[i].zName;
    if( memcmp(z,"test",4)==0 ) continue;
    if( zPrefix && memcmp(zPrefix, z, nPrefix)!=0 ) continue;
    aCmd[nCmd++] = aCommand[i].zName;
  }
  multi_column_list(aCmd, nCmd);
}

/*
** COMMAND: test-commands
**
** Usage: %fossil test-commands
**

** List all commands used for testing and debugging.


*/
void cmd_test_cmd_list(void){
  int i, nCmd;
  const char *aCmd[count(aCommand)];
  for(i=nCmd=0; i<count(aCommand); i++){


    if( strncmp(aCommand[i].zName,"test",4)!=0 ) continue;
    aCmd[nCmd++] = aCommand[i].zName;




  }
  multi_column_list(aCmd, nCmd);
}


/*
** COMMAND: test-list-webpage
**
** List all web pages







|





|







|

|

>
|
>
>

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

|







812
813
814
815
816
817
818
819
820
821
822
823
824
825
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
    fossil_print("\n");
  }
}

/*
** List of commands starting with zPrefix, or all commands if zPrefix is NULL.
*/
static void command_list(const char *zPrefix, int cmdMask){
  int i, nCmd;
  int nPrefix = zPrefix ? strlen(zPrefix) : 0;
  const char *aCmd[count(aCommand)];
  for(i=nCmd=0; i<count(aCommand); i++){
    const char *z = aCommand[i].zName;
    if( (aCommand[i].cmdFlags & cmdMask)==0 ) continue;
    if( zPrefix && memcmp(zPrefix, z, nPrefix)!=0 ) continue;
    aCmd[nCmd++] = aCommand[i].zName;
  }
  multi_column_list(aCmd, nCmd);
}

/*
** COMMAND: commands
**
** Usage: %fossil commands ?--test? ?--all? ?--aux?
**
** List available commands.  If the --test option is used list only unsupported
** commands intended for testing and debugging.  With --all, show all commands
** including test debugging commands.  With --aux, show only the auxiliary
** and less often used commands, and/or command aliases.
*/
void cmd_command_list(void){
  int cmdFlags = CMDFLAG_1ST_TIER | CMDFLAG_2ND_TIER;


  if( find_option("all",0,0)!=0 ){
    cmdFlags |= CMDFLAG_TEST;
  }else if( find_option("test",0,0)!=0 ){
    cmdFlags = CMDFLAG_TEST;
  }else if( find_option("aux",0,0)!=0 ){
    cmdFlags = CMDFLAG_2ND_TIER;
  }else{
    fossil_print("Use --test or --all to see test and debug commands.\n");
  }
  command_list(0, cmdFlags);
}


/*
** COMMAND: test-list-webpage
**
** List all web pages
871
872
873
874
875
876
877

878
879



880
881
882
883
884
885
886




887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
}


/*
** COMMAND: help
**
** Usage: %fossil help COMMAND

**
** Display information on how to use COMMAND



*/
void help_cmd(void){
  int rc, idx;
  const char *z;
  if( g.argc<3 ){
    fossil_print("Usage: %s help COMMAND.\nAvailable COMMANDs:\n",
                 fossil_nameofexe());




    cmd_cmd_list(0);
    version_cmd();
    return;
  }
  rc = name_search(g.argv[2], aCommand, count(aCommand), &idx);
  if( rc==1 ){
    fossil_print("unknown command: %s\nAvailable commands:\n", g.argv[2]);
    cmd_cmd_list(0);
    fossil_exit(1);
  }else if( rc==2 ){
    fossil_print("ambiguous command prefix: %s\nMatching commands:\n",
                 g.argv[2]);
    cmd_cmd_list(g.argv[2]);
    fossil_exit(1);
  }
  z = aCmdHelp[idx];
  if( z==0 ){
    fossil_fatal("no help available for the %s command",
       aCommand[idx].zName);
  }







>

|
>
>
>





<
|
>
>
>
>
|






|




|







882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899

900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
}


/*
** COMMAND: help
**
** Usage: %fossil help COMMAND
**    or: %fossil COMMAND -help
**
** Display information on how to use COMMAND.  To display a list of
** available commands use:
**
**    %fossil commands
*/
void help_cmd(void){
  int rc, idx;
  const char *z;
  if( g.argc<3 ){

    z = fossil_nameofexe();
    fossil_print(
      "Usage: %s help COMMAND\n"
      "Common COMMANDs:  (use \"%s commands\" for a complete list)\n",
      z, z);
    command_list(0, CMDFLAG_1ST_TIER);
    version_cmd();
    return;
  }
  rc = name_search(g.argv[2], aCommand, count(aCommand), &idx);
  if( rc==1 ){
    fossil_print("unknown command: %s\nAvailable commands:\n", g.argv[2]);
    command_list(0, 0xff);
    fossil_exit(1);
  }else if( rc==2 ){
    fossil_print("ambiguous command prefix: %s\nMatching commands:\n",
                 g.argv[2]);
    command_list(g.argv[2], 0xff);
    fossil_exit(1);
  }
  z = aCmdHelp[idx];
  if( z==0 ){
    fossil_fatal("no help available for the %s command",
       aCommand[idx].zName);
  }
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297

  /* Return the result.
  */
  cgi_reply();
}

/*
** COMMAND: cgi
**
** Usage: %fossil ?cgi? SCRIPT
**
** The SCRIPT argument is the name of a file that is the CGI script
** that is being run.  The command name, "cgi", may be omitted if
** the GATEWAY_INTERFACE environment variable is set to "CGI" (which
** should always be the case for CGI scripts run by a webserver.)  The







|







1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315

  /* Return the result.
  */
  cgi_reply();
}

/*
** COMMAND: cgi*
**
** Usage: %fossil ?cgi? SCRIPT
**
** The SCRIPT argument is the name of a file that is the CGI script
** that is being run.  The command name, "cgi", may be omitted if
** the GATEWAY_INTERFACE environment variable is set to "CGI" (which
** should always be the case for CGI scripts run by a webserver.)  The
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
/*
** undocumented format:
**
**        fossil http REPOSITORY INFILE OUTFILE IPADDR
**
** The argv==6 form is used by the win32 server only.
**
** COMMAND: http
**
** Usage: %fossil http REPOSITORY [--notfound URL] [--host HOSTNAME] [--https]
**
** Handle a single HTTP request appearing on stdin.  The resulting webpage
** is delivered on stdout.  This method is used to launch an HTTP request
** handler from inetd, for example.  The argument is the name of the 
** repository.







|







1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
/*
** undocumented format:
**
**        fossil http REPOSITORY INFILE OUTFILE IPADDR
**
** The argv==6 form is used by the win32 server only.
**
** COMMAND: http*
**
** Usage: %fossil http REPOSITORY [--notfound URL] [--host HOSTNAME] [--https]
**
** Handle a single HTTP request appearing on stdin.  The resulting webpage
** is delivered on stdout.  This method is used to launch an HTTP request
** handler from inetd, for example.  The argument is the name of the 
** repository.
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
  }
  return 0;
}
#endif
#endif

/*
** COMMAND: server
** COMMAND: ui
**
** Usage: %fossil server ?-P|--port TCPPORT? ?REPOSITORY?
**    Or: %fossil ui ?-P|--port TCPPORT? ?REPOSITORY?
**
** Open a socket and begin listening and responding to HTTP requests on
** TCP port 8080, or on any other TCP port defined by the -P or







|







1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
  }
  return 0;
}
#endif
#endif

/*
** COMMAND: server*
** COMMAND: ui
**
** Usage: %fossil server ?-P|--port TCPPORT? ?REPOSITORY?
**    Or: %fossil ui ?-P|--port TCPPORT? ?REPOSITORY?
**
** Open a socket and begin listening and responding to HTTP requests on
** TCP port 8080, or on any other TCP port defined by the -P or
Changes to src/manifest.c.
1332
1333
1334
1335
1336
1337
1338
1339

1340
1341
1342



1343
1344










1345
1346

1347
1348
1349
1350
1351
1352
1353
         add_one_mlink(cid, pParentFile->zUuid, pChildFile->zUuid,
                       pChildFile->zName, 0, isPublic, mperm);
       }
    }
  }
  if( pParent->zBaseline && pChild->zBaseline ){
    /* Both parent and child are delta manifests.  Look for files that
    ** are marked as deleted in the parent but which reappear in the child

    ** and show such files as being added in the child. */
    for(i=0, pParentFile=pParent->aFile; i<pParent->nFile; i++, pParentFile++){
      if( pParentFile->zUuid ) continue;



      pChildFile = manifest_file_seek(pChild, pParentFile->zName);
      if( pChildFile ){










        add_one_mlink(cid, 0, pChildFile->zUuid, pChildFile->zName, 0,
                      isPublic, manifest_file_mperm(pChildFile));

      }
    }
  }else if( pChild->zBaseline==0 ){
    /* pChild is a baseline.  Look for files that are present in pParent
    ** but are missing from pChild and mark them as having been deleted. */
    manifest_file_rewind(pParent);
    while( (pParentFile = manifest_file_next(pParent,0))!=0 ){







|
>
|

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







1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
         add_one_mlink(cid, pParentFile->zUuid, pChildFile->zUuid,
                       pChildFile->zName, 0, isPublic, mperm);
       }
    }
  }
  if( pParent->zBaseline && pChild->zBaseline ){
    /* Both parent and child are delta manifests.  Look for files that
    ** are deleted or modified in the parent but which reappear or revert
    ** to baseline in the child and show such files as being added or changed
    ** in the child. */
    for(i=0, pParentFile=pParent->aFile; i<pParent->nFile; i++, pParentFile++){
      if( pParentFile->zUuid ){
        pChildFile = manifest_file_seek_base(pChild, pParentFile->zName);
        if( pChildFile==0 ){
          /* The child file reverts to baseline.  Show this as a change */
          pChildFile = manifest_file_seek(pChild, pParentFile->zName);
          if( pChildFile ){
            add_one_mlink(cid, pParentFile->zUuid, pChildFile->zUuid,
                          pChildFile->zName, 0, isPublic,
                          manifest_file_mperm(pChildFile));
          }
        }
      }else{
        pChildFile = manifest_file_seek(pChild, pParentFile->zName);
        if( pChildFile ){
          /* File resurrected in the child after having been deleted in
          ** the parent.  Show this as an added file. */
          add_one_mlink(cid, 0, pChildFile->zUuid, pChildFile->zName, 0,
                        isPublic, manifest_file_mperm(pChildFile));
        }
      }
    }
  }else if( pChild->zBaseline==0 ){
    /* pChild is a baseline.  Look for files that are present in pParent
    ** but are missing from pChild and mark them as having been deleted. */
    manifest_file_rewind(pParent);
    while( (pParentFile = manifest_file_next(pParent,0))!=0 ){
Changes to src/md5.c.
419
420
421
422
423
424
425
426

427
428
429
430
431
432
433
434
435
436
  MD5Final(zResult, &ctx);
  DigestToBase16(zResult, blob_buffer(pCksum));
  return 0;
}


/*
** COMMAND: test-md5sum

**
** Compute an MD5 checksum of all files named on the command-line.
** If an file is named "-" then take its content from standard input.
*/
void md5sum_test(void){
  int i;
  Blob in;
  Blob cksum;
  
  for(i=2; i<g.argc; i++){







|
>


|







419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
  MD5Final(zResult, &ctx);
  DigestToBase16(zResult, blob_buffer(pCksum));
  return 0;
}


/*
** COMMAND: md5sum*
** Usage: %fossil md5sum FILES....
**
** Compute an MD5 checksum of all files named on the command-line.
** If a file is named "-" then content is read from standard input.
*/
void md5sum_test(void){
  int i;
  Blob in;
  Blob cksum;
  
  for(i=2; i<g.argc; i++){
Changes to src/mkindex.c.
34
35
36
37
38
39
40
41


42
43
44
45
46
47
48
** webpage name into pointers to the function.
**
** We also scan for comments lines of this form:
**
**       COMMAND:  cmdname
**
** These entries build a constant table used to map command names into
** functions.


**
** Comment text following COMMAND: through the end of the comment is
** understood to be help text for the command specified.  This help
** text is accumulated and a table containing the text for each command
** is generated.  That table is used implement the "fossil help" command
** and the "/help" HTTP method.
**







|
>
>







34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
** webpage name into pointers to the function.
**
** We also scan for comments lines of this form:
**
**       COMMAND:  cmdname
**
** These entries build a constant table used to map command names into
** functions.  If cmdname ends with "*" then the command is a second-tier
** command that is not displayed by the "fossil help" command.  The
** final "*" is not considered to be part of the command name.
**
** Comment text following COMMAND: through the end of the comment is
** understood to be help text for the command specified.  This help
** text is accumulated and a table containing the text for each command
** is generated.  That table is used implement the "fossil help" command
** and the "/help" HTTP method.
**
222
223
224
225
226
227
228

229



230
231
232


233

234
235

236
237
238
239
240
241
242
243









244

245
246


247
248
249
250
251
252
253
    printf("extern void %s(void);\n", aEntry[i].zFunc);
  }
  printf(
    "typedef struct NameMap NameMap;\n"
    "struct NameMap {\n"
    "  const char *zName;\n"
    "  void (*xFunc)(void);\n"

    "};\n"



    "static const NameMap aWebpage[] = {\n"
  );
  for(i=0; i<nFixed && aEntry[i].eType==0; i++){


    printf("  { \"%s\",%*s %s },\n",

      aEntry[i].zPath, (int)(25-strlen(aEntry[i].zPath)), "",
      aEntry[i].zFunc

    );
  }
  printf("};\n");
  nType0 = i;
  printf(
    "static const NameMap aCommand[] = {\n"
  );
  for(i=nType0; i<nFixed && aEntry[i].eType==1; i++){









    printf("  { \"%s\",%*s %s },\n",

      aEntry[i].zPath, (int)(25-strlen(aEntry[i].zPath)), "",
      aEntry[i].zFunc


    );
  }
  printf("};\n");
  for(i=nType0; i<nFixed; i++){
    char *z = aEntry[i].zHelp;
    if( z && z[0] ){
      printf("static const char zHelp_%s[] = \n", aEntry[i].zFunc);







>

>
>
>



>
>
|
>
|
|
>








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







224
225
226
227
228
229
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
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
    printf("extern void %s(void);\n", aEntry[i].zFunc);
  }
  printf(
    "typedef struct NameMap NameMap;\n"
    "struct NameMap {\n"
    "  const char *zName;\n"
    "  void (*xFunc)(void);\n"
    "  char cmdFlags;\n"
    "};\n"
    "#define CMDFLAG_1ST_TIER  0x01\n"
    "#define CMDFLAG_2ND_TIER  0x02\n"
    "#define CMDFLAG_TEST      0x04\n"
    "static const NameMap aWebpage[] = {\n"
  );
  for(i=0; i<nFixed && aEntry[i].eType==0; i++){
    const char *z = aEntry[i].zPath;
    int n = strlen(z);
    printf("  { \"%s\",%*s %s,%*s 1 },\n",
      z,
      25-n, "",
      aEntry[i].zFunc,
      (int)(35-strlen(aEntry[i].zFunc)), ""
    );
  }
  printf("};\n");
  nType0 = i;
  printf(
    "static const NameMap aCommand[] = {\n"
  );
  for(i=nType0; i<nFixed && aEntry[i].eType==1; i++){
    const char *z = aEntry[i].zPath;
    int n = strlen(z);
    int cmdFlags = 0x01;
    if( z[n-1]=='*' ){
      n--;
      cmdFlags = 0x02;
    }else if( memcmp(z, "test-", 5)==0 ){
      cmdFlags = 0x04;
    }
    printf("  { \"%.*s\",%*s %s,%*s %d },\n",
      n, z,
      25-n, "",
      aEntry[i].zFunc,
      (int)(35-strlen(aEntry[i].zFunc)), "",
      cmdFlags
    );
  }
  printf("};\n");
  for(i=nType0; i<nFixed; i++){
    char *z = aEntry[i].zHelp;
    if( z && z[0] ){
      printf("static const char zHelp_%s[] = \n", aEntry[i].zFunc);
Changes to src/name.c.
20
21
22
23
24
25
26


















































































































































































































27
28
29
30
31
32
33
34
35
36
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
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
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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
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
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
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
259
260
261
262
263
264
265
266
267
268
269
270
**
** A user-supplied object name is any unique prefix of a valid UUID but
** not necessarily in canonical form.  
*/
#include "config.h"
#include "name.h"
#include <assert.h>



















































































































































































































/*
** This routine takes a user-entered UUID which might be in mixed
** case and might only be a prefix of the full UUID and converts it
** into the full-length UUID in canonical form.
**
** If the input is not a UUID or a UUID prefix, then try to resolve
** the name as a tag.  If multiple tags match, pick the latest.
** If the input name matches "tag:*" then always resolve as a tag.
**
** If the input is not a tag, then try to match it as an ISO-8601 date
** string YYYY-MM-DD HH:MM:SS and pick the nearest check-in to that date.
** If the input is of the form "date:*" or "localtime:*" or "utc:*" then
** always resolve the name as a date.
**
** Return 0 on success.  Return 1 if the name cannot be resolved.
** Return 2 name is ambiguous.
*/
int name_to_uuid(Blob *pName, int iErrPriority, const char *zType){
  int rc;
  int sz;
  sz = blob_size(pName);
  if( sz>UUID_SIZE || sz<4 || !validate16(blob_buffer(pName), sz) ){
    char *zUuid;
    const char *zName = blob_str(pName);
    if( memcmp(zName, "tag:", 4)==0 ){
      zName += 4;
      zUuid = tag_to_uuid(zName, zType);
    }else{
      zUuid = tag_to_uuid(zName, zType);
      if( zUuid==0 ){
        zUuid = date_to_uuid(zName, zType);
      }
    }
    if( zUuid ){
      blob_reset(pName);
      blob_append(pName, zUuid, -1);
      free(zUuid);
      return 0;
    }
    fossil_error(iErrPriority, "not a valid object name: %s", zName);
    return 1;
  }
  blob_materialize(pName);
  canonical16(blob_buffer(pName), sz);
  if( sz==UUID_SIZE ){
    rc = db_int(1, "SELECT 0 FROM blob WHERE uuid=%B", pName);
    if( rc ){
      fossil_error(iErrPriority, "no such artifact: %b", pName);
      blob_reset(pName);
    }
  }else if( sz<UUID_SIZE && sz>=4 ){
    Stmt q;
    db_prepare(&q, "SELECT uuid FROM blob WHERE uuid GLOB '%b*'", pName);
    if( db_step(&q)!=SQLITE_ROW ){
      char *zUuid;
      db_finalize(&q);
      zUuid = tag_to_uuid(blob_str(pName), "*");
      if( zUuid ){
        blob_reset(pName);
        blob_append(pName, zUuid, -1);
        free(zUuid);
        return 0;
      }
      fossil_error(iErrPriority, "no artifacts match the prefix \"%b\"", pName);
      return 1;
    }
    blob_reset(pName);
    blob_append(pName, db_column_text(&q, 0), db_column_bytes(&q, 0));
    if( db_step(&q)==SQLITE_ROW ){
      fossil_error(iErrPriority, 
         "multiple artifacts match"
      );
      blob_reset(pName);
      db_finalize(&q);
      return 2;
    }
    db_finalize(&q);
    rc = 0;
  }else{
    rc = 0;
  }
  return rc;
}

/*
** Return TRUE if the string begins with an ISO8601 date: YYYY-MM-DD.
*/
static int is_date(const char *z){
  if( !fossil_isdigit(z[0]) ) return 0;
  if( !fossil_isdigit(z[1]) ) return 0;
  if( !fossil_isdigit(z[2]) ) return 0;
  if( !fossil_isdigit(z[3]) ) return 0;
  if( z[4]!='-') return 0;
  if( !fossil_isdigit(z[5]) ) return 0;
  if( !fossil_isdigit(z[6]) ) return 0;
  if( z[7]!='-') return 0;
  if( !fossil_isdigit(z[8]) ) return 0;
  if( !fossil_isdigit(z[9]) ) return 0;
  return 1;
}

/*
** Convert a symbolic tag name into the UUID of a check-in that contains
** that tag.  If the tag appears on multiple check-ins, return the UUID
** of the most recent check-in with the tag.
**
** If the input string is of the form:
**
**      tag:date
**
** Then return the UUID of the oldest check-in with that tag that is
** not older than 'date'.
**
** An input of "tip" returns the most recent check-in.
**
** Memory to hold the returned string comes from malloc() and needs to
** be freed by the caller.
*/
char *tag_to_uuid(const char *zTag, const char *zType){
  int vid;
  char *zUuid;

  if( zType==0 || zType[0]==0 ) zType = "*";
  zUuid = db_text(0,
       "SELECT blob.uuid"
       "  FROM tag, tagxref, event, blob"
       " WHERE tag.tagname='sym-%q' "
       "   AND tagxref.tagid=tag.tagid AND tagxref.tagtype>0 "
       "   AND event.objid=tagxref.rid "
       "   AND blob.rid=event.objid "
       "   AND event.type GLOB '%q'"
       " ORDER BY event.mtime DESC /*sort*/",
       zTag, zType
    );
  if( zUuid==0 ){
    int nTag = strlen(zTag);
    int i;
    for(i=0; i<nTag-10; i++){
      if( zTag[i]==':' && is_date(&zTag[i+1]) ){
        char *zDate = mprintf("%s", &zTag[i+1]);
        char *zTagBase = mprintf("%.*s", i, zTag);
        int nDate = strlen(zDate);
        int useUtc = 0;
        if( sqlite3_strnicmp(&zDate[nDate-3],"utc",3)==0 ){
          nDate -= 3;
          zDate[nDate] = 0;
          useUtc = 1;
        }
        zUuid = db_text(0,
          "SELECT blob.uuid"
          "  FROM tag, tagxref, event, blob"
          " WHERE tag.tagname='sym-%q' "
          "   AND tagxref.tagid=tag.tagid AND tagxref.tagtype>0 "
          "   AND event.objid=tagxref.rid "
          "   AND blob.rid=event.objid "
          "   AND event.mtime<=julianday(%Q %s)"
          "   AND event.type GLOB '%q'"
          " ORDER BY event.mtime DESC /*sort*/ ",
          zTagBase, zDate, (useUtc ? "" : ",'utc'"), zType
        );
        break;
      }
    }
    if( zUuid==0 && fossil_strcmp(zTag, "tip")==0 ){
      zUuid = db_text(0,
        "SELECT blob.uuid"
        "  FROM event, blob"
        " WHERE event.type='ci'"
        "   AND blob.rid=event.objid"
        " ORDER BY event.mtime DESC"
      );
    }
    if( zUuid==0 && g.localOpen && (vid=db_lget_int("checkout",0))!=0 ){
      if( fossil_strcmp(zTag, "current")==0 ){
        zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", vid);
      }else if( fossil_strcmp(zTag, "prev")==0 
                || fossil_strcmp(zTag, "previous")==0 ){
        zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid="
                           "(SELECT pid FROM plink WHERE cid=%d AND isprim)",
                           vid);
      }else if( fossil_strcmp(zTag, "next")==0 ){
        zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid="
                           "(SELECT cid FROM plink WHERE pid=%d"
                           "  ORDER BY isprim DESC, mtime DESC)",
                           vid);
      }
    }
  }
  return zUuid;
}

/*
** Convert a date/time string into a UUID.
**
** Input forms accepted:
**
**    date:DATE
**    local:DATE
**    utc:DATE
**
** The DATE is interpreted as localtime unless the "utc:" prefix is used
** or a "utc" string appears at the end of the DATE string.
*/
char *date_to_uuid(const char *zDate, const char *zType){
  int useUtc = 0;
  int n;
  char *zCopy = 0;
  char *zUuid;

  if( memcmp(zDate, "date:", 5)==0 ){
    zDate += 5;
  }else if( memcmp(zDate, "local:", 6)==0 ){
    zDate += 6;
  }else if( memcmp(zDate, "utc:", 4)==0 ){
    zDate += 4;
    useUtc = 1;
  }
  n = strlen(zDate);
  if( n<10 || !is_date(zDate) ) return 0;
  if( n>4 && sqlite3_strnicmp(&zDate[n-3], "utc", 3)==0 ){
    zCopy = mprintf("%s", zDate);
    zCopy[n-3] = 0;
    zDate = zCopy;
    n -= 3;
    useUtc = 1;
  }
  if( zType==0 || zType[0]==0 ) zType = "*";
  zUuid = db_text(0,
    "SELECT (SELECT uuid FROM blob WHERE rid=event.objid)"
    "  FROM event"
    " WHERE mtime<=julianday(%Q %s) AND type GLOB '%q'"
    " ORDER BY mtime DESC LIMIT 1",
    zDate, useUtc ? "" : ",'utc'", zType
  );
  free(zCopy);
  return zUuid;
}

/*
** COMMAND:  test-name-to-id
**
** Convert a name to a full artifact ID.
*/







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



















<
<
<
<
<
|
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
|
<
<
<
<
<
<
|
|
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
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
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
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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
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
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
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






















259




260



























































261




262






263
264

265
























266













267
268














































269
270
271
272
273
274
275
**
** A user-supplied object name is any unique prefix of a valid UUID but
** not necessarily in canonical form.  
*/
#include "config.h"
#include "name.h"
#include <assert.h>

/*
** Return TRUE if the string begins with something that looks roughly
** like an ISO date/time string.  The SQLite date/time functions will
** have the final say-so about whether or not the date/time string is
** well-formed.
*/
static int is_date(const char *z){
  if( !fossil_isdigit(z[0]) ) return 0;
  if( !fossil_isdigit(z[1]) ) return 0;
  if( !fossil_isdigit(z[2]) ) return 0;
  if( !fossil_isdigit(z[3]) ) return 0;
  if( z[4]!='-') return 0;
  if( !fossil_isdigit(z[5]) ) return 0;
  if( !fossil_isdigit(z[6]) ) return 0;
  if( z[7]!='-') return 0;
  if( !fossil_isdigit(z[8]) ) return 0;
  if( !fossil_isdigit(z[9]) ) return 0;
  return 1;
}

/*
** Convert a symbolic name into a RID.  Acceptable forms:
**
**   *  SHA1 hash
**   *  SHA1 hash prefix of at least 4 characters
**   *  Symbolic Name
**   *  "tag:" + symbolic name
**   *  Date or date-time 
**   *  "date:" + Date or date-time
**   *  symbolic-name ":" date-time
**   *  "tip"
**
** The following additional forms are available in local checkouts:
**
**   *  "current"
**   *  "prev" or "previous"
**   *  "next"
**
** Return the RID of the matching artifact.  Or return 0 if the name does not
** match any known object.  Or return -1 if the name is ambiguious.
**
** The zType parameter specifies the type of artifact: ci, t, w, e, g. 
** If zType is NULL or "" or "*" then any type of artifact will serve.
** zType is "ci" in most use cases since we are usually searching for
** a check-in.
*/
static int symbolic_name_to_rid(const char *zTag, const char *zType){
  int vid;
  int rid = 0;
  int nTag;
  int i;

  if( zType==0 || zType[0]==0 ) zType = "*";
  if( zTag==0 || zTag[0]==0 ) return 0;

  /* special keyword: "tip" */
  if( fossil_strcmp(zTag, "tip")==0 && (zType[0]=='*' || zType[0]=='c') ){
    rid = db_int(0,
      "SELECT objid"
      "  FROM event"
      " WHERE type='ci'"
      " ORDER BY event.mtime DESC"
    );
    if( rid ) return rid;
  }

  /* special keywords: "prev", "previous", "current", and "next" */
  if( g.localOpen && (vid=db_lget_int("checkout",0))!=0 ){
    if( fossil_strcmp(zTag, "current")==0 ){
      rid = vid;
    }else if( fossil_strcmp(zTag, "prev")==0 
              || fossil_strcmp(zTag, "previous")==0 ){
      rid = db_int(0, "SELECT pid FROM plink WHERE cid=%d AND isprim", vid);
    }else if( fossil_strcmp(zTag, "next")==0 ){
      rid = db_int(0, "SELECT cid FROM plink WHERE pid=%d"
                      "  ORDER BY isprim DESC, mtime DESC", vid);
    }
    if( rid ) return rid;
  }

  /* Date and times */
  if( memcmp(zTag, "date:", 5)==0 ){
    rid = db_int(0, 
      "SELECT objid FROM event"
      " WHERE mtime<=julianday(%Q) AND type GLOB '%q'"
      " ORDER BY mtime DESC LIMIT 1",
      &zTag[5], zType);
    return rid;
  }
  if( is_date(zTag) ){
    rid = db_int(0, 
      "SELECT objid FROM event"
      " WHERE mtime<=julianday(%Q) AND type GLOB '%q'"
      " ORDER BY mtime DESC LIMIT 1",
      zTag, zType);
    if( rid) return rid;
  }

  /* Deprecated date & time formats:   "local:" + date-time and
  ** "utc:" + date-time */
  if( memcmp(zTag, "local:", 6)==0 ){
    rid = db_int(0, 
      "SELECT objid FROM event"
      " WHERE mtime<=julianday(%Q) AND type GLOB '%q'"
      " ORDER BY mtime DESC LIMIT 1",
      &zTag[6], zType);
    return rid;
  }
  if( memcmp(zTag, "utc:", 4)==0 ){
    rid = db_int(0, 
      "SELECT objid FROM event"
      " WHERE mtime<=julianday('%qz') AND type GLOB '%q'"
      " ORDER BY mtime DESC LIMIT 1",
      &zTag[4], zType);
    return rid;
  }

  /* "tag:" + symbolic-name */
  if( memcmp(zTag, "tag:", 4)==0 ){
    rid = db_int(0,
       "SELECT event.objid"
       "  FROM tag, tagxref, event"
       " WHERE tag.tagname='sym-%q' "
       "   AND tagxref.tagid=tag.tagid AND tagxref.tagtype>0 "
       "   AND event.objid=tagxref.rid "
       "   AND event.type GLOB '%q'"
       " ORDER BY event.mtime DESC /*sort*/",
       &zTag[4], zType
    );
    return rid;
  }

  /* symbolic-name ":" date-time */
  nTag = strlen(zTag);
  for(i=0; i<nTag-10 && zTag[i]!=':'; i++){}
  if( zTag[i]==':' && is_date(&zTag[i+1]) ){
    char *zDate = mprintf("%s", &zTag[i+1]);
    char *zTagBase = mprintf("%.*s", i, zTag);
    int nDate = strlen(zDate);
    if( sqlite3_strnicmp(&zDate[nDate-3],"utc",3)==0 ){
      zDate[nDate-3] = 'z';
      zDate[nDate-2] = 0;
    }
    rid = db_int(0,
      "SELECT event.objid"
      "  FROM tag, tagxref, event"
      " WHERE tag.tagname='sym-%q' "
      "   AND tagxref.tagid=tag.tagid AND tagxref.tagtype>0 "
      "   AND event.objid=tagxref.rid "
      "   AND event.mtime<=julianday(%Q)"
      "   AND event.type GLOB '%q'"
      " ORDER BY event.mtime DESC /*sort*/ ",
      zTagBase, zDate, zType
    );
    return rid;
  }

  /* SHA1 hash or prefix */
  if( nTag>=4 && nTag<=UUID_SIZE && validate16(zTag, nTag) ){
    Stmt q;
    char zUuid[UUID_SIZE+1];
    memcpy(zUuid, zTag, nTag+1);
    canonical16(zUuid, nTag);
    rid = 0;
    if( zType[0]=='*' ){
      db_prepare(&q, "SELECT rid FROM blob WHERE uuid GLOB '%s*'", zUuid);
    }else{
      db_prepare(&q,
        "SELECT blob.rid"
        "  FROM blob, event"
        " WHERE blob.uuid GLOB '%s*'"
        "   AND event.objid=blob.rid"
        "   AND event.type GLOB '%q'",
        zUuid, zType
      );
    }
    if( db_step(&q)==SQLITE_ROW ){
      rid = db_column_int(&q, 0);
      if( db_step(&q)==SQLITE_ROW ) rid = -1;
    }
    db_finalize(&q);
    if( rid ) return rid;
  }

  /* Symbolic name */
  rid = db_int(0,
    "SELECT event.objid"
    "  FROM tag, tagxref, event"
    " WHERE tag.tagname='sym-%q' "
    "   AND tagxref.tagid=tag.tagid AND tagxref.tagtype>0 "
    "   AND event.objid=tagxref.rid "
    "   AND event.type GLOB '%q'"
    " ORDER BY event.mtime DESC /*sort*/ ",
    zTag, zType
  );
  if( rid>0 ) return rid;

  /* Undocumented:  numeric tags get translated directly into the RID */
  for(i=0; fossil_isdigit(zTag[i]); i++){}
  if( zTag[i]==0 ){
    rid = db_int(0, 
      "SELECT event.objid"
      "  FROM event"
      " WHERE event.objid=%s"
      "   AND event.type GLOB '%q'", zTag, zType);
  }
  return rid;
}


/*
** This routine takes a user-entered UUID which might be in mixed
** case and might only be a prefix of the full UUID and converts it
** into the full-length UUID in canonical form.
**
** If the input is not a UUID or a UUID prefix, then try to resolve
** the name as a tag.  If multiple tags match, pick the latest.
** If the input name matches "tag:*" then always resolve as a tag.
**
** If the input is not a tag, then try to match it as an ISO-8601 date
** string YYYY-MM-DD HH:MM:SS and pick the nearest check-in to that date.
** If the input is of the form "date:*" or "localtime:*" or "utc:*" then
** always resolve the name as a date.
**
** Return 0 on success.  Return 1 if the name cannot be resolved.
** Return 2 name is ambiguous.
*/
int name_to_uuid(Blob *pName, int iErrPriority, const char *zType){





  char *zName = blob_str(pName);


  int rid = symbolic_name_to_rid(zName, zType);



















  if( rid<0 ){






















    fossil_error(iErrPriority, "ambiguous name: %s", zName);




    return 2;



























































  }else if( rid==0 ){




    fossil_error(iErrPriority, "not found: %s", zName);






    return 1;
  }else{

    blob_reset(pName);
























    db_blob(pName, "SELECT uuid FROM blob WHERE rid=%d", rid);













    return 0;
  }














































}

/*
** COMMAND:  test-name-to-id
**
** Convert a name to a full artifact ID.
*/
282
283
284
285
286
287
288
289
290
291


292




293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
      fossil_print("%s\n", blob_buffer(&name));
    }
    blob_reset(&name);
  }
}

/*
** Convert a name to a rid.  If the name is a small integer value then
** just use atoi() to do the conversion.  If the name contains alphabetic
** characters or is not an existing rid, then use name_to_uuid then


** convert the uuid to a rid.




**
** This routine is used by command-line routines to resolve command-line inputs
** into a rid.
*/
int name_to_typed_rid(const char *zName, const char *zType){
  int i;
  int rid;
  Blob name;

  if( zName==0 || zName[0]==0 ) return 0;
  blob_init(&name, zName, -1);
  if( name_to_uuid(&name, -1, zType) ){
    blob_reset(&name);
    for(i=0; zName[i] && fossil_isdigit(zName[i]); i++){}
    if( zName[i]==0 ){
      rid = atoi(zName);
      if( db_exists("SELECT 1 FROM blob WHERE rid=%d", rid) ){
        return rid;
      }
    }
    fossil_error(1, "no such artifact: %s", zName);
    return 0;
  }else{
    rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%B", &name);
    blob_reset(&name);
  }
  return rid;
}
int name_to_rid(const char *zName){
  return name_to_typed_rid(zName, "*");
}

/*
** WEBPAGE: ambiguous







|
|
|
>
>
|
>
>
>
>





<

<


|
<
<
<
|
|
<
|
|
<
|


<
|

<







287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308

309

310
311
312



313
314

315
316

317
318
319

320
321

322
323
324
325
326
327
328
      fossil_print("%s\n", blob_buffer(&name));
    }
    blob_reset(&name);
  }
}

/*
** Convert a name to a rid.  If the name can be any of the various forms
** accepted:
**
**   * SHA1 hash or prefix thereof
**   * symbolic name
**   * date
**   * label:date
**   * prev, previous
**   * next
**   * tip
**
** This routine is used by command-line routines to resolve command-line inputs
** into a rid.
*/
int name_to_typed_rid(const char *zName, const char *zType){

  int rid;


  if( zName==0 || zName[0]==0 ) return 0;
  rid = symbolic_name_to_rid(zName, zType);



  if( rid<0 ){
    fossil_error(1, "ambiguous name: %s", zName);

    return 0;
  }else if( rid==0 ){

    fossil_error(1, "not found: %s", zName);
    return 0;
  }else{

    return rid;
  }

}
int name_to_rid(const char *zName){
  return name_to_typed_rid(zName, "*");
}

/*
** WEBPAGE: ambiguous
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
/*
** Convert the name in CGI parameter zParamName into a rid and return that
** rid.  If the CGI parameter is missing or is not a valid artifact tag,
** return 0.  If the CGI parameter is ambiguous, redirect to a page that
** shows all possibilities and do not return.
*/
int name_to_rid_www(const char *zParamName){
  int i, rc;
  int rid;
  const char *zName = P(zParamName);
  Blob name;
  if(!zName && fossil_has_json()){
    zName = json_find_option_cstr(zParamName,NULL,NULL);
  }
  if( zName==0 || zName[0]==0 ) return 0;
  blob_init(&name, zName, -1);
  rc = name_to_uuid(&name, -1, "*");
  if( rc==1 ){



    blob_reset(&name);

    for(i=0; zName[i] && fossil_isdigit(zName[i]); i++){}



















    if( zName[i]==0 ){







      rid = atoi(zName);








      if( db_exists("SELECT 1 FROM blob WHERE rid=%d", rid) ){
        return rid;
      }
    }
    return 0;
  }else if( rc==2 ){
    cgi_redirectf("%s/ambiguous/%T?src=%t", g.zTop, zName, g.zPath);
    return 0;
  }else{
    rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%B", &name);












    blob_reset(&name);


  }










  return rid;











}







<


<




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


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

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
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423


424

425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
/*
** Convert the name in CGI parameter zParamName into a rid and return that
** rid.  If the CGI parameter is missing or is not a valid artifact tag,
** return 0.  If the CGI parameter is ambiguous, redirect to a page that
** shows all possibilities and do not return.
*/
int name_to_rid_www(const char *zParamName){

  int rid;
  const char *zName = P(zParamName);

  if(!zName && fossil_has_json()){
    zName = json_find_option_cstr(zParamName,NULL,NULL);
  }
  if( zName==0 || zName[0]==0 ) return 0;

  rid = symbolic_name_to_rid(zName, "*");
  if( rid<0 ){
    cgi_redirectf("%s/ambiguous/%T?src=%t", g.zTop, zName, g.zPath);
    rid = 0;
  }
  return rid;
}

/*
** COMMAND: whatis*
** Usage: %fossil whatis NAME
**
** Resolve the symbol NAME into its canonical 40-character SHA1-hash
** artifact name and provide a description of what role that artifact
** plays.
*/
void whatis_cmd(void){
  int rid;
  const char *zName;
  int fExtra;
  db_find_and_open_repository(0,0);
  fExtra = find_option("verbose","v",0)!=0;
  if( g.argc!=3 ) usage("whatis NAME");
  zName = g.argv[2];
  rid = symbolic_name_to_rid(zName, 0);
  if( rid<0 ){
    fossil_print("Ambiguous artifact name prefix: %s\n", zName);
  }else if( rid==0 ){
    fossil_print("Unknown artifact: %s\n", zName);
  }else{
    Stmt q;
    db_prepare(&q, "SELECT uuid, size, datetime(mtime, 'localtime'), ipaddr"
                   "  FROM blob, rcvfrom"
                   " WHERE rid=%d"
                   "   AND rcvfrom.rcvid=blob.rcvid",
                   rid);
    if( db_step(&q)==SQLITE_ROW ){
      if( fExtra ){
        fossil_print("artifact: %s (%d)\n", db_column_text(&q,0), rid);
        fossil_print("size:     %d bytes\n", db_column_int(&q,1));
        fossil_print("received: %s from %s\n",
           db_column_text(&q, 2),
           db_column_text(&q, 3));
      }else{
        fossil_print("artifact: %s\n", db_column_text(&q,0));
        fossil_print("size:     %d bytes\n", db_column_int(&q,1));
      }
    }
    db_finalize(&q);


    db_prepare(&q,

       "SELECT type, datetime(mtime,'localtime'),"
       "       coalesce(euser,user), coalesce(ecomment,comment)"
       "  FROM event WHERE objid=%d", rid);
    if( db_step(&q)==SQLITE_ROW ){
      const char *zType;
      switch( db_column_text(&q,0)[0] ){
        case 'c':  zType = "Check-in";       break;
        case 'w':  zType = "Wiki-edit";      break;
        case 'e':  zType = "Event";          break;
        case 't':  zType = "Ticket-change";  break;
        case 'g':  zType = "Tag-change";     break;
      }
      fossil_print("type:     %s by %s on %s\n", zType, db_column_text(&q,2),
                   db_column_text(&q, 1));
      fossil_print("comment:  ");
      comment_print(db_column_text(&q,3), 10, 78);
    }
    db_finalize(&q);
    db_prepare(&q,
      "SELECT filename.name, blob.uuid, datetime(event.mtime,'localtime'),"
      "       coalesce(euser,user), coalesce(ecomment,comment)"
      "  FROM mlink, filename, blob, event"
      " WHERE mlink.fid=%d"
      "   AND filename.fnid=mlink.fnid"
      "   AND event.objid=mlink.mid"
      "   AND blob.rid=mlink.mid"
      " ORDER BY event.mtime DESC /*sort*/",
      rid);
    while( db_step(&q)==SQLITE_ROW ){
      fossil_print("file:     %s\n", db_column_text(&q,0));
      fossil_print("          part of [%.10s] by %s on %s\n",
        db_column_text(&q, 1),
        db_column_text(&q, 3),
        db_column_text(&q, 2));
      fossil_print("          ");
      comment_print(db_column_text(&q,4), 10, 78);
    }
    db_finalize(&q);
  }
}
Changes to src/rebuild.c.
368
369
370
371
372
373
374




375
376
377
378
379
380
381
382
  db_multi_exec(
     "DELETE FROM unclustered"
     " WHERE rid IN (SELECT rid FROM shun JOIN blob USING(uuid))"
  );
  db_multi_exec(
    "DELETE FROM config WHERE name IN ('remote-code', 'remote-maxid')"
  );




  totalSize = db_int(0, "SELECT count(*) FROM blob");
  incrSize = totalSize/100;
  totalSize += incrSize*2;
  db_prepare(&s,
     "SELECT rid, size FROM blob /*scan*/"
     " WHERE NOT EXISTS(SELECT 1 FROM shun WHERE uuid=blob.uuid)"
     "   AND NOT EXISTS(SELECT 1 FROM delta WHERE rid=blob.rid)"
  );







>
>
>
>
|







368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
  db_multi_exec(
     "DELETE FROM unclustered"
     " WHERE rid IN (SELECT rid FROM shun JOIN blob USING(uuid))"
  );
  db_multi_exec(
    "DELETE FROM config WHERE name IN ('remote-code', 'remote-maxid')"
  );

  /* The following should be count(*) instead of max(rid). max(rid) is
  ** an adequate approximation, however, and is much faster for large
  ** repositories. */
  totalSize = db_int(0, "SELECT max(rid) FROM blob");
  incrSize = totalSize/100;
  totalSize += incrSize*2;
  db_prepare(&s,
     "SELECT rid, size FROM blob /*scan*/"
     " WHERE NOT EXISTS(SELECT 1 FROM shun WHERE uuid=blob.uuid)"
     "   AND NOT EXISTS(SELECT 1 FROM delta WHERE rid=blob.rid)"
  );
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
  }
  db_finalize(&q);

  db_end_transaction(0);
}

/*
** COMMAND:  rebuild
**
** Usage: %fossil rebuild ?REPOSITORY? ?OPTIONS?
**
** Reconstruct the named repository database from the core
** records.  Run this command after updating the fossil
** executable in a way that changes the database schema.
**







|







485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
  }
  db_finalize(&q);

  db_end_transaction(0);
}

/*
** COMMAND: rebuild
**
** Usage: %fossil rebuild ?REPOSITORY? ?OPTIONS?
**
** Reconstruct the named repository database from the core
** records.  Run this command after updating the fossil
** executable in a way that changes the database schema.
**
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
      fossil_print("  %3d %s\n", db_column_int(&q,0), db_column_text(&q,1));
    }
    db_finalize(&q);
  }
}

/*
** COMMAND: scrub
** %fossil scrub ?OPTIONS? ?REPOSITORY?
**
** The command removes sensitive information (such as passwords) from a
** repository so that the respository can be sent to an untrusted reader.
**
** By default, only passwords are removed.  However, if the --verily option
** is added, then private branches, concealed email addresses, IP







|







718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
      fossil_print("  %3d %s\n", db_column_int(&q,0), db_column_text(&q,1));
    }
    db_finalize(&q);
  }
}

/*
** COMMAND: scrub*
** %fossil scrub ?OPTIONS? ?REPOSITORY?
**
** The command removes sensitive information (such as passwords) from a
** repository so that the respository can be sent to an untrusted reader.
**
** By default, only passwords are removed.  However, if the --verily option
** is added, then private branches, concealed email addresses, IP
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
    fossil_panic("encountered error %d while trying to open \"%s\".",
                  errno, g.argv[3]);
  }
  fossil_mbcs_free(zMbcsPath);
}

/*
** COMMAND: reconstruct
**
** Usage: %fossil reconstruct FILENAME DIRECTORY
**
** This command studies the artifacts (files) in DIRECTORY and
** reconstructs the fossil record from them. It places the new
** fossil repository in FILENAME. Subdirectories are read, files
** with leading '.' in the filename are ignored.







|







852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
    fossil_panic("encountered error %d while trying to open \"%s\".",
                  errno, g.argv[3]);
  }
  fossil_mbcs_free(zMbcsPath);
}

/*
** COMMAND: reconstruct*
**
** Usage: %fossil reconstruct FILENAME DIRECTORY
**
** This command studies the artifacts (files) in DIRECTORY and
** reconstructs the fossil record from them. It places the new
** fossil repository in FILENAME. Subdirectories are read, files
** with leading '.' in the filename are ignored.
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
  fossil_print("project-id: %s\n", db_get("project-code", 0));
  fossil_print("server-id: %s\n", db_get("server-code", 0));
  zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
  fossil_print("admin-user: %s (initial password is \"%s\")\n", g.zLogin, zPassword);
}

/*
** COMMAND: deconstruct
**
** Usage %fossil deconstruct ?OPTIONS? DESTINATION
**
**
** This command exports all artifacts of a given repository and
** writes all artifacts to the file system. The DESTINATION directory
** will be populated with subdirectories AA and files AA/BBBBBBBBB.., where







|







913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
  fossil_print("project-id: %s\n", db_get("project-code", 0));
  fossil_print("server-id: %s\n", db_get("server-code", 0));
  zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
  fossil_print("admin-user: %s (initial password is \"%s\")\n", g.zLogin, zPassword);
}

/*
** COMMAND: deconstruct*
**
** Usage %fossil deconstruct ?OPTIONS? DESTINATION
**
**
** This command exports all artifacts of a given repository and
** writes all artifacts to the file system. The DESTINATION directory
** will be populated with subdirectories AA and files AA/BBBBBBBBB.., where
Changes to src/search.c.
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
  sqlite3_create_function(g.db, "score", 1, SQLITE_UTF8, p,
     search_score_sqlfunc, 0, 0);
}

/*
** Testing the search function.
**
** COMMAND: search
** %fossil search pattern...
**
** Search for timeline entries matching the pattern.
*/
void search_cmd(void){
  Search *p;
  Blob pattern;







|







163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
  sqlite3_create_function(g.db, "score", 1, SQLITE_UTF8, p,
     search_score_sqlfunc, 0, 0);
}

/*
** Testing the search function.
**
** COMMAND: search*
** %fossil search pattern...
**
** Search for timeline entries matching the pattern.
*/
void search_cmd(void){
  Search *p;
  Blob pattern;
Changes to src/sha1.c.
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
    zProjid = 0;
  }
  sqlite3_result_text(context, sha1_shared_secret(zPw, zLogin, zProjid), -1,
                      fossil_free);
}

/*
** COMMAND: sha1sum
** %fossil sha1sum FILE...
**
** Compute an SHA1 checksum of all files named on the command-line.
** If an file is named "-" then take its content from standard input.
*/
void sha1sum_test(void){
  int i;







|







435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
    zProjid = 0;
  }
  sqlite3_result_text(context, sha1_shared_secret(zPw, zLogin, zProjid), -1,
                      fossil_free);
}

/*
** COMMAND: sha1sum*
** %fossil sha1sum FILE...
**
** Compute an SHA1 checksum of all files named on the command-line.
** If an file is named "-" then take its content from standard input.
*/
void sha1sum_test(void){
  int i;
Changes to src/sqlite3.c.
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
#ifdef HAVE_STDINT_H
#include <stdint.h>
#endif
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#endif

/*
** The number of samples of an index that SQLite takes in order to 
** construct a histogram of the table content when running ANALYZE
** and with SQLITE_ENABLE_STAT2
*/
#define SQLITE_INDEX_SAMPLES 10

/*
** The following macros are used to cast pointers to integers and
** integers to pointers.  The way you do this varies from one compiler
** to the next, so we have developed the following set of #if statements
** to generate appropriate macros for a wide range of compilers.
**
** The correct "ANSI" way to do this is to use the intptr_t type. 







<
<
<
<
<
<
<







312
313
314
315
316
317
318







319
320
321
322
323
324
325
#ifdef HAVE_STDINT_H
#include <stdint.h>
#endif
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#endif








/*
** The following macros are used to cast pointers to integers and
** integers to pointers.  The way you do this varies from one compiler
** to the next, so we have developed the following set of #if statements
** to generate appropriate macros for a wide range of compilers.
**
** The correct "ANSI" way to do this is to use the intptr_t type. 
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
**
** 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-20 00:55:54 4344483f7d7f64dffadde0053e6c745948db9486"

/*
** 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







|







647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
**
** 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
8790
8791
8792
8793
8794
8795
8796

8797
8798
8799
8800
8801
8802
8803
SQLITE_PRIVATE const sqlite3_vfs *sqlite3PagerVfs(Pager*);
SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager*);
SQLITE_PRIVATE const char *sqlite3PagerJournalname(Pager*);
SQLITE_PRIVATE int sqlite3PagerNosync(Pager*);
SQLITE_PRIVATE void *sqlite3PagerTempSpace(Pager*);
SQLITE_PRIVATE int sqlite3PagerIsMemdb(Pager*);
SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *, int, int, int *);


/* Functions used to truncate the database file. */
SQLITE_PRIVATE void sqlite3PagerTruncateImage(Pager*,Pgno);

#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_WAL)
SQLITE_PRIVATE void *sqlite3PagerCodec(DbPage *);
#endif







>







8783
8784
8785
8786
8787
8788
8789
8790
8791
8792
8793
8794
8795
8796
8797
SQLITE_PRIVATE const sqlite3_vfs *sqlite3PagerVfs(Pager*);
SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager*);
SQLITE_PRIVATE const char *sqlite3PagerJournalname(Pager*);
SQLITE_PRIVATE int sqlite3PagerNosync(Pager*);
SQLITE_PRIVATE void *sqlite3PagerTempSpace(Pager*);
SQLITE_PRIVATE int sqlite3PagerIsMemdb(Pager*);
SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *, int, int, int *);
SQLITE_PRIVATE void sqlite3PagerClearCache(Pager *);

/* Functions used to truncate the database file. */
SQLITE_PRIVATE void sqlite3PagerTruncateImage(Pager*,Pgno);

#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_WAL)
SQLITE_PRIVATE void *sqlite3PagerCodec(DbPage *);
#endif
10187
10188
10189
10190
10191
10192
10193
10194
10195

10196
10197
10198
10199
10200
10201
10202
  int nSample;             /* Number of elements in aSample[] */
  tRowcnt avgEq;           /* Average nEq value for key values not in aSample */
  IndexSample *aSample;    /* Samples of the left-most key */
#endif
};

/*
** Each sample stored in the sqlite_stat2 table is represented in memory 
** using a structure of this type.

*/
struct IndexSample {
  union {
    char *z;        /* Value if eType is SQLITE_TEXT or SQLITE_BLOB */
    double r;       /* Value if eType is SQLITE_FLOAT */
    i64 i;          /* Value if eType is SQLITE_INTEGER */
  } u;







|
|
>







10181
10182
10183
10184
10185
10186
10187
10188
10189
10190
10191
10192
10193
10194
10195
10196
10197
  int nSample;             /* Number of elements in aSample[] */
  tRowcnt avgEq;           /* Average nEq value for key values not in aSample */
  IndexSample *aSample;    /* Samples of the left-most key */
#endif
};

/*
** Each sample stored in the sqlite_stat3 table is represented in memory 
** using a structure of this type.  See documentation at the top of the
** analyze.c source file for additional information.
*/
struct IndexSample {
  union {
    char *z;        /* Value if eType is SQLITE_TEXT or SQLITE_BLOB */
    double r;       /* Value if eType is SQLITE_FLOAT */
    i64 i;          /* Value if eType is SQLITE_INTEGER */
  } u;
12291
12292
12293
12294
12295
12296
12297
12298
12299
12300
12301
12302
12303
12304
12305
12306
12307
#endif
#ifdef SQLITE_ENABLE_OVERSIZE_CELL_CHECK
  "ENABLE_OVERSIZE_CELL_CHECK",
#endif
#ifdef SQLITE_ENABLE_RTREE
  "ENABLE_RTREE",
#endif
#ifdef SQLITE_ENABLE_STAT2
  "ENABLE_STAT2",
#endif
#ifdef SQLITE_ENABLE_STAT3
  "ENABLE_STAT3",
#endif
#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
  "ENABLE_UNLOCK_NOTIFY",
#endif
#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT







<
<
<







12286
12287
12288
12289
12290
12291
12292



12293
12294
12295
12296
12297
12298
12299
#endif
#ifdef SQLITE_ENABLE_OVERSIZE_CELL_CHECK
  "ENABLE_OVERSIZE_CELL_CHECK",
#endif
#ifdef SQLITE_ENABLE_RTREE
  "ENABLE_RTREE",
#endif



#ifdef SQLITE_ENABLE_STAT3
  "ENABLE_STAT3",
#endif
#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
  "ENABLE_UNLOCK_NOTIFY",
#endif
#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
12994
12995
12996
12997
12998
12999
13000

13001
13002
13003
13004
13005
13006
13007
SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem*, FuncDef*);
SQLITE_PRIVATE const char *sqlite3OpcodeName(int);
SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve);
SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *, int);
SQLITE_PRIVATE void sqlite3VdbeFrameDelete(VdbeFrame*);
SQLITE_PRIVATE int sqlite3VdbeFrameRestore(VdbeFrame *);
SQLITE_PRIVATE void sqlite3VdbeMemStoreType(Mem *pMem);


#ifdef SQLITE_OMIT_MERGE_SORT
# define sqlite3VdbeSorterInit(Y,Z)      SQLITE_OK
# define sqlite3VdbeSorterWrite(X,Y,Z)   SQLITE_OK
# define sqlite3VdbeSorterClose(Y,Z)
# define sqlite3VdbeSorterRowkey(Y,Z)    SQLITE_OK
# define sqlite3VdbeSorterRewind(X,Y,Z)  SQLITE_OK







>







12986
12987
12988
12989
12990
12991
12992
12993
12994
12995
12996
12997
12998
12999
13000
SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem*, FuncDef*);
SQLITE_PRIVATE const char *sqlite3OpcodeName(int);
SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve);
SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *, int);
SQLITE_PRIVATE void sqlite3VdbeFrameDelete(VdbeFrame*);
SQLITE_PRIVATE int sqlite3VdbeFrameRestore(VdbeFrame *);
SQLITE_PRIVATE void sqlite3VdbeMemStoreType(Mem *pMem);
SQLITE_PRIVATE int sqlite3VdbeTransferError(Vdbe *p);

#ifdef SQLITE_OMIT_MERGE_SORT
# define sqlite3VdbeSorterInit(Y,Z)      SQLITE_OK
# define sqlite3VdbeSorterWrite(X,Y,Z)   SQLITE_OK
# define sqlite3VdbeSorterClose(Y,Z)
# define sqlite3VdbeSorterRowkey(Y,Z)    SQLITE_OK
# define sqlite3VdbeSorterRewind(X,Y,Z)  SQLITE_OK
29481
29482
29483
29484
29485
29486
29487
29488
29489
29490
29491
29492
29493
29494
29495
29496
29497
29498
29499
29500
29501
    ** the following naming conventions:
    **
    **   "<path to db>-journal"
    **   "<path to db>-wal"
    **   "<path to db>-journalNN"
    **   "<path to db>-walNN"
    **
    ** where NN is a 4 digit decimal number. The NN naming schemes are 
    ** used by the test_multiplex.c module.
    */
    nDb = sqlite3Strlen30(zPath) - 1; 
#ifdef SQLITE_ENABLE_8_3_NAMES
    while( nDb>0 && zPath[nDb]!='-' && zPath[nDb]!='/' ) nDb--;
    if( nDb==0 || zPath[nDb]=='/' ) return SQLITE_OK;
#else
    while( zPath[nDb]!='-' ){
      assert( nDb>0 );
      assert( zPath[nDb]!='\n' );
      nDb--;
    }
#endif







|




|
|







29474
29475
29476
29477
29478
29479
29480
29481
29482
29483
29484
29485
29486
29487
29488
29489
29490
29491
29492
29493
29494
    ** the following naming conventions:
    **
    **   "<path to db>-journal"
    **   "<path to db>-wal"
    **   "<path to db>-journalNN"
    **   "<path to db>-walNN"
    **
    ** where NN is a decimal number. The NN naming schemes are 
    ** used by the test_multiplex.c module.
    */
    nDb = sqlite3Strlen30(zPath) - 1; 
#ifdef SQLITE_ENABLE_8_3_NAMES
    while( nDb>0 && !sqlite3Isalnum(zPath[nDb]) ) nDb--;
    if( nDb==0 || zPath[nDb]!='-' ) return SQLITE_OK;
#else
    while( zPath[nDb]!='-' ){
      assert( nDb>0 );
      assert( zPath[nDb]!='\n' );
      nDb--;
    }
#endif
44161
44162
44163
44164
44165
44166
44167







44168
44169
44170
44171
44172
44173
44174
      rc = sqlite3WalClose(pPager->pWal, pPager->ckptSyncFlags,
                           pPager->pageSize, (u8*)pPager->pTmpSpace);
      pPager->pWal = 0;
    }
  }
  return rc;
}








#ifdef SQLITE_HAS_CODEC
/*
** This function is called by the wal module when writing page content
** into the log file.
**
** This function returns a pointer to a buffer containing the encrypted







>
>
>
>
>
>
>







44154
44155
44156
44157
44158
44159
44160
44161
44162
44163
44164
44165
44166
44167
44168
44169
44170
44171
44172
44173
44174
      rc = sqlite3WalClose(pPager->pWal, pPager->ckptSyncFlags,
                           pPager->pageSize, (u8*)pPager->pTmpSpace);
      pPager->pWal = 0;
    }
  }
  return rc;
}

/*
** Unless this is an in-memory or temporary database, clear the pager cache.
*/
SQLITE_PRIVATE void sqlite3PagerClearCache(Pager *pPager){
  if( !MEMDB && pPager->tempFile==0 ) pager_reset(pPager);
}

#ifdef SQLITE_HAS_CODEC
/*
** This function is called by the wal module when writing page content
** into the log file.
**
** This function returns a pointer to a buffer containing the encrypted
57004
57005
57006
57007
57008
57009
57010


57011
57012
57013
57014
57015
57016
57017
  ** or an error code.
  */
  sqlite3_backup_step(&b, 0x7FFFFFFF);
  assert( b.rc!=SQLITE_OK );
  rc = sqlite3_backup_finish(&b);
  if( rc==SQLITE_OK ){
    pTo->pBt->pageSizeFixed = 0;


  }

  assert( sqlite3BtreeIsInTrans(pTo)==0 );
  sqlite3BtreeLeave(pFrom);
  sqlite3BtreeLeave(pTo);
  return rc;
}







>
>







57004
57005
57006
57007
57008
57009
57010
57011
57012
57013
57014
57015
57016
57017
57018
57019
  ** or an error code.
  */
  sqlite3_backup_step(&b, 0x7FFFFFFF);
  assert( b.rc!=SQLITE_OK );
  rc = sqlite3_backup_finish(&b);
  if( rc==SQLITE_OK ){
    pTo->pBt->pageSizeFixed = 0;
  }else{
    sqlite3PagerClearCache(sqlite3BtreePager(b.pDest));
  }

  assert( sqlite3BtreeIsInTrans(pTo)==0 );
  sqlite3BtreeLeave(pFrom);
  sqlite3BtreeLeave(pTo);
  return rc;
}
60478
60479
60480
60481
60482
60483
60484
























60485
60486
60487
60488
60489
60490
60491
/*
** Each VDBE holds the result of the most recent sqlite3_step() call
** in p->rc.  This routine sets that result back to SQLITE_OK.
*/
SQLITE_PRIVATE void sqlite3VdbeResetStepResult(Vdbe *p){
  p->rc = SQLITE_OK;
}

























/*
** Clean up a VDBE after execution but do not delete the VDBE just yet.
** Write any error messages into *pzErrMsg.  Return the result code.
**
** After this routine is run, the VDBE should be ready to be executed
** again.







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







60480
60481
60482
60483
60484
60485
60486
60487
60488
60489
60490
60491
60492
60493
60494
60495
60496
60497
60498
60499
60500
60501
60502
60503
60504
60505
60506
60507
60508
60509
60510
60511
60512
60513
60514
60515
60516
60517
/*
** Each VDBE holds the result of the most recent sqlite3_step() call
** in p->rc.  This routine sets that result back to SQLITE_OK.
*/
SQLITE_PRIVATE void sqlite3VdbeResetStepResult(Vdbe *p){
  p->rc = SQLITE_OK;
}

/*
** Copy the error code and error message belonging to the VDBE passed
** as the first argument to its database handle (so that they will be 
** returned by calls to sqlite3_errcode() and sqlite3_errmsg()).
**
** This function does not clear the VDBE error code or message, just
** copies them to the database handle.
*/
SQLITE_PRIVATE int sqlite3VdbeTransferError(Vdbe *p){
  sqlite3 *db = p->db;
  int rc = p->rc;
  if( p->zErrMsg ){
    u8 mallocFailed = db->mallocFailed;
    sqlite3BeginBenignMalloc();
    sqlite3ValueSetStr(db->pErr, -1, p->zErrMsg, SQLITE_UTF8, SQLITE_TRANSIENT);
    sqlite3EndBenignMalloc();
    db->mallocFailed = mallocFailed;
    db->errCode = rc;
  }else{
    sqlite3Error(db, rc, 0);
  }
  return rc;
}

/*
** Clean up a VDBE after execution but do not delete the VDBE just yet.
** Write any error messages into *pzErrMsg.  Return the result code.
**
** After this routine is run, the VDBE should be ready to be executed
** again.
60506
60507
60508
60509
60510
60511
60512
60513
60514
60515
60516
60517
60518
60519
60520
60521
60522
60523
60524
60525
60526
60527
60528
60529
60530
60531

  /* If the VDBE has be run even partially, then transfer the error code
  ** and error message from the VDBE into the main database structure.  But
  ** if the VDBE has just been set to run but has not actually executed any
  ** instructions yet, leave the main database error information unchanged.
  */
  if( p->pc>=0 ){
    if( p->zErrMsg ){
      sqlite3BeginBenignMalloc();
      sqlite3ValueSetStr(db->pErr,-1,p->zErrMsg,SQLITE_UTF8,SQLITE_TRANSIENT);
      sqlite3EndBenignMalloc();
      db->errCode = p->rc;
      sqlite3DbFree(db, p->zErrMsg);
      p->zErrMsg = 0;
    }else if( p->rc ){
      sqlite3Error(db, p->rc, 0);
    }else{
      sqlite3Error(db, SQLITE_OK, 0);
    }
    if( p->runOnlyOnce ) p->expired = 1;
  }else if( p->rc && p->expired ){
    /* The expired flag was set on the VDBE before the first call
    ** to sqlite3_step(). For consistency (since sqlite3_step() was
    ** called), set the database error in this case as well.
    */
    sqlite3Error(db, p->rc, 0);







<
<
<
|
<
|
|
<
<
<
<
<







60532
60533
60534
60535
60536
60537
60538



60539

60540
60541





60542
60543
60544
60545
60546
60547
60548

  /* If the VDBE has be run even partially, then transfer the error code
  ** and error message from the VDBE into the main database structure.  But
  ** if the VDBE has just been set to run but has not actually executed any
  ** instructions yet, leave the main database error information unchanged.
  */
  if( p->pc>=0 ){



    sqlite3VdbeTransferError(p);

    sqlite3DbFree(db, p->zErrMsg);
    p->zErrMsg = 0;





    if( p->runOnlyOnce ) p->expired = 1;
  }else if( p->rc && p->expired ){
    /* The expired flag was set on the VDBE before the first call
    ** to sqlite3_step(). For consistency (since sqlite3_step() was
    ** called), set the database error in this case as well.
    */
    sqlite3Error(db, p->rc, 0);
61863
61864
61865
61866
61867
61868
61869
61870
61871
61872
61873
61874
61875
61876
61877
  );
  assert( p->rc!=SQLITE_ROW && p->rc!=SQLITE_DONE );
  if( p->isPrepareV2 && rc!=SQLITE_ROW && rc!=SQLITE_DONE ){
    /* If this statement was prepared using sqlite3_prepare_v2(), and an
    ** error has occured, then return the error code in p->rc to the
    ** caller. Set the error code in the database handle to the same value.
    */ 
    rc = db->errCode = p->rc;
  }
  return (rc&db->errMask);
}

/*
** The maximum number of times that a statement will try to reparse
** itself before giving up and returning SQLITE_SCHEMA.







|







61880
61881
61882
61883
61884
61885
61886
61887
61888
61889
61890
61891
61892
61893
61894
  );
  assert( p->rc!=SQLITE_ROW && p->rc!=SQLITE_DONE );
  if( p->isPrepareV2 && rc!=SQLITE_ROW && rc!=SQLITE_DONE ){
    /* If this statement was prepared using sqlite3_prepare_v2(), and an
    ** error has occured, then return the error code in p->rc to the
    ** caller. Set the error code in the database handle to the same value.
    */ 
    rc = sqlite3VdbeTransferError(p);
  }
  return (rc&db->errMask);
}

/*
** The maximum number of times that a statement will try to reparse
** itself before giving up and returning SQLITE_SCHEMA.
67763
67764
67765
67766
67767
67768
67769
67770
67771
67772

67773
67774
67775
67776
67777
67778
67779
  int res;
#endif /* local variables moved into u.bn */

  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  u.bn.pC = p->apCsr[pOp->p1];
  assert( u.bn.pC!=0 );
  u.bn.pCrsr = u.bn.pC->pCursor;
  if( NEVER(u.bn.pCrsr==0) ){
    u.bn.res = 1;
  }else{

    rc = sqlite3BtreeLast(u.bn.pCrsr, &u.bn.res);
  }
  u.bn.pC->nullRow = (u8)u.bn.res;
  u.bn.pC->deferredMoveto = 0;
  u.bn.pC->rowidIsValid = 0;
  u.bn.pC->cacheStatus = CACHE_STALE;
  if( pOp->p2>0 && u.bn.res ){







<
|
<
>







67780
67781
67782
67783
67784
67785
67786

67787

67788
67789
67790
67791
67792
67793
67794
67795
  int res;
#endif /* local variables moved into u.bn */

  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  u.bn.pC = p->apCsr[pOp->p1];
  assert( u.bn.pC!=0 );
  u.bn.pCrsr = u.bn.pC->pCursor;

  u.bn.res = 0;

  if( ALWAYS(u.bn.pCrsr!=0) ){
    rc = sqlite3BtreeLast(u.bn.pCrsr, &u.bn.res);
  }
  u.bn.pC->nullRow = (u8)u.bn.res;
  u.bn.pC->deferredMoveto = 0;
  u.bn.pC->rowidIsValid = 0;
  u.bn.pC->cacheStatus = CACHE_STALE;
  if( pOp->p2>0 && u.bn.res ){
77608
77609
77610
77611
77612
77613
77614
77615
77616
77617
77618
77619
77620
77621
77622
77623
77624
77625
77626
77627
77628
77629
77630
77631
** largest possible nEq values.
*/
#ifndef SQLITE_OMIT_ANALYZE

/*
** This routine generates code that opens the sqlite_stat1 table for
** writing with cursor iStatCur. If the library was built with the
** SQLITE_ENABLE_STAT2 macro defined, then the sqlite_stat2 table is
** opened for writing using cursor (iStatCur+1)
**
** If the sqlite_stat1 tables does not previously exist, it is created.
** Similarly, if the sqlite_stat2 table does not exist and the library
** is compiled with SQLITE_ENABLE_STAT2 defined, it is created. 
**
** Argument zWhere may be a pointer to a buffer containing a table name,
** or it may be a NULL pointer. If it is not NULL, then all entries in
** the sqlite_stat1 and (if applicable) sqlite_stat2 tables associated
** with the named table are deleted. If zWhere==0, then code is generated
** to delete all stat table entries.
*/
static void openStatTable(
  Parse *pParse,          /* Parsing context */
  int iDb,                /* The database we are looking in */
  int iStatCur,           /* Open the sqlite_stat1 table on this cursor */







|



|
|



|







77624
77625
77626
77627
77628
77629
77630
77631
77632
77633
77634
77635
77636
77637
77638
77639
77640
77641
77642
77643
77644
77645
77646
77647
** largest possible nEq values.
*/
#ifndef SQLITE_OMIT_ANALYZE

/*
** This routine generates code that opens the sqlite_stat1 table for
** writing with cursor iStatCur. If the library was built with the
** SQLITE_ENABLE_STAT3 macro defined, then the sqlite_stat3 table is
** opened for writing using cursor (iStatCur+1)
**
** If the sqlite_stat1 tables does not previously exist, it is created.
** Similarly, if the sqlite_stat3 table does not exist and the library
** is compiled with SQLITE_ENABLE_STAT3 defined, it is created. 
**
** Argument zWhere may be a pointer to a buffer containing a table name,
** or it may be a NULL pointer. If it is not NULL, then all entries in
** the sqlite_stat1 and (if applicable) sqlite_stat3 tables associated
** with the named table are deleted. If zWhere==0, then code is generated
** to delete all stat table entries.
*/
static void openStatTable(
  Parse *pParse,          /* Parsing context */
  int iDb,                /* The database we are looking in */
  int iStatCur,           /* Open the sqlite_stat1 table on this cursor */
81402
81403
81404
81405
81406
81407
81408
81409
81410
81411
81412
81413
81414
81415
81416
81417
81418
81419
81420
81421
81422
81423
81424
81425


81426
81427
81428
81429
81430
81431
81432
81433
81434
81435
81436
      iDestroyed = iLargest;
    }
  }
#endif
}

/*
** Remove entries from the sqlite_stat1 and sqlite_stat2 tables
** after a DROP INDEX or DROP TABLE command.
*/
static void sqlite3ClearStatTables(
  Parse *pParse,         /* The parsing context */
  int iDb,               /* The database number */
  const char *zType,     /* "idx" or "tbl" */
  const char *zName      /* Name of index or table */
){
  static const char *azStatTab[] = { 
    "sqlite_stat1",
    "sqlite_stat2",
    "sqlite_stat3",
  };
  int i;
  const char *zDbName = pParse->db->aDb[iDb].zName;
  for(i=0; i<ArraySize(azStatTab); i++){


    if( sqlite3FindTable(pParse->db, azStatTab[i], zDbName) ){
      sqlite3NestedParse(pParse,
        "DELETE FROM %Q.%s WHERE %s=%Q",
        zDbName, azStatTab[i], zType, zName
      );
    }
  }
}

/*
** Generate code to drop a table.







|








<
<
<
<
<


|
>
>
|


|







81418
81419
81420
81421
81422
81423
81424
81425
81426
81427
81428
81429
81430
81431
81432
81433





81434
81435
81436
81437
81438
81439
81440
81441
81442
81443
81444
81445
81446
81447
81448
81449
      iDestroyed = iLargest;
    }
  }
#endif
}

/*
** Remove entries from the sqlite_statN tables (for N in (1,2,3))
** after a DROP INDEX or DROP TABLE command.
*/
static void sqlite3ClearStatTables(
  Parse *pParse,         /* The parsing context */
  int iDb,               /* The database number */
  const char *zType,     /* "idx" or "tbl" */
  const char *zName      /* Name of index or table */
){





  int i;
  const char *zDbName = pParse->db->aDb[iDb].zName;
  for(i=1; i<=3; i++){
    char zTab[24];
    sqlite3_snprintf(sizeof(zTab),zTab,"sqlite_stat%d",i);
    if( sqlite3FindTable(pParse->db, zTab, zDbName) ){
      sqlite3NestedParse(pParse,
        "DELETE FROM %Q.%s WHERE %s=%Q",
        zDbName, zTab, zType, zName
      );
    }
  }
}

/*
** Generate code to drop a table.
89248
89249
89250
89251
89252
89253
89254
89255

89256

89257
89258
89259
89260
89261
89262
89263
  int  (*bind_text)(sqlite3_stmt*,int,const char*,int n,void(*)(void*));
  int  (*bind_text16)(sqlite3_stmt*,int,const void*,int,void(*)(void*));
  int  (*bind_value)(sqlite3_stmt*,int,const sqlite3_value*);
  int  (*busy_handler)(sqlite3*,int(*)(void*,int),void*);
  int  (*busy_timeout)(sqlite3*,int ms);
  int  (*changes)(sqlite3*);
  int  (*close)(sqlite3*);
  int  (*collation_needed)(sqlite3*,void*,void(*)(void*,sqlite3*,int eTextRep,const char*));

  int  (*collation_needed16)(sqlite3*,void*,void(*)(void*,sqlite3*,int eTextRep,const void*));

  const void * (*column_blob)(sqlite3_stmt*,int iCol);
  int  (*column_bytes)(sqlite3_stmt*,int iCol);
  int  (*column_bytes16)(sqlite3_stmt*,int iCol);
  int  (*column_count)(sqlite3_stmt*pStmt);
  const char * (*column_database_name)(sqlite3_stmt*,int);
  const void * (*column_database_name16)(sqlite3_stmt*,int);
  const char * (*column_decltype)(sqlite3_stmt*,int i);







|
>
|
>







89261
89262
89263
89264
89265
89266
89267
89268
89269
89270
89271
89272
89273
89274
89275
89276
89277
89278
  int  (*bind_text)(sqlite3_stmt*,int,const char*,int n,void(*)(void*));
  int  (*bind_text16)(sqlite3_stmt*,int,const void*,int,void(*)(void*));
  int  (*bind_value)(sqlite3_stmt*,int,const sqlite3_value*);
  int  (*busy_handler)(sqlite3*,int(*)(void*,int),void*);
  int  (*busy_timeout)(sqlite3*,int ms);
  int  (*changes)(sqlite3*);
  int  (*close)(sqlite3*);
  int  (*collation_needed)(sqlite3*,void*,void(*)(void*,sqlite3*,
                           int eTextRep,const char*));
  int  (*collation_needed16)(sqlite3*,void*,void(*)(void*,sqlite3*,
                             int eTextRep,const void*));
  const void * (*column_blob)(sqlite3_stmt*,int iCol);
  int  (*column_bytes)(sqlite3_stmt*,int iCol);
  int  (*column_bytes16)(sqlite3_stmt*,int iCol);
  int  (*column_count)(sqlite3_stmt*pStmt);
  const char * (*column_database_name)(sqlite3_stmt*,int);
  const void * (*column_database_name16)(sqlite3_stmt*,int);
  const char * (*column_decltype)(sqlite3_stmt*,int i);
89274
89275
89276
89277
89278
89279
89280
89281

89282

89283



89284



89285
89286
89287
89288
89289
89290
89291
  const unsigned char * (*column_text)(sqlite3_stmt*,int iCol);
  const void * (*column_text16)(sqlite3_stmt*,int iCol);
  int  (*column_type)(sqlite3_stmt*,int iCol);
  sqlite3_value* (*column_value)(sqlite3_stmt*,int iCol);
  void * (*commit_hook)(sqlite3*,int(*)(void*),void*);
  int  (*complete)(const char*sql);
  int  (*complete16)(const void*sql);
  int  (*create_collation)(sqlite3*,const char*,int,void*,int(*)(void*,int,const void*,int,const void*));

  int  (*create_collation16)(sqlite3*,const void*,int,void*,int(*)(void*,int,const void*,int,const void*));

  int  (*create_function)(sqlite3*,const char*,int,int,void*,void (*xFunc)(sqlite3_context*,int,sqlite3_value**),void (*xStep)(sqlite3_context*,int,sqlite3_value**),void (*xFinal)(sqlite3_context*));



  int  (*create_function16)(sqlite3*,const void*,int,int,void*,void (*xFunc)(sqlite3_context*,int,sqlite3_value**),void (*xStep)(sqlite3_context*,int,sqlite3_value**),void (*xFinal)(sqlite3_context*));



  int (*create_module)(sqlite3*,const char*,const sqlite3_module*,void*);
  int  (*data_count)(sqlite3_stmt*pStmt);
  sqlite3 * (*db_handle)(sqlite3_stmt*);
  int (*declare_vtab)(sqlite3*,const char*);
  int  (*enable_shared_cache)(int);
  int  (*errcode)(sqlite3*db);
  const char * (*errmsg)(sqlite3*);







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







89289
89290
89291
89292
89293
89294
89295
89296
89297
89298
89299
89300
89301
89302
89303
89304
89305
89306
89307
89308
89309
89310
89311
89312
89313
89314
  const unsigned char * (*column_text)(sqlite3_stmt*,int iCol);
  const void * (*column_text16)(sqlite3_stmt*,int iCol);
  int  (*column_type)(sqlite3_stmt*,int iCol);
  sqlite3_value* (*column_value)(sqlite3_stmt*,int iCol);
  void * (*commit_hook)(sqlite3*,int(*)(void*),void*);
  int  (*complete)(const char*sql);
  int  (*complete16)(const void*sql);
  int  (*create_collation)(sqlite3*,const char*,int,void*,
                           int(*)(void*,int,const void*,int,const void*));
  int  (*create_collation16)(sqlite3*,const void*,int,void*,
                             int(*)(void*,int,const void*,int,const void*));
  int  (*create_function)(sqlite3*,const char*,int,int,void*,
                          void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
                          void (*xStep)(sqlite3_context*,int,sqlite3_value**),
                          void (*xFinal)(sqlite3_context*));
  int  (*create_function16)(sqlite3*,const void*,int,int,void*,
                            void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
                            void (*xStep)(sqlite3_context*,int,sqlite3_value**),
                            void (*xFinal)(sqlite3_context*));
  int (*create_module)(sqlite3*,const char*,const sqlite3_module*,void*);
  int  (*data_count)(sqlite3_stmt*pStmt);
  sqlite3 * (*db_handle)(sqlite3_stmt*);
  int (*declare_vtab)(sqlite3*,const char*);
  int  (*enable_shared_cache)(int);
  int  (*errcode)(sqlite3*db);
  const char * (*errmsg)(sqlite3*);
89322
89323
89324
89325
89326
89327
89328
89329

89330
89331
89332
89333

89334
89335
89336
89337
89338

89339
89340
89341
89342
89343
89344
89345
  void  (*result_null)(sqlite3_context*);
  void  (*result_text)(sqlite3_context*,const char*,int,void(*)(void*));
  void  (*result_text16)(sqlite3_context*,const void*,int,void(*)(void*));
  void  (*result_text16be)(sqlite3_context*,const void*,int,void(*)(void*));
  void  (*result_text16le)(sqlite3_context*,const void*,int,void(*)(void*));
  void  (*result_value)(sqlite3_context*,sqlite3_value*);
  void * (*rollback_hook)(sqlite3*,void(*)(void*),void*);
  int  (*set_authorizer)(sqlite3*,int(*)(void*,int,const char*,const char*,const char*,const char*),void*);

  void  (*set_auxdata)(sqlite3_context*,int,void*,void (*)(void*));
  char * (*snprintf)(int,char*,const char*,...);
  int  (*step)(sqlite3_stmt*);
  int  (*table_column_metadata)(sqlite3*,const char*,const char*,const char*,char const**,char const**,int*,int*,int*);

  void  (*thread_cleanup)(void);
  int  (*total_changes)(sqlite3*);
  void * (*trace)(sqlite3*,void(*xTrace)(void*,const char*),void*);
  int  (*transfer_bindings)(sqlite3_stmt*,sqlite3_stmt*);
  void * (*update_hook)(sqlite3*,void(*)(void*,int ,char const*,char const*,sqlite_int64),void*);

  void * (*user_data)(sqlite3_context*);
  const void * (*value_blob)(sqlite3_value*);
  int  (*value_bytes)(sqlite3_value*);
  int  (*value_bytes16)(sqlite3_value*);
  double  (*value_double)(sqlite3_value*);
  int  (*value_int)(sqlite3_value*);
  sqlite_int64  (*value_int64)(sqlite3_value*);







|
>



|
>




|
>







89345
89346
89347
89348
89349
89350
89351
89352
89353
89354
89355
89356
89357
89358
89359
89360
89361
89362
89363
89364
89365
89366
89367
89368
89369
89370
89371
  void  (*result_null)(sqlite3_context*);
  void  (*result_text)(sqlite3_context*,const char*,int,void(*)(void*));
  void  (*result_text16)(sqlite3_context*,const void*,int,void(*)(void*));
  void  (*result_text16be)(sqlite3_context*,const void*,int,void(*)(void*));
  void  (*result_text16le)(sqlite3_context*,const void*,int,void(*)(void*));
  void  (*result_value)(sqlite3_context*,sqlite3_value*);
  void * (*rollback_hook)(sqlite3*,void(*)(void*),void*);
  int  (*set_authorizer)(sqlite3*,int(*)(void*,int,const char*,const char*,
                         const char*,const char*),void*);
  void  (*set_auxdata)(sqlite3_context*,int,void*,void (*)(void*));
  char * (*snprintf)(int,char*,const char*,...);
  int  (*step)(sqlite3_stmt*);
  int  (*table_column_metadata)(sqlite3*,const char*,const char*,const char*,
                                char const**,char const**,int*,int*,int*);
  void  (*thread_cleanup)(void);
  int  (*total_changes)(sqlite3*);
  void * (*trace)(sqlite3*,void(*xTrace)(void*,const char*),void*);
  int  (*transfer_bindings)(sqlite3_stmt*,sqlite3_stmt*);
  void * (*update_hook)(sqlite3*,void(*)(void*,int ,char const*,char const*,
                                         sqlite_int64),void*);
  void * (*user_data)(sqlite3_context*);
  const void * (*value_blob)(sqlite3_value*);
  int  (*value_bytes)(sqlite3_value*);
  int  (*value_bytes16)(sqlite3_value*);
  double  (*value_double)(sqlite3_value*);
  int  (*value_int)(sqlite3_value*);
  sqlite_int64  (*value_int64)(sqlite3_value*);
89353
89354
89355
89356
89357
89358
89359
89360

89361
89362
89363
89364
89365

89366
89367
89368


89369
89370
89371
89372
89373
89374
89375
  /* Added ??? */
  int (*overload_function)(sqlite3*, const char *zFuncName, int nArg);
  /* Added by 3.3.13 */
  int (*prepare_v2)(sqlite3*,const char*,int,sqlite3_stmt**,const char**);
  int (*prepare16_v2)(sqlite3*,const void*,int,sqlite3_stmt**,const void**);
  int (*clear_bindings)(sqlite3_stmt*);
  /* Added by 3.4.1 */
  int (*create_module_v2)(sqlite3*,const char*,const sqlite3_module*,void*,void (*xDestroy)(void *));

  /* Added by 3.5.0 */
  int (*bind_zeroblob)(sqlite3_stmt*,int,int);
  int (*blob_bytes)(sqlite3_blob*);
  int (*blob_close)(sqlite3_blob*);
  int (*blob_open)(sqlite3*,const char*,const char*,const char*,sqlite3_int64,int,sqlite3_blob**);

  int (*blob_read)(sqlite3_blob*,void*,int,int);
  int (*blob_write)(sqlite3_blob*,const void*,int,int);
  int (*create_collation_v2)(sqlite3*,const char*,int,void*,int(*)(void*,int,const void*,int,const void*),void(*)(void*));


  int (*file_control)(sqlite3*,const char*,int,void*);
  sqlite3_int64 (*memory_highwater)(int);
  sqlite3_int64 (*memory_used)(void);
  sqlite3_mutex *(*mutex_alloc)(int);
  void (*mutex_enter)(sqlite3_mutex*);
  void (*mutex_free)(sqlite3_mutex*);
  void (*mutex_leave)(sqlite3_mutex*);







|
>




|
>


|
>
>







89379
89380
89381
89382
89383
89384
89385
89386
89387
89388
89389
89390
89391
89392
89393
89394
89395
89396
89397
89398
89399
89400
89401
89402
89403
89404
89405
  /* Added ??? */
  int (*overload_function)(sqlite3*, const char *zFuncName, int nArg);
  /* Added by 3.3.13 */
  int (*prepare_v2)(sqlite3*,const char*,int,sqlite3_stmt**,const char**);
  int (*prepare16_v2)(sqlite3*,const void*,int,sqlite3_stmt**,const void**);
  int (*clear_bindings)(sqlite3_stmt*);
  /* Added by 3.4.1 */
  int (*create_module_v2)(sqlite3*,const char*,const sqlite3_module*,void*,
                          void (*xDestroy)(void *));
  /* Added by 3.5.0 */
  int (*bind_zeroblob)(sqlite3_stmt*,int,int);
  int (*blob_bytes)(sqlite3_blob*);
  int (*blob_close)(sqlite3_blob*);
  int (*blob_open)(sqlite3*,const char*,const char*,const char*,sqlite3_int64,
                   int,sqlite3_blob**);
  int (*blob_read)(sqlite3_blob*,void*,int,int);
  int (*blob_write)(sqlite3_blob*,const void*,int,int);
  int (*create_collation_v2)(sqlite3*,const char*,int,void*,
                             int(*)(void*,int,const void*,int,const void*),
                             void(*)(void*));
  int (*file_control)(sqlite3*,const char*,int,void*);
  sqlite3_int64 (*memory_highwater)(int);
  sqlite3_int64 (*memory_used)(void);
  sqlite3_mutex *(*mutex_alloc)(int);
  void (*mutex_enter)(sqlite3_mutex*);
  void (*mutex_free)(sqlite3_mutex*);
  void (*mutex_leave)(sqlite3_mutex*);
89397
89398
89399
89400
89401
89402
89403
89404




89405
89406
89407
89408
89409
89410
89411
  int (*backup_finish)(sqlite3_backup*);
  sqlite3_backup *(*backup_init)(sqlite3*,const char*,sqlite3*,const char*);
  int (*backup_pagecount)(sqlite3_backup*);
  int (*backup_remaining)(sqlite3_backup*);
  int (*backup_step)(sqlite3_backup*,int);
  const char *(*compileoption_get)(int);
  int (*compileoption_used)(const char*);
  int (*create_function_v2)(sqlite3*,const char*,int,int,void*,void (*xFunc)(sqlite3_context*,int,sqlite3_value**),void (*xStep)(sqlite3_context*,int,sqlite3_value**),void (*xFinal)(sqlite3_context*),void(*xDestroy)(void*));




  int (*db_config)(sqlite3*,int,...);
  sqlite3_mutex *(*db_mutex)(sqlite3*);
  int (*db_status)(sqlite3*,int,int*,int*,int);
  int (*extended_errcode)(sqlite3*);
  void (*log)(int,const char*,...);
  sqlite3_int64 (*soft_heap_limit64)(sqlite3_int64);
  const char *(*sourceid)(void);







|
>
>
>
>







89427
89428
89429
89430
89431
89432
89433
89434
89435
89436
89437
89438
89439
89440
89441
89442
89443
89444
89445
  int (*backup_finish)(sqlite3_backup*);
  sqlite3_backup *(*backup_init)(sqlite3*,const char*,sqlite3*,const char*);
  int (*backup_pagecount)(sqlite3_backup*);
  int (*backup_remaining)(sqlite3_backup*);
  int (*backup_step)(sqlite3_backup*,int);
  const char *(*compileoption_get)(int);
  int (*compileoption_used)(const char*);
  int (*create_function_v2)(sqlite3*,const char*,int,int,void*,
                            void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
                            void (*xStep)(sqlite3_context*,int,sqlite3_value**),
                            void (*xFinal)(sqlite3_context*),
                            void(*xDestroy)(void*));
  int (*db_config)(sqlite3*,int,...);
  sqlite3_mutex *(*db_mutex)(sqlite3*);
  int (*db_status)(sqlite3*,int,int*,int*,int);
  int (*extended_errcode)(sqlite3*);
  void (*log)(int,const char*,...);
  sqlite3_int64 (*soft_heap_limit64)(sqlite3_int64);
  const char *(*sourceid)(void);
100483
100484
100485
100486
100487
100488
100489
100490
100491
100492
100493
100494
100495
100496
100497
100498
100499
100500
100501
100502
100503
100504
100505
100506
100507
100508
100509
100510
100511
100512
  assert( op==SAVEPOINT_RELEASE||op==SAVEPOINT_ROLLBACK||op==SAVEPOINT_BEGIN );
  assert( iSavepoint>=0 );
  if( db->aVTrans ){
    int i;
    for(i=0; rc==SQLITE_OK && i<db->nVTrans; i++){
      VTable *pVTab = db->aVTrans[i];
      const sqlite3_module *pMod = pVTab->pMod->pModule;
      if( pMod->iVersion>=2 ){
        int (*xMethod)(sqlite3_vtab *, int);
        switch( op ){
          case SAVEPOINT_BEGIN:
            xMethod = pMod->xSavepoint;
            pVTab->iSavepoint = iSavepoint+1;
            break;
          case SAVEPOINT_ROLLBACK:
            xMethod = pMod->xRollbackTo;
            break;
          default:
            xMethod = pMod->xRelease;
            break;
        }
        if( xMethod && pVTab->iSavepoint>iSavepoint ){
          rc = xMethod(db->aVTrans[i]->pVtab, iSavepoint);
        }
      }
    }
  }
  return rc;
}








|














|







100517
100518
100519
100520
100521
100522
100523
100524
100525
100526
100527
100528
100529
100530
100531
100532
100533
100534
100535
100536
100537
100538
100539
100540
100541
100542
100543
100544
100545
100546
  assert( op==SAVEPOINT_RELEASE||op==SAVEPOINT_ROLLBACK||op==SAVEPOINT_BEGIN );
  assert( iSavepoint>=0 );
  if( db->aVTrans ){
    int i;
    for(i=0; rc==SQLITE_OK && i<db->nVTrans; i++){
      VTable *pVTab = db->aVTrans[i];
      const sqlite3_module *pMod = pVTab->pMod->pModule;
      if( pVTab->pVtab && pMod->iVersion>=2 ){
        int (*xMethod)(sqlite3_vtab *, int);
        switch( op ){
          case SAVEPOINT_BEGIN:
            xMethod = pMod->xSavepoint;
            pVTab->iSavepoint = iSavepoint+1;
            break;
          case SAVEPOINT_ROLLBACK:
            xMethod = pMod->xRollbackTo;
            break;
          default:
            xMethod = pMod->xRelease;
            break;
        }
        if( xMethod && pVTab->iSavepoint>iSavepoint ){
          rc = xMethod(pVTab->pVtab, iSavepoint);
        }
      }
    }
  }
  return rc;
}

101365
101366
101367
101368
101369
101370
101371
101372
101373
101374
101375
101376
101377
101378
101379
101380
101381
101382
101383
101384
101385
101386
101387
101388
101389
101390
101391
101392
101393
101394
101395
101396
101397
  if( op==TK_VARIABLE ){
    Vdbe *pReprepare = pParse->pReprepare;
    int iCol = pRight->iColumn;
    pVal = sqlite3VdbeGetValue(pReprepare, iCol, SQLITE_AFF_NONE);
    if( pVal && sqlite3_value_type(pVal)==SQLITE_TEXT ){
      z = (char *)sqlite3_value_text(pVal);
    }
    sqlite3VdbeSetVarmask(pParse->pVdbe, iCol); /* IMP: R-31526-56213 */
    assert( pRight->op==TK_VARIABLE || pRight->op==TK_REGISTER );
  }else if( op==TK_STRING ){
    z = pRight->u.zToken;
  }
  if( z ){
    cnt = 0;
    while( (c=z[cnt])!=0 && c!=wc[0] && c!=wc[1] && c!=wc[2] ){
      cnt++;
    }
    if( cnt!=0 && 255!=(u8)z[cnt-1] ){
      Expr *pPrefix;
      *pisComplete = c==wc[0] && z[cnt+1]==0;
      pPrefix = sqlite3Expr(db, TK_STRING, z);
      if( pPrefix ) pPrefix->u.zToken[cnt] = 0;
      *ppPrefix = pPrefix;
      if( op==TK_VARIABLE ){
        Vdbe *v = pParse->pVdbe;
        sqlite3VdbeSetVarmask(v, pRight->iColumn); /* IMP: R-31526-56213 */
        if( *pisComplete && pRight->u.zToken[1] ){
          /* If the rhs of the LIKE expression is a variable, and the current
          ** value of the variable means there is no need to invoke the LIKE
          ** function, then no OP_Variable will be added to the program.
          ** This causes problems for the sqlite3_bind_parameter_name()
          ** API. To workaround them, add a dummy OP_Variable here.
          */ 







|

















|







101399
101400
101401
101402
101403
101404
101405
101406
101407
101408
101409
101410
101411
101412
101413
101414
101415
101416
101417
101418
101419
101420
101421
101422
101423
101424
101425
101426
101427
101428
101429
101430
101431
  if( op==TK_VARIABLE ){
    Vdbe *pReprepare = pParse->pReprepare;
    int iCol = pRight->iColumn;
    pVal = sqlite3VdbeGetValue(pReprepare, iCol, SQLITE_AFF_NONE);
    if( pVal && sqlite3_value_type(pVal)==SQLITE_TEXT ){
      z = (char *)sqlite3_value_text(pVal);
    }
    sqlite3VdbeSetVarmask(pParse->pVdbe, iCol);
    assert( pRight->op==TK_VARIABLE || pRight->op==TK_REGISTER );
  }else if( op==TK_STRING ){
    z = pRight->u.zToken;
  }
  if( z ){
    cnt = 0;
    while( (c=z[cnt])!=0 && c!=wc[0] && c!=wc[1] && c!=wc[2] ){
      cnt++;
    }
    if( cnt!=0 && 255!=(u8)z[cnt-1] ){
      Expr *pPrefix;
      *pisComplete = c==wc[0] && z[cnt+1]==0;
      pPrefix = sqlite3Expr(db, TK_STRING, z);
      if( pPrefix ) pPrefix->u.zToken[cnt] = 0;
      *ppPrefix = pPrefix;
      if( op==TK_VARIABLE ){
        Vdbe *v = pParse->pVdbe;
        sqlite3VdbeSetVarmask(v, pRight->iColumn);
        if( *pisComplete && pRight->u.zToken[1] ){
          /* If the rhs of the LIKE expression is a variable, and the current
          ** value of the variable means there is no need to invoke the LIKE
          ** function, then no OP_Variable will be added to the program.
          ** This causes problems for the sqlite3_bind_parameter_name()
          ** API. To workaround them, add a dummy OP_Variable here.
          */ 
103297
103298
103299
103300
103301
103302
103303
103304
103305
103306
103307
103308
103309
103310
103311
  u8 aff, 
  sqlite3_value **pp
){
  if( pExpr->op==TK_VARIABLE
   || (pExpr->op==TK_REGISTER && pExpr->op2==TK_VARIABLE)
  ){
    int iVar = pExpr->iColumn;
    sqlite3VdbeSetVarmask(pParse->pVdbe, iVar); /* IMP: R-31526-56213 */
    *pp = sqlite3VdbeGetValue(pParse->pReprepare, iVar, aff);
    return SQLITE_OK;
  }
  return sqlite3ValueFromExpr(pParse->db, pExpr, SQLITE_UTF8, aff, pp);
}
#endif








|







103331
103332
103333
103334
103335
103336
103337
103338
103339
103340
103341
103342
103343
103344
103345
  u8 aff, 
  sqlite3_value **pp
){
  if( pExpr->op==TK_VARIABLE
   || (pExpr->op==TK_REGISTER && pExpr->op2==TK_VARIABLE)
  ){
    int iVar = pExpr->iColumn;
    sqlite3VdbeSetVarmask(pParse->pVdbe, iVar);
    *pp = sqlite3VdbeGetValue(pParse->pReprepare, iVar, aff);
    return SQLITE_OK;
  }
  return sqlite3ValueFromExpr(pParse->db, pExpr, SQLITE_UTF8, aff, pp);
}
#endif

103827
103828
103829
103830
103831
103832
103833
103834
103835
103836
103837
103838
103839
103840
103841
    ** to do a binary search to locate a row in a table or index is roughly
    ** log10(N) times the time to move from one row to the next row within
    ** a table or index.  The actual times can vary, with the size of
    ** records being an important factor.  Both moves and searches are
    ** slower with larger records, presumably because fewer records fit
    ** on one page and hence more pages have to be fetched.
    **
    ** The ANALYZE command and the sqlite_stat1 and sqlite_stat2 tables do
    ** not give us data on the relative sizes of table and index records.
    ** So this computation assumes table records are about twice as big
    ** as index records
    */
    if( (wsFlags & WHERE_NOT_FULLSCAN)==0 ){
      /* The cost of a full table scan is a number of move operations equal
      ** to the number of rows in the table.







|







103861
103862
103863
103864
103865
103866
103867
103868
103869
103870
103871
103872
103873
103874
103875
    ** to do a binary search to locate a row in a table or index is roughly
    ** log10(N) times the time to move from one row to the next row within
    ** a table or index.  The actual times can vary, with the size of
    ** records being an important factor.  Both moves and searches are
    ** slower with larger records, presumably because fewer records fit
    ** on one page and hence more pages have to be fetched.
    **
    ** The ANALYZE command and the sqlite_stat1 and sqlite_stat3 tables do
    ** not give us data on the relative sizes of table and index records.
    ** So this computation assumes table records are about twice as big
    ** as index records
    */
    if( (wsFlags & WHERE_NOT_FULLSCAN)==0 ){
      /* The cost of a full table scan is a number of move operations equal
      ** to the number of rows in the table.
Changes to src/sqlite3.h.
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
**
** 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-20 00:55:54 4344483f7d7f64dffadde0053e6c745948db9486"

/*
** 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







|







105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
**
** 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
Changes to src/stash.c.
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
  );
  if( g.argc>3 ){
    int i;
    for(i=3; i<g.argc; i++){
      stash_add_file_or_dir(stashid, vid, g.argv[i]);
    }
  }else{
    stash_add_file_or_dir(stashid, vid, ".");
  }
  return stashid;
}

/*
** Apply a stash to the current check-out.
*/







|







168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
  );
  if( g.argc>3 ){
    int i;
    for(i=3; i<g.argc; i++){
      stash_add_file_or_dir(stashid, vid, g.argv[i]);
    }
  }else{
    stash_add_file_or_dir(stashid, vid, g.zLocalRoot);
  }
  return stashid;
}

/*
** Apply a stash to the current check-out.
*/
256
257
258
259
260
261
262

263
264
265
266
267
268
269
270
271
    if( fossil_strcmp(zOrig,zNew)!=0 ){
      undo_save(zOrig);
      file_delete(zOPath);
    }
  }
  db_finalize(&q);
  if( nConflict ){

    fossil_print("WARNING: %d merge conflicts - see messages above for details.\n",
            nConflict);
  }
}

/*
** Show the diffs associate with a single stash.
*/
static void stash_diff(int stashid, const char *zDiffCmd, int diffFlags){







>
|
|







256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
    if( fossil_strcmp(zOrig,zNew)!=0 ){
      undo_save(zOrig);
      file_delete(zOPath);
    }
  }
  db_finalize(&q);
  if( nConflict ){
    fossil_print(
      "WARNING: %d merge conflicts - see messages above for details.\n",
      nConflict);
  }
}

/*
** Show the diffs associate with a single stash.
*/
static void stash_diff(int stashid, const char *zDiffCmd, int diffFlags){
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
404
405
406
407
408
409
410
411
412
413
414
415
416
417
/*
** COMMAND: stash
**
** Usage: %fossil stash SUBCOMMAND ARGS...
**
**  fossil stash
**  fossil stash save ?-m COMMENT? ?FILES...?

**
**     Save the current changes in the working tree as a new stash.
**     Then revert the changes back to the last check-in.  If FILES
**     are listed, then only stash and revert the named files.  The
**     "save" verb can be omitted if and only if there are no other
**     arguments.

**
**  fossil stash list
**  fossil stash ls
**
**     List all changes sets currently stashed.

**
**  fossil stash pop
**
**     Apply the most recently create stash to the current working
**     check-out.  Then delete that stash.  This is equivalent to
**     doing an "apply" and a "drop" against the most recent stash.
**     This command is undoable.
**
**  fossil stash apply ?STASHID?
**
**     Apply the identified stash to the current working check-out.
**     If no STASHID is specified, use the most recent stash.  Unlike
**     the "pop" command, the stash is retained so that it can be used
**     again.  This command is undoable.
**
**  fossil stash goto ?STASHID?
**
**     Update to the baseline checkout for STASHID then apply the
**     changes of STASHID.  Keep STASHID so that it can be reused
**     This command is undoable.
**
**  fossil stash drop ?STASHID? ?--all?
**  fossil stash rm   ?STASHID? ?--all?
**
**     Forget everything about STASHID.  Forget the whole stash if the
**     --all flag is used.  Individual drops are undoable but --all is not.
**
**  fossil stash snapshot ?-m COMMENT? ?FILES...?
**
**     Save the current changes in the working tree as a new stash
**     but, unlike "save", do not revert those changes.
**
**  fossil stash diff ?STASHID?
**  fossil stash gdiff ?STASHID?
**
**     Show diffs of the current working directory and what that
**     directory would be if STASHID were applied.  
*/
void stash_cmd(void){







>





|
>

|
|

|
>


<
<
<
<
<
<


|
|
|
|













<
<
<
<
<







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





404
405
406
407
408
409
410
/*
** COMMAND: stash
**
** Usage: %fossil stash SUBCOMMAND ARGS...
**
**  fossil stash
**  fossil stash save ?-m COMMENT? ?FILES...?
**  fossil stash snapshot ?-m COMMENT? ?FILES...?
**
**     Save the current changes in the working tree as a new stash.
**     Then revert the changes back to the last check-in.  If FILES
**     are listed, then only stash and revert the named files.  The
**     "save" verb can be omitted if and only if there are no other
**     arguments.  The "snapshot" verb works the same as "save" but
**     omits the revert, keeping the check-out unchanged.
**
**  fossil stash list ?--detail?
**  fossil stash ls ?-l?
**
**     List all changes sets currently stashed.  Show information about
**     individual files in each changeset if --detail or -l is used.
**
**  fossil stash pop






**  fossil stash apply ?STASHID?
**
**     Apply STASHID or the most recently create stash to the current
**     working check-out.  The "pop" command deletes that changeset from
**     the stash after applying it but the "apply" command retains the
**     changeset.
**
**  fossil stash goto ?STASHID?
**
**     Update to the baseline checkout for STASHID then apply the
**     changes of STASHID.  Keep STASHID so that it can be reused
**     This command is undoable.
**
**  fossil stash drop ?STASHID? ?--all?
**  fossil stash rm   ?STASHID? ?--all?
**
**     Forget everything about STASHID.  Forget the whole stash if the
**     --all flag is used.  Individual drops are undoable but --all is not.
**





**  fossil stash diff ?STASHID?
**  fossil stash gdiff ?STASHID?
**
**     Show diffs of the current working directory and what that
**     directory would be if STASHID were applied.  
*/
void stash_cmd(void){
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
    g.argv[1] = "revert";
    revert_cmd();
  }else
  if( memcmp(zCmd, "snapshot", nCmd)==0 ){
    stash_create();
  }else
  if( memcmp(zCmd, "list", nCmd)==0 || memcmp(zCmd, "ls", nCmd)==0 ){
    Stmt q;
    int n = 0;

    verify_all_options();
    db_prepare(&q,
       "SELECT stashid, (SELECT uuid FROM blob WHERE rid=vid),"
       "       comment, datetime(ctime) FROM stash"
       " ORDER BY ctime DESC"
    );




    while( db_step(&q)==SQLITE_ROW ){

      const char *zCom;
      n++;
      fossil_print("%5d: [%.14s] on %s\n",
        db_column_int(&q, 0),
        db_column_text(&q, 1),
        db_column_text(&q, 3)
      );
      zCom = db_column_text(&q, 2);
      if( zCom && zCom[0] ){
        fossil_print("       ");
        comment_print(zCom, 7, 79);
      }















    }




    db_finalize(&q);

    if( n==0 ) fossil_print("empty stash\n");
  }else
  if( memcmp(zCmd, "drop", nCmd)==0 || memcmp(zCmd, "rm", nCmd)==0 ){
    int allFlag = find_option("all", 0, 0)!=0;
    if( g.argc>4 ) usage("apply STASHID");
    if( allFlag ){




      db_multi_exec("DELETE FROM stash; DELETE FROM stashfile;");

    }else{
      stashid = stash_get_id(g.argc==4 ? g.argv[3] : 0);
      undo_begin();
      undo_save_stash(stashid);
      stash_drop(stashid);
      undo_finish();
    }







|

>






>
>
>
>

>



|








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

>




|

>
>
>
>
|
>







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
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
    g.argv[1] = "revert";
    revert_cmd();
  }else
  if( memcmp(zCmd, "snapshot", nCmd)==0 ){
    stash_create();
  }else
  if( memcmp(zCmd, "list", nCmd)==0 || memcmp(zCmd, "ls", nCmd)==0 ){
    Stmt q, q2;
    int n = 0;
    int fDetail = find_option("detail","l",0)!=0;
    verify_all_options();
    db_prepare(&q,
       "SELECT stashid, (SELECT uuid FROM blob WHERE rid=vid),"
       "       comment, datetime(ctime) FROM stash"
       " ORDER BY ctime DESC"
    );
    if( fDetail ){
      db_prepare(&q2, "SELECT isAdded, isRemoved, origname, newname"
                      "  FROM stashfile WHERE stashid=$id");
    }
    while( db_step(&q)==SQLITE_ROW ){
      int stashid = db_column_int(&q, 0);
      const char *zCom;
      n++;
      fossil_print("%5d: [%.14s] on %s\n",
        stashid,
        db_column_text(&q, 1),
        db_column_text(&q, 3)
      );
      zCom = db_column_text(&q, 2);
      if( zCom && zCom[0] ){
        fossil_print("       ");
        comment_print(zCom, 7, 79);
      }
      if( fDetail ){
        db_bind_int(&q2, "$id", stashid);
        while( db_step(&q2)==SQLITE_ROW ){
          int isAdded = db_column_int(&q2, 0);
          int isRemoved = db_column_int(&q2, 1);
          const char *zOrig = db_column_text(&q2, 2);
          const char *zNew = db_column_text(&q2, 3);
          if( isAdded ){
             fossil_print("          ADD %s\n", zNew);
          }else if( isRemoved ){
             fossil_print("          REMOVE %s\n", zOrig);
          }else if( fossil_strcmp(zOrig,zNew)!=0 ){
             fossil_print("          RENAME %s -> %s\n", zOrig, zNew);
          }else{
             fossil_print("          EDIT %s\n", zOrig);
          }
        }
        db_reset(&q2);
      }
    }
    db_finalize(&q);
    if( fDetail ) db_finalize(&q2);
    if( n==0 ) fossil_print("empty stash\n");
  }else
  if( memcmp(zCmd, "drop", nCmd)==0 || memcmp(zCmd, "rm", nCmd)==0 ){
    int allFlag = find_option("all", 0, 0)!=0;
    if( g.argc>4 ) usage("drop STASHID");
    if( allFlag ){
      Blob ans;
      blob_zero(&ans);
      prompt_user("This action is not undoable.  Continue (y/N)? ", &ans);
      if( blob_str(&ans)[0]=='y' ){
        db_multi_exec("DELETE FROM stash; DELETE FROM stashfile;");
      }
    }else{
      stashid = stash_get_id(g.argc==4 ? g.argv[3] : 0);
      undo_begin();
      undo_save_stash(stashid);
      stash_drop(stashid);
      undo_finish();
    }
535
536
537
538
539
540
541






542
543
544
545
546
547
  }else
  if( memcmp(zCmd, "gdiff", nCmd)==0 ){
    const char *zDiffCmd = db_get("gdiff-command", 0);
    int diffFlags = diff_options();
    if( g.argc>4 ) usage("diff STASHID");
    stashid = stash_get_id(g.argc==4 ? g.argv[3] : 0);
    stash_diff(stashid, zDiffCmd, diffFlags);






  }else
  {
    usage("SUBCOMMAND ARGS...");
  }
  db_end_transaction(0);
}







>
>
>
>
>
>






559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
  }else
  if( memcmp(zCmd, "gdiff", nCmd)==0 ){
    const char *zDiffCmd = db_get("gdiff-command", 0);
    int diffFlags = diff_options();
    if( g.argc>4 ) usage("diff STASHID");
    stashid = stash_get_id(g.argc==4 ? g.argv[3] : 0);
    stash_diff(stashid, zDiffCmd, diffFlags);
  }else
  if( memcmp(zCmd, "help", nCmd)==0 ){
    g.argv[1] = "help";
    g.argv[2] = "stash";
    g.argc = 3;
    help_cmd();
  }else
  {
    usage("SUBCOMMAND ARGS...");
  }
  db_end_transaction(0);
}
Changes to src/tar.c.
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
  manifest_destroy(pManifest);
  blob_reset(&mfile);
  blob_reset(&filename);
  tar_finish(pTar);
}

/*
** COMMAND: tarball
**
** Usage: %fossil tarball VERSION OUTPUTFILE [--name DIRECTORYNAME]
**
** Generate a compressed tarball for a specified version.  If the --name
** option is used, its argument becomes the name of the top-level directory
** in the resulting tarball.  If --name is omitted, the top-level directory
** named is derived from the project name, the check-in date and time, and







|







521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
  manifest_destroy(pManifest);
  blob_reset(&mfile);
  blob_reset(&filename);
  tar_finish(pTar);
}

/*
** COMMAND: tarball*
**
** Usage: %fossil tarball VERSION OUTPUTFILE [--name DIRECTORYNAME]
**
** Generate a compressed tarball for a specified version.  If the --name
** option is used, its argument becomes the name of the top-level directory
** in the resulting tarball.  If --name is omitted, the top-level directory
** named is derived from the project name, the check-in date and time, and
Changes to src/tkt.c.
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
    }
    blob_reset(&val);
  }
  @ </ol>
}

/*
** COMMAND: ticket
** Usage: %fossil ticket SUBCOMMAND ...
**
** Run various subcommands to control tickets
**
**     %fossil ticket show (REPORTTITLE|REPORTNR) ?TICKETFILTER? ?options?
**
**         options can be:







|







835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
    }
    blob_reset(&val);
  }
  @ </ol>
}

/*
** COMMAND: ticket*
** Usage: %fossil ticket SUBCOMMAND ...
**
** Run various subcommands to control tickets
**
**     %fossil ticket show (REPORTTITLE|REPORTNR) ?TICKETFILTER? ?options?
**
**         options can be:
Changes to src/undo.c.
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
  undoActive = 0;
  fossil_print("Rolling back prior filesystem changes...\n");
  undo_all_filesystem(0);
}

/*
** COMMAND: undo
** COMMAND: redo
**
** Usage: %fossil undo ?--explain? ?FILENAME...?
**    or: %fossil redo ?--explain? ?FILENAME...?
**
** Undo the changes to the working checkout caused by the most recent
** of the following operations:
**







|







346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
  undoActive = 0;
  fossil_print("Rolling back prior filesystem changes...\n");
  undo_all_filesystem(0);
}

/*
** COMMAND: undo
** COMMAND: redo*
**
** Usage: %fossil undo ?--explain? ?FILENAME...?
**    or: %fossil redo ?--explain? ?FILENAME...?
**
** Undo the changes to the working checkout caused by the most recent
** of the following operations:
**
Changes to src/user.c.
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
  if( z ){
    strip_string(pIn, z);
  }
}


/*
** COMMAND:  user
**
** Usage: %fossil user SUBCOMMAND ...  ?-R|--repository FILE?
**
** Run various subcommands on users of the open repository or of
** the repository identified by the -R or --repository option.
**
**    %fossil user capabilities USERNAME ?STRING?







|







140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
  if( z ){
    strip_string(pIn, z);
  }
}


/*
** COMMAND: user*
**
** Usage: %fossil user SUBCOMMAND ...  ?-R|--repository FILE?
**
** Run various subcommands on users of the open repository or of
** the repository identified by the -R or --repository option.
**
**    %fossil user capabilities USERNAME ?STRING?
Changes to src/wiki.c.
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
  assert( blob_is_reset(&wiki) );
  content_deltify(rid,nrid,0);
  db_end_transaction(0);
  return 1;
}

/*
** COMMAND: wiki
**
** Usage: %fossil wiki (export|create|commit|list) WikiName
**
** Run various subcommands to work with wiki entries.
**
**     %fossil wiki export PAGENAME ?FILE?
**







|







837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
  assert( blob_is_reset(&wiki) );
  content_deltify(rid,nrid,0);
  db_end_transaction(0);
  return 1;
}

/*
** COMMAND: wiki*
**
** Usage: %fossil wiki (export|create|commit|list) WikiName
**
** Run various subcommands to work with wiki entries.
**
**     %fossil wiki export PAGENAME ?FILE?
**
Changes to src/winhttp.c.
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
      fossil_fatal("error from StartServiceCtrlDispatcher()");
    }
  }
  return 0;
}

/*
** COMMAND: winsrv
** Usage: fossil winsrv METHOD ?SERVICE-NAME? ?OPTIONS?
**
** Where METHOD is one of: create delete show start stop.
**
** The winsrv command manages Fossil as a Windows service.  This allows
** (for example) Fossil to be running in the background when no user
** is logged in.







|







430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
      fossil_fatal("error from StartServiceCtrlDispatcher()");
    }
  }
  return 0;
}

/*
** COMMAND: winsrv*
** Usage: fossil winsrv METHOD ?SERVICE-NAME? ?OPTIONS?
**
** Where METHOD is one of: create delete show start stop.
**
** The winsrv command manages Fossil as a Windows service.  This allows
** (for example) Fossil to be running in the background when no user
** is logged in.
Changes to src/xfer.c.
635
636
637
638
639
640
641

642
643
644
645
646

647
648
649
650
651
652
653
  Blob cluster, cksum;
  Blob deleteWhere;
  Stmt q;
  int nUncl;
  int nRow = 0;
  int rid;


  /* We should not ever get any private artifacts in the unclustered table.
  ** But if we do (because of a bug) now is a good time to delete them. */
  db_multi_exec(
    "DELETE FROM unclustered WHERE rid IN (SELECT rid FROM private)"
  );


  nUncl = db_int(0, "SELECT count(*) FROM unclustered /*scan*/"
                    " WHERE NOT EXISTS(SELECT 1 FROM phantom"
                                      " WHERE rid=unclustered.rid)");
  if( nUncl>=100 ){
    blob_zero(&cluster);
    blob_zero(&deleteWhere);







>





>







635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
  Blob cluster, cksum;
  Blob deleteWhere;
  Stmt q;
  int nUncl;
  int nRow = 0;
  int rid;

#if 0
  /* We should not ever get any private artifacts in the unclustered table.
  ** But if we do (because of a bug) now is a good time to delete them. */
  db_multi_exec(
    "DELETE FROM unclustered WHERE rid IN (SELECT rid FROM private)"
  );
#endif

  nUncl = db_int(0, "SELECT count(*) FROM unclustered /*scan*/"
                    " WHERE NOT EXISTS(SELECT 1 FROM phantom"
                                      " WHERE rid=unclustered.rid)");
  if( nUncl>=100 ){
    blob_zero(&cluster);
    blob_zero(&deleteWhere);
Changes to src/zip.c.
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
  }
  manifest_destroy(pManifest);
  blob_reset(&filename);
  zip_close(pZip);
}

/*
** COMMAND: zip
**
** Usage: %fossil zip VERSION OUTPUTFILE [--name DIRECTORYNAME]
**
** Generate a ZIP archive for a specified version.  If the --name option is
** used, it argument becomes the name of the top-level directory in the
** resulting ZIP archive.  If --name is omitted, the top-level directory
** named is derived from the project name, the check-in date and time, and







|







375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
  }
  manifest_destroy(pManifest);
  blob_reset(&filename);
  zip_close(pZip);
}

/*
** COMMAND: zip*
**
** Usage: %fossil zip VERSION OUTPUTFILE [--name DIRECTORYNAME]
**
** Generate a ZIP archive for a specified version.  If the --name option is
** used, it argument becomes the name of the top-level directory in the
** resulting ZIP archive.  If --name is omitted, the top-level directory
** named is derived from the project name, the check-in date and time, and
Changes to www/checkin_names.wiki.
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142

143
144
145
146
147
148
149
150

  *   <i>YYYY-MM-DD</i>
  *   <i>YYYY-MM-DD HH:MM</i>
  *   <i>YYYY-MM-DD HH:MM:SS</i>

The space between the day and the year can optionally be 
replaced by an uppercase <b>T</b> and the entire timestamp can
optionally be followed by "<b>utc</b>".

In its default configuration, Fossil interprets and displays all dates
in Universal Coordinated Time (UTC).  This tends to work the best for
distributed projects where participants are scattered around the globe.
But there is an option on the Admin/Timeline page of the web-interface to
switch to local time.  The "<b>utc</b>" suffix on an timestamp check-in
name is meaningless if Fossil is in the default mode of using UTC for
everything, but if Fossil has been switched to localtime mode, then the
"<b>utc</b>" suffix means to interpret that particular timestamp using 
UTC instead localtime.


As an example, consider the homepage for the Fossil website itself:

<blockquote>
http://www.fossil-scm.org/fossil/doc/<b>trunk</b>/www/index.wiki
</blockquote>

The bold component of that URL is a check-in name.  To see what the
Fossil website looked like on January 1, 2009, one has merely to change







|





|


|


>
|







124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151

  *   <i>YYYY-MM-DD</i>
  *   <i>YYYY-MM-DD HH:MM</i>
  *   <i>YYYY-MM-DD HH:MM:SS</i>

The space between the day and the year can optionally be 
replaced by an uppercase <b>T</b> and the entire timestamp can
optionally be followed by "<b>z</b>" or "<b>Z</b>".

In its default configuration, Fossil interprets and displays all dates
in Universal Coordinated Time (UTC).  This tends to work the best for
distributed projects where participants are scattered around the globe.
But there is an option on the Admin/Timeline page of the web-interface to
switch to local time.  The "<b>Z</b>" suffix on an timestamp check-in
name is meaningless if Fossil is in the default mode of using UTC for
everything, but if Fossil has been switched to localtime mode, then the
"<b>Z</b>" suffix means to interpret that particular timestamp using 
UTC instead localtime.

For an example of how timestamps are useful, 
consider the homepage for the Fossil website itself:

<blockquote>
http://www.fossil-scm.org/fossil/doc/<b>trunk</b>/www/index.wiki
</blockquote>

The bold component of that URL is a check-in name.  To see what the
Fossil website looked like on January 1, 2009, one has merely to change