Fossil

Check-in [b19ef490fd]
Login

Check-in [b19ef490fd]

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

Overview
Comment:Merge the latest trunk changes and the mingw-broken-cmdline branch into unicode-cmdline.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | unicode-cmdline
Files: files | file ages | folders
SHA1: b19ef490fdbe5822c893ae12ea8de463575a33e1
User & Date: drh 2012-09-11 11:57:57.508
Context
2012-09-11
12:16
Merge the unicode-cmdline branch into trunk. ... (check-in: f668ff44c0 user: drh tags: trunk)
11:57
Merge the latest trunk changes and the mingw-broken-cmdline branch into unicode-cmdline. ... (Closed-Leaf check-in: b19ef490fd user: drh tags: unicode-cmdline)
2012-09-10
18:15
add .PHONY target to makefile, this makes "make test" work even though there already is a directory named "test" ... (check-in: ffcdfadbda user: jan.nijtmans tags: trunk)
08:21
Add some test cases ... (Closed-Leaf check-in: d43165418c user: jan.nijtmans tags: mingw-broken-cmdline)
2012-09-07
07:55
merge trunk ... (check-in: af4287ac3a user: jan.nijtmans tags: unicode-cmdline)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/diffcmd.c.
449
450
451
452
453
454
455






















456
457
458
459
460
461
462
      pFromFile = manifest_file_next(pFrom,0);
      pToFile = manifest_file_next(pTo,0);
    }
  }
  manifest_destroy(pFrom);
  manifest_destroy(pTo);
}























/*
** COMMAND: diff
** COMMAND: gdiff
**
** Usage: %fossil diff|gdiff ?OPTIONS? ?FILE1? ?FILE2 ...?
**







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







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
      pFromFile = manifest_file_next(pFrom,0);
      pToFile = manifest_file_next(pTo,0);
    }
  }
  manifest_destroy(pFrom);
  manifest_destroy(pTo);
}

/*
** Return the name of the external diff command, or return NULL if
** no external diff command is defined.
*/
const char *diff_command_external(int guiDiff){
  char *zDefault;
  const char *zName;

  if( guiDiff ){
#if defined(_WIN32)
    zDefault = "WinDiff.exe";
#else
    zDefault = 0;
#endif
    zName = "gdiff-command";
  }else{
    zDefault = 0;
    zName = "diff-command";
  }
  return db_get(zName, zDefault);
}

/*
** COMMAND: diff
** COMMAND: gdiff
**
** Usage: %fossil diff|gdiff ?OPTIONS? ?FILE1? ?FILE2 ...?
**
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
    zTo = zBranch;
    zFrom = mprintf("root:%s", zBranch);
  }
  if( zTo==0 ){
    db_must_be_within_tree();
    verify_all_options();
    if( !isInternDiff ){
      zDiffCmd = db_get(isGDiff ? "gdiff-command" : "diff-command", 0);
    }
    if( g.argc>=3 ){
      for(f=2; f<g.argc; ++f){
        diff_one_against_disk(zFrom, zDiffCmd, diffFlags, g.argv[f]);
      }
    }else{
      diff_all_against_disk(zFrom, zDiffCmd, diffFlags);
    }
  }else if( zFrom==0 ){
    fossil_fatal("must use --from if --to is present");
  }else{
    db_find_and_open_repository(0, 0);
    verify_all_options();
    if( !isInternDiff ){
      zDiffCmd = db_get(isGDiff ? "gdiff-command" : "diff-command", 0);
    }
    if( g.argc>=3 ){
      for(f=2; f<g.argc; ++f){
        diff_one_two_versions(zFrom, zTo, zDiffCmd, diffFlags, g.argv[f]);        
      }
    }else{
      diff_all_two_versions(zFrom, zTo, zDiffCmd, diffFlags);







|














|







542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
    zTo = zBranch;
    zFrom = mprintf("root:%s", zBranch);
  }
  if( zTo==0 ){
    db_must_be_within_tree();
    verify_all_options();
    if( !isInternDiff ){
      zDiffCmd = diff_command_external(isGDiff);
    }
    if( g.argc>=3 ){
      for(f=2; f<g.argc; ++f){
        diff_one_against_disk(zFrom, zDiffCmd, diffFlags, g.argv[f]);
      }
    }else{
      diff_all_against_disk(zFrom, zDiffCmd, diffFlags);
    }
  }else if( zFrom==0 ){
    fossil_fatal("must use --from if --to is present");
  }else{
    db_find_and_open_repository(0, 0);
    verify_all_options();
    if( !isInternDiff ){
      zDiffCmd = diff_command_external(isGDiff);
    }
    if( g.argc>=3 ){
      for(f=2; f<g.argc; ++f){
        diff_one_two_versions(zFrom, zTo, zDiffCmd, diffFlags, g.argv[f]);        
      }
    }else{
      diff_all_two_versions(zFrom, zTo, zDiffCmd, diffFlags);
Changes to src/main.c.
327
328
329
330
331
332
333
334

335




















































































































336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363

364
365
366
367
368
369
370
  memset(&g.json, 0, sizeof(g.json));
#endif
  free(g.zErrMsg);
  if(g.db){
    db_close(0);
  }
}


/*




















































































































** Convert all arguments to UTF-8. Then search g.argv for for arguments
** "--args FILENAME". If found, then
** (1) remove the two arguments from g.argv
** (2) Read the file FILENAME
** (3) Use the contents of FILE to replace the two removed arguments:
**     (a) Ignore blank lines in the file
**     (b) Each non-empty line of the file is an argument, except
**     (c) If the line begins with "-" and contains a space, it is broken
**         into two arguments at the space.
*/
static void expand_args_option(int argc, void *argv){
  Blob file = empty_blob;   /* Content of the file */
  Blob line = empty_blob;   /* One line of the file */
  unsigned int nLine;       /* Number of lines in the file*/
  unsigned int i, j, k;     /* Loop counters */
  int n;                    /* Number of bytes in one line */
  char *z;            /* General use string pointer */
  char **newArgv;     /* New expanded g.argv under construction */
  char const * zFileName;   /* input file name */
  FILE * zInFile;           /* input FILE */
  int foundBom = -1;        /* -1= not searched yet, 0 = no; 1=yes */
#ifdef _WIN32
  wchar_t buf[MAX_PATH];
#endif

  g.argc = argc;
  g.argv = argv;
#ifdef _WIN32

  GetModuleFileNameW(NULL, buf, MAX_PATH);
  g.argv[0] = fossil_unicode_to_utf8(buf);
#ifdef UNICODE
  for(i=1; i<g.argc; i++) g.argv[i] = fossil_unicode_to_utf8(g.argv[i]);
#else
  for(i=1; i<g.argc; i++) g.argv[i] = fossil_mbcs_to_utf8(g.argv[i]);
#endif








>

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














|
|










>







327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
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
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
  memset(&g.json, 0, sizeof(g.json));
#endif
  free(g.zErrMsg);
  if(g.db){
    db_close(0);
  }
}

#if defined(_WIN32)
/*
** Parse the command-line arguments passed to windows.  We do this
** ourselves to work around bugs in the command-line parsing of MinGW.
** It is possible (in theory) to only use this routine when compiling
** with MinGW and to use built-in command-line parsing for MSVC and
** MinGW-64.  However, the code is here, it is efficient, and works, and
** by using it in all cases we do a better job of testing it.  If you suspect
** a bug in this code, test your theory by invoking "fossil test-echo".
**
** This routine is copied from TCL with some reformatting.
** The original comment text follows:
**
** Parse the Windows command line string into argc/argv. Done here
** because we don't trust the builtin argument parser in crt0. Windows
** applications are responsible for breaking their command line into
** arguments.
**
** 2N backslashes + quote -> N backslashes + begin quoted string
** 2N + 1 backslashes + quote -> literal
** N backslashes + non-quote -> literal
** quote + quote in a quoted string -> single quote
** quote + quote not in quoted string -> empty string
** quote -> begin quoted string
**
** Results:
** Fills argcPtr with the number of arguments and argvPtr with the array
** of arguments.
*/
#include <tchar.h>
#define tchar_isspace(X)  ((X)==TEXT(' ') || (X)==TEXT('\t'))
static void parse_windows_command_line(
  int *argcPtr,   /* Filled with number of argument strings. */
  void *argvPtr   /* Filled with argument strings (malloc'd). */
){
  TCHAR *cmdLine, *p, *arg, *argSpace;
  TCHAR **argv;
  int argc, size, inquote, copy, slashes;

  cmdLine = GetCommandLine();

  /*
  ** Precompute an overly pessimistic guess at the number of arguments in
  ** the command line by counting non-space spans.
  */
  size = 2;
  for(p=cmdLine; *p!=TEXT('\0'); p++){
    if( tchar_isspace(*p) ){
      size++;
      while( tchar_isspace(*p) ){
        p++;
      }
      if( *p==TEXT('\0') ){
        break;
      }
    }
  }

  argSpace = fossil_malloc(size * sizeof(char*)
    + (_tcslen(cmdLine) * sizeof(TCHAR)) + sizeof(TCHAR));
  argv = (TCHAR**)argSpace;
  argSpace += size*(sizeof(char*)/sizeof(TCHAR));
  size--;

  p = cmdLine;
  for(argc=0; argc<size; argc++){
    argv[argc] = arg = argSpace;
    while( tchar_isspace(*p) ){
      p++;
    }
    if (*p == TEXT('\0')) {
      break;
    }
    inquote = 0;
    slashes = 0;
    while(1){
      copy = 1;
      while( *p==TEXT('\\') ){
        slashes++;
        p++;
      }
      if( *p==TEXT('"') ){
        if( (slashes&1)==0 ){
          copy = 0;
          if( inquote && p[1]==TEXT('"') ){
            p++;
            copy = 1;
          }else{
            inquote = !inquote;
          }
        }
        slashes >>= 1;
      }
      while( slashes ){
        *arg = TEXT('\\');
        arg++;
        slashes--;
      }
      if( *p==TEXT('\0') || (!inquote && tchar_isspace(*p)) ){
        break;
      }
      if( copy!=0 ){
        *arg = *p;
        arg++;
      }
      p++;
    }
    *arg = '\0';
    argSpace = arg + 1;
  }
  argv[argc] = NULL;
  *argcPtr = argc;
  *((TCHAR ***)argvPtr) = argv;
}
#endif /* defined(_WIN32) */


/*
** Convert all arguments from mbcs (or unicode) to UTF-8. Then
** search g.argv for arguments "--args FILENAME". If found, then
** (1) remove the two arguments from g.argv
** (2) Read the file FILENAME
** (3) Use the contents of FILE to replace the two removed arguments:
**     (a) Ignore blank lines in the file
**     (b) Each non-empty line of the file is an argument, except
**     (c) If the line begins with "-" and contains a space, it is broken
**         into two arguments at the space.
*/
static void expand_args_option(int argc, void *argv){
  Blob file = empty_blob;   /* Content of the file */
  Blob line = empty_blob;   /* One line of the file */
  unsigned int nLine;       /* Number of lines in the file*/
  unsigned int i, j, k;     /* Loop counters */
  int n;                    /* Number of bytes in one line */
  char *z;                  /* General use string pointer */
  char **newArgv;           /* New expanded g.argv under construction */
  char const * zFileName;   /* input file name */
  FILE * zInFile;           /* input FILE */
  int foundBom = -1;        /* -1= not searched yet, 0 = no; 1=yes */
#ifdef _WIN32
  wchar_t buf[MAX_PATH];
#endif

  g.argc = argc;
  g.argv = argv;
#ifdef _WIN32
  parse_windows_command_line(&g.argc, &g.argv);
  GetModuleFileNameW(NULL, buf, MAX_PATH);
  g.argv[0] = fossil_unicode_to_utf8(buf);
#ifdef UNICODE
  for(i=1; i<g.argc; i++) g.argv[i] = fossil_unicode_to_utf8(g.argv[i]);
#else
  for(i=1; i<g.argc; i++) g.argv[i] = fossil_mbcs_to_utf8(g.argv[i]);
#endif
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
    if( n<=1 ) continue;
    z = blob_buffer(&line);
    z[n-1] = 0;
    if (foundBom == -1) {
      static const char bom[] = { 0xEF, 0xBB, 0xBF };
      foundBom = memcmp(z, bom, 3)==0;
      if( foundBom ) {
    	  z += 3; n -= 3;
      }
    }
    if((n>1) && ('\r'==z[n-2])){
      if(n==2) continue /*empty line*/;
      z[n-2] = 0;
    }
    if (!foundBom) {







|







520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
    if( n<=1 ) continue;
    z = blob_buffer(&line);
    z[n-1] = 0;
    if (foundBom == -1) {
      static const char bom[] = { 0xEF, 0xBB, 0xBF };
      foundBom = memcmp(z, bom, 3)==0;
      if( foundBom ) {
        z += 3; n -= 3;
      }
    }
    if((n>1) && ('\r'==z[n-2])){
      if(n==2) continue /*empty line*/;
      z[n-2] = 0;
    }
    if (!foundBom) {
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
**   --th-trace          trace TH1 execution (for debugging purposes)
**
** See also: cgi, http, winsrv
*/
void cmd_webserver(void){
  int iPort, mxPort;        /* Range of TCP ports allowed */
  const char *zPort;        /* Value of the --port option */
  char *zBrowser;           /* Name of web browser program */
  char *zBrowserCmd = 0;    /* Command to launch the web browser */
  int isUiCmd;              /* True if command is "ui", not "server' */
  const char *zNotFound;    /* The --notfound option or NULL */
  int flags = 0;            /* Server flags */

#if defined(_WIN32)
  const char *zStopperFile;    /* Name of file used to terminate server */







|







1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
**   --th-trace          trace TH1 execution (for debugging purposes)
**
** See also: cgi, http, winsrv
*/
void cmd_webserver(void){
  int iPort, mxPort;        /* Range of TCP ports allowed */
  const char *zPort;        /* Value of the --port option */
  const char *zBrowser;     /* Name of web browser program */
  char *zBrowserCmd = 0;    /* Command to launch the web browser */
  int isUiCmd;              /* True if command is "ui", not "server' */
  const char *zNotFound;    /* The --notfound option or NULL */
  int flags = 0;            /* Server flags */

#if defined(_WIN32)
  const char *zStopperFile;    /* Name of file used to terminate server */
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
  }
#if !defined(_WIN32)
  /* Unix implementation */
  if( isUiCmd ){
#if !defined(__DARWIN__) && !defined(__APPLE__) && !defined(__HAIKU__)
    zBrowser = db_get("web-browser", 0);
    if( zBrowser==0 ){
      static char *azBrowserProg[] = { "xdg-open", "gnome-open", "firefox" };
      int i;
      zBrowser = "echo";
      for(i=0; i<sizeof(azBrowserProg)/sizeof(azBrowserProg[0]); i++){
        if( binaryOnPath(azBrowserProg[i]) ){
          zBrowser = azBrowserProg[i];
          break;
        }







|







1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
  }
#if !defined(_WIN32)
  /* Unix implementation */
  if( isUiCmd ){
#if !defined(__DARWIN__) && !defined(__APPLE__) && !defined(__HAIKU__)
    zBrowser = db_get("web-browser", 0);
    if( zBrowser==0 ){
      static const char *const azBrowserProg[] = { "xdg-open", "gnome-open", "firefox" };
      int i;
      zBrowser = "echo";
      for(i=0; i<sizeof(azBrowserProg)/sizeof(azBrowserProg[0]); i++){
        if( binaryOnPath(azBrowserProg[i]) ){
          zBrowser = azBrowserProg[i];
          break;
        }
Changes to src/main.mk.
1086
1087
1088
1089
1090
1091
1092







$(OBJDIR)/th_tcl.o:	$(SRCDIR)/th_tcl.c
	$(XTCC) -c $(SRCDIR)/th_tcl.c -o $(OBJDIR)/th_tcl.o


$(OBJDIR)/cson_amalgamation.o: $(SRCDIR)/cson_amalgamation.c
	$(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $(OBJDIR)/cson_amalgamation.o -DCSON_FOSSIL_MODE















>
>
>
>
>
>
>
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
$(OBJDIR)/th_tcl.o:	$(SRCDIR)/th_tcl.c
	$(XTCC) -c $(SRCDIR)/th_tcl.c -o $(OBJDIR)/th_tcl.o


$(OBJDIR)/cson_amalgamation.o: $(SRCDIR)/cson_amalgamation.c
	$(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $(OBJDIR)/cson_amalgamation.o -DCSON_FOSSIL_MODE

#
# The list of all the targets that do not correspond to real files. This stops
# 'make' from getting confused when someone makes an error in a rule.
#

.PHONY: all install test clean

Changes to src/makemake.tcl.
301
302
303
304
305
306
307







308
309
310
311
312
313
314
writeln "\$(OBJDIR)/th_tcl.o:\t\$(SRCDIR)/th_tcl.c"
writeln "\t\$(XTCC) -c \$(SRCDIR)/th_tcl.c -o \$(OBJDIR)/th_tcl.o\n"

set opt {}
writeln {
$(OBJDIR)/cson_amalgamation.o: $(SRCDIR)/cson_amalgamation.c
	$(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $(OBJDIR)/cson_amalgamation.o -DCSON_FOSSIL_MODE







}

close $output_file
#
# End of the main.mk output
##############################################################################
##############################################################################







>
>
>
>
>
>
>







301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
writeln "\$(OBJDIR)/th_tcl.o:\t\$(SRCDIR)/th_tcl.c"
writeln "\t\$(XTCC) -c \$(SRCDIR)/th_tcl.c -o \$(OBJDIR)/th_tcl.o\n"

set opt {}
writeln {
$(OBJDIR)/cson_amalgamation.o: $(SRCDIR)/cson_amalgamation.c
	$(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $(OBJDIR)/cson_amalgamation.o -DCSON_FOSSIL_MODE

#
# The list of all the targets that do not correspond to real files. This stops
# 'make' from getting confused when someone makes an error in a rule.
#

.PHONY: all install test clean
}

close $output_file
#
# End of the main.mk output
##############################################################################
##############################################################################
464
465
466
467
468
469
470





471
472
473
474
475
476
477
endif

# With JSON support
ifdef FOSSIL_ENABLE_JSON
TCC += -DFOSSIL_ENABLE_JSON=1
RCC += -DFOSSIL_ENABLE_JSON=1
endif






#### We add the -static option here so that we can build a static
#    executable that will run in a chroot jail.
#
LIB = -static

# OpenSSL: Add the necessary libraries required, if enabled.







>
>
>
>
>







471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
endif

# With JSON support
ifdef FOSSIL_ENABLE_JSON
TCC += -DFOSSIL_ENABLE_JSON=1
RCC += -DFOSSIL_ENABLE_JSON=1
endif

# Fix buggy MinGW command line parsing
ifdef MINGW_BROKEN_MAINARGS
TCC += -DMINGW_BROKEN_MAINARGS
endif

#### We add the -static option here so that we can build a static
#    executable that will run in a chroot jail.
#
LIB = -static

# OpenSSL: Add the necessary libraries required, if enabled.
Changes to src/setup.c.
1612
1613
1614
1615
1616
1617
1618























1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636



1637
1638
1639
1640
1641
1642
1643
  @ <p><span class="note">Note:</span>  Your browser has probably cached these
  @ images, so you may need to press the Reload button before changes will
  @ take effect. </p>
  style_footer();
  db_end_transaction(0);
}

























/*
** WEBPAGE: admin_sql
**
** Run raw SQL commands against the database file using the web interface.
*/
void sql_page(void){
  const char *zQ = P("q");
  int go = P("go")!=0;
  login_check_credentials();
  if( !g.perm.Setup ){
    login_needed();
  }
  db_begin_transaction();
  style_header("Raw SQL Commands");
  @ <p><b>Caution:</b> There are no restrictions on the SQL that can be
  @ run by this page.  You can do serious and irrepairable damage to the
  @ repository.  Proceed with extreme caution.</p>



  @
  @ <p>Database names:<ul><li>repository &rarr; %s(db_name("repository"))
  if( g.configOpen ){
    @ <li>config &rarr; %s(db_name("configdb"))
  }
  if( g.localOpen ){
    @ <li>local-checkout &rarr; %s(db_name("localdb"))







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


















>
>
>







1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
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
  @ <p><span class="note">Note:</span>  Your browser has probably cached these
  @ images, so you may need to press the Reload button before changes will
  @ take effect. </p>
  style_footer();
  db_end_transaction(0);
}

/*
** Prevent the RAW SQL feature from being used to ATTACH a different
** database and query it.
**
** Actually, the RAW SQL feature only does a single statement per request.
** So it is not possible to ATTACH and then do a separate query.  This
** routine is not strictly necessary, therefore.  But it does not hurt
** to be paranoid.
*/
int raw_sql_query_authorizer(
  void *pError,
  int code,
  const char *zArg1,
  const char *zArg2,
  const char *zArg3,
  const char *zArg4
){
  if( code==SQLITE_ATTACH ){
    return SQLITE_DENY;
  }
  return SQLITE_OK;
}


/*
** WEBPAGE: admin_sql
**
** Run raw SQL commands against the database file using the web interface.
*/
void sql_page(void){
  const char *zQ = P("q");
  int go = P("go")!=0;
  login_check_credentials();
  if( !g.perm.Setup ){
    login_needed();
  }
  db_begin_transaction();
  style_header("Raw SQL Commands");
  @ <p><b>Caution:</b> There are no restrictions on the SQL that can be
  @ run by this page.  You can do serious and irrepairable damage to the
  @ repository.  Proceed with extreme caution.</p>
  @
  @ <p>Only a the first statement in the entry box will be run.
  @ Any subsequent statements will be silently ignored.</p>
  @
  @ <p>Database names:<ul><li>repository &rarr; %s(db_name("repository"))
  if( g.configOpen ){
    @ <li>config &rarr; %s(db_name("configdb"))
  }
  if( g.localOpen ){
    @ <li>local-checkout &rarr; %s(db_name("localdb"))
1669
1670
1671
1672
1673
1674
1675

1676
1677
1678
1679
1680
1681
1682
    int rc;
    const char *zTail;
    int nCol;
    int nRow = 0;
    int i;
    @ <hr />
    login_verify_csrf_secret();

    rc = sqlite3_prepare_v2(g.db, zQ, -1, &pStmt, &zTail);
    if( rc!=SQLITE_OK ){
      @ <div class="generalError">%h(sqlite3_errmsg(g.db))</div>
      sqlite3_finalize(pStmt);
    }else if( pStmt==0 ){
      /* No-op */
    }else if( (nCol = sqlite3_column_count(pStmt))==0 ){







>







1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
    int rc;
    const char *zTail;
    int nCol;
    int nRow = 0;
    int i;
    @ <hr />
    login_verify_csrf_secret();
    sqlite3_set_authorizer(g.db, raw_sql_query_authorizer, 0);
    rc = sqlite3_prepare_v2(g.db, zQ, -1, &pStmt, &zTail);
    if( rc!=SQLITE_OK ){
      @ <div class="generalError">%h(sqlite3_errmsg(g.db))</div>
      sqlite3_finalize(pStmt);
    }else if( pStmt==0 ){
      /* No-op */
    }else if( (nCol = sqlite3_column_count(pStmt))==0 ){
Changes to src/stash.c.
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
    stash_apply(stashid, nConflict);
    db_multi_exec("UPDATE vfile SET mtime=0 WHERE pathname IN "
                  "(SELECT origname FROM stashfile WHERE stashid=%d)",
                  stashid);
    undo_finish();
  }else
  if( memcmp(zCmd, "diff", nCmd)==0 ){
    const char *zDiffCmd = db_get("diff-command", 0);
    u64 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, "gdiff", nCmd)==0 ){
    const char *zDiffCmd = db_get("gdiff-command", 0);
    u64 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;







|






|

|







547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
    stash_apply(stashid, nConflict);
    db_multi_exec("UPDATE vfile SET mtime=0 WHERE pathname IN "
                  "(SELECT origname FROM stashfile WHERE stashid=%d)",
                  stashid);
    undo_finish();
  }else
  if( memcmp(zCmd, "diff", nCmd)==0 ){
    const char *zDiffCmd = diff_command_external(0);
    u64 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, "gdiff", nCmd)==0 ){
    const char *zDiffCmd = diff_command_external(1);
    u64 diffFlags = diff_options();
    if( g.argc>4 ) usage("gdiff 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;
Added test/cmdline.test.




























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#
# Copyright (c) 2011 D. Richard Hipp
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the Simplified BSD License (also
# known as the "2-Clause License" or "FreeBSD License".)
#
# This program is distributed in the hope that it will be useful,
# but without any warranty; without even the implied warranty of
# merchantability or fitness for a particular purpose.
#
# Author contact information:
#   drh@hwaci.com
#   http://www.hwaci.com/drh/
#
############################################################################
#
# Test command line parsing
#

proc cmd-line {testname args} {
  set i 1
  foreach {cmdline result} $args {
    fossil test-echo {*}$cmdline
    test cmd-line-$testname.$i {[lrange [split $::RESULT \n] 2 end]=="\{argv\[2\] = \[$result\]\}"}
    incr i
  }
}
cmd-line 100 abc abc {"abc"} abc
cmd-line 101 * {*} *.* {*.*}
Changes to win/Makefile.mingw.
143
144
145
146
147
148
149





150
151
152
153
154
155
156
endif

# With JSON support
ifdef FOSSIL_ENABLE_JSON
TCC += -DFOSSIL_ENABLE_JSON=1
RCC += -DFOSSIL_ENABLE_JSON=1
endif






#### We add the -static option here so that we can build a static
#    executable that will run in a chroot jail.
#
LIB = -static

# OpenSSL: Add the necessary libraries required, if enabled.







>
>
>
>
>







143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
endif

# With JSON support
ifdef FOSSIL_ENABLE_JSON
TCC += -DFOSSIL_ENABLE_JSON=1
RCC += -DFOSSIL_ENABLE_JSON=1
endif

# Fix buggy MinGW command line parsing
ifdef MINGW_BROKEN_MAINARGS
TCC += -DMINGW_BROKEN_MAINARGS
endif

#### We add the -static option here so that we can build a static
#    executable that will run in a chroot jail.
#
LIB = -static

# OpenSSL: Add the necessary libraries required, if enabled.