Fossil

Changes On Branch double-dash-flag
Login

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

Changes In Branch double-dash-flag Excluding Merge-Ins

This is equivalent to a diff from e5e094071d to 52ae3288ab

2019-09-27
23:56
Added -- support to (3-way-merge, open, sqlar, stash save|snapshot, tarball, touch, undo/redo, update, zip). ... (Closed-Leaf check-in: 52ae3288ab user: stephan tags: double-dash-flag)
22:51
Added -- support to (diff, finfo, grep, new). We can now grep for patterns which start with a dash. ... (check-in: 639b2c183e user: stephan tags: double-dash-flag)
18:47
Update the fingerprint mechanism so that it if the revised hash algorithm fails, it retries using the legacy hash algorithm before reporting an error (and alarming users). The revised hash is always stored. The "test-fingerprint" command is updated to show both the old and the new hash algorithm and the fingerprint currently stored in the localdb. ... (check-in: 36d3685833 user: drh tags: trunk)
16:10
Added -- support to (add, rm, mv). ... (check-in: 9a7101d5dc user: stephan tags: double-dash-flag)
15:45
fossil add: fixed leak of ignore-glob prompt string. ... (check-in: e5e094071d user: stephan tags: trunk)
2019-09-26
17:58
Remove the discussion of the "close" command from the fiveminutes.wiki document as the "close" command is not really needed, is rarely used, and serves no purpose in the document but to confuse the reader. ... (check-in: f6e635308c user: drh tags: trunk)

Changes to src/add.c.
242
243
244
245
246
247
248
249

250
251
252
253
254
255
256
242
243
244
245
246
247
248

249
250
251
252
253
254
255
256







-
+







  blob_reset(&repoName);
  return nAdd;
}

/*
** COMMAND: add
**
** Usage: %fossil add ?OPTIONS? FILE1 ?FILE2 ...?
** Usage: %fossil add ?OPTIONS? ?--? FILE1 ?FILE2 ...?
**
** Make arrangements to add one or more files or directories to the
** current checkout at the next commit.
**
** When adding files or directories recursively, filenames that begin
** with "." are excluded by default.  To include such files, add
** the "--dotfiles" option to the command-line.
274
275
276
277
278
279
280


281
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
274
275
276
277
278
279
280
281
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







+
+



















-
+







**    --case-sensitive <BOOL> Override the case-sensitive setting.
**    --dotfiles              include files beginning with a dot (".")
**    -f|--force              Add files without prompting
**    --ignore <CSG>          Ignore unmanaged files matching patterns from
**                            the comma separated list of glob patterns.
**    --clean <CSG>           Also ignore files matching patterns from
**                            the comma separated list of glob patterns.
**    --                      Treat all following arguments as files,
**                            even if they look like flags.
**
** See also: addremove, rm
*/
void add_cmd(void){
  int i;                     /* Loop counter */
  int vid;                   /* Currently checked out version */
  int nRoot;                 /* Full path characters in g.zLocalRoot */
  const char *zCleanFlag;    /* The --clean option or clean-glob setting */
  const char *zIgnoreFlag;   /* The --ignore option or ignore-glob setting */
  Glob *pIgnore, *pClean;    /* Ignore everything matching the glob patterns */
  unsigned scanFlags = 0;    /* Flags passed to vfile_scan() */
  int forceFlag;

  zCleanFlag = find_option("clean",0,1);
  zIgnoreFlag = find_option("ignore",0,1);
  forceFlag = find_option("force","f",0)!=0;
  if( find_option("dotfiles",0,0)!=0 ) scanFlags |= SCAN_ALL;

  /* We should be done with options.. */
  verify_all_options();
  verify_all_options2();

  db_must_be_within_tree();
  if( zCleanFlag==0 ){
    zCleanFlag = db_get("clean-glob", 0);
  }
  if( zIgnoreFlag==0 ){
    zIgnoreFlag = db_get("ignore-glob", 0);
330
331
332
333
334
335
336
337

338
339
340
341
342
343
344
332
333
334
335
336
337
338

339
340
341
342
343
344
345
346







-
+







    zName = blob_str(&fullName);
    isDir = file_isdir(zName, RepoFILE);
    if( isDir==1 ){
      vfile_scan(&fullName, nRoot-1, scanFlags, pClean, pIgnore, RepoFILE);
    }else if( isDir==0 ){
      fossil_warning("not found: %s", zName);
    }else{
      char *zTreeName = &zName[nRoot];
      const char *zTreeName = &zName[nRoot];
      if( !forceFlag && glob_match(pIgnore, zTreeName) ){
        Blob ans;
        char cReply;
        char *prompt = mprintf("file \"%s\" matches \"ignore-glob\".  "
                               "Add it (a=all/y/N)? ", zTreeName);
        prompt_user(prompt, &ans);
        fossil_free(prompt);
416
417
418
419
420
421
422
423

424
425
426
427
428
429
430
418
419
420
421
422
423
424

425
426
427
428
429
430
431
432







-
+







}

/*
** COMMAND: rm
** COMMAND: delete
** COMMAND: forget*
**
** Usage: %fossil rm|delete|forget FILE1 ?FILE2 ...?
** Usage: %fossil rm|delete|forget ?OPTIONS? ?--? FILE1 ?FILE2 ...?
**
** Remove one or more files or directories from the repository.
**
** The 'rm' and 'delete' commands do NOT normally remove the files from
** disk.  They just mark the files as no longer being part of the project.
** In other words, future changes to the named files will not be versioned.
** However, the default behavior of this command may be overridden via the
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
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







+
+
















-
+







**
** Options:
**   --soft                  Skip removing files from the checkout.
**                           This supersedes the --hard option.
**   --hard                  Remove files from the checkout.
**   --case-sensitive <BOOL> Override the case-sensitive setting.
**   -n|--dry-run            If given, display instead of run actions.
**   --                      Treat all following arguments as files,
**                           even if they look like flags.
**
** See also: addremove, add
*/
void delete_cmd(void){
  int i;
  int removeFiles;
  int dryRunFlag;
  int softFlag;
  int hardFlag;
  Stmt loop;

  dryRunFlag = find_option("dry-run","n",0)!=0;
  softFlag = find_option("soft",0,0)!=0;
  hardFlag = find_option("hard",0,0)!=0;

  /* We should be done with options.. */
  verify_all_options();
  verify_all_options2();

  db_must_be_within_tree();
  db_begin_transaction();
  if( g.argv[1][0]=='f' ){ /* i.e. "forget" */
    removeFiles = 0;
  }else if( softFlag ){
    removeFiles = 0;
822
823
824
825
826
827
828
829
830


831
832
833
834
835
836
837
826
827
828
829
830
831
832


833
834
835
836
837
838
839
840
841







-
-
+
+







  }
}

/*
** COMMAND: mv
** COMMAND: rename*
**
** Usage: %fossil mv|rename OLDNAME NEWNAME
**    or: %fossil mv|rename OLDNAME... DIR
** Usage: %fossil mv|rename ?OPTIONS? ?--? OLDNAME NEWNAME
**    or: %fossil mv|rename ?OPTIONS? ?--? 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.
**
** The 'mv' command does NOT normally rename or move the files on disk.
** This command merely records the fact that file names have changed so
** that appropriate notations can be made at the next commit/check-in.
848
849
850
851
852
853
854


855
856
857
858
859
860
861
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867







+
+







**
** Options:
**   --soft                  Skip moving files within the checkout.
**                           This supersedes the --hard option.
**   --hard                  Move files within the checkout.
**   --case-sensitive <BOOL> Override the case-sensitive setting.
**   -n|--dry-run            If given, display instead of run actions.
**   --                      Treat all following arguments as files,
**                           even if they look like flags.
**
** See also: changes, status
*/
void mv_cmd(void){
  int i;
  int vid;
  int moveFiles;
870
871
872
873
874
875
876
877

878
879
880
881
882
883
884

885
886
887
888
889
890
891
876
877
878
879
880
881
882

883
884
885
886
887
888
889

890
891
892
893
894
895
896
897







-
+






-
+








  db_must_be_within_tree();
  dryRunFlag = find_option("dry-run","n",0)!=0;
  softFlag = find_option("soft",0,0)!=0;
  hardFlag = find_option("hard",0,0)!=0;

  /* We should be done with options.. */
  verify_all_options();
  verify_all_options2();

  vid = db_lget_int("checkout", 0);
  if( vid==0 ){
    fossil_fatal("no checkout in which to rename files");
  }
  if( g.argc<4 ){
    usage("OLDNAME NEWNAME");
    usage("?OPTIONS? ?--? OLDNAME NEWNAME");
  }
  zDest = g.argv[g.argc-1];
  db_begin_transaction();
  if( g.argv[1][0]=='r' ){ /* i.e. "rename" */
    moveFiles = 0;
  }else if( softFlag ){
    moveFiles = 0;
908
909
910
911
912
913
914
915

916
917
918
919
920
921
922
914
915
916
917
918
919
920

921
922
923
924
925
926
927
928







-
+







  if( g.argc!=4 ){
    origType = -1;
  }else{
    origType = (file_isdir(g.argv[2], RepoFILE) == 1);
  }
  destType = file_isdir(zDest, RepoFILE);
  if( origType==-1 && destType!=1 ){
    usage("OLDNAME NEWNAME");
    usage("?OPTIONS? ?--? OLDNAME NEWNAME");
  }else if( origType==1 && destType==2 ){
    fossil_fatal("cannot rename '%s' to '%s' since another file named"
                 " '%s' exists", g.argv[2], zDest, zDest);
  }else if( origType==0 && destType!=1 ){
    Blob orig;
    file_tree_name(g.argv[2], &orig, 0, 1);
    db_multi_exec(
Changes to src/branch.c.
47
48
49
50
51
52
53






54
55
56
57
58
59
60
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66







+
+
+
+
+
+







  }
  return zBr;
}

/*
**  fossil branch new    NAME  BASIS ?OPTIONS?
**  argv0  argv1  argv2  argv3 argv4
**
** Or:
**
**  fossil branch new ?OPTIONS? NAME BASIS
**
**  with the "--" flag before NAME *or* BASIS.
*/
void branch_new(void){
  int rootid;            /* RID of the root check-in - what we branch off of */
  int brid;              /* RID of the branch check-in */
  int noSign;            /* True if the branch is unsigned */
  int i;                 /* Loop counter */
  char *zUuid;           /* Artifact ID of origin */
71
72
73
74
75
76
77
78

79
80
81
82
83
84
85
77
78
79
80
81
82
83

84
85
86
87
88
89
90
91







-
+







  int isPrivate = 0;     /* True if the branch should be private */

  noSign = find_option("nosign","",0)!=0;
  zColor = find_option("bgcolor","c",1);
  isPrivate = find_option("private",0,0)!=0;
  zDateOvrd = find_option("date-override",0,1);
  zUserOvrd = find_option("user-override",0,1);
  verify_all_options();
  verify_all_options2();
  if( g.argc<5 ){
    usage("new BRANCH-NAME BASIS ?OPTIONS?");
  }
  db_find_and_open_repository(0, 0);
  noSign = db_get_boolean("omitsign", 0)|noSign;
  if( db_get_boolean("clearsign", 0)==0 ){ noSign = 1; }

349
350
351
352
353
354
355

356
357
358
359
360
361
362
363


364
365
366
367
368
369
370
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







+








+
+







**        List all branches. Options:
**          -a|--all      List all branches.  Default show only open branches
**          -c|--closed   List closed branches.
**          -r            Reverse the sort order
**          -t            Show recently changed branches first
**
**    fossil branch new BRANCH-NAME BASIS ?OPTIONS?
**    fossil branch new ?OPTIONS? -- BRANCH-NAME BASIS
**
**        Create a new branch BRANCH-NAME off of check-in BASIS.
**        Supported options for this subcommand include:
**        --private             branch is private (i.e., remains local)
**        --bgcolor COLOR       use COLOR instead of automatic background
**        --nosign              do not sign contents on this branch
**        --date-override DATE  DATE to use instead of 'now'
**        --user-override USER  USER to use instead of the current default
**        --                    All arguments after this  are treated as
**                              non-flags.
**
**        DATE may be "now" or "YYYY-MM-DDTHH:MM:SS.SSS". If in
**        year-month-day form, it may be truncated, the "T" may be
**        replaced by a space, and it may also name a timezone offset
**        from UTC as "-HH:MM" (westward) or "+HH:MM" (eastward).
**        Either no timezone suffix or "Z" means UTC.
**
Changes to src/checkin.c.
350
351
352
353
354
355
356
357

358
359
360
361
362
363
364
350
351
352
353
354
355
356

357
358
359
360
361
362
363
364







-
+







  return relativePaths;
}

/*
** COMMAND: changes
** COMMAND: status
**
** Usage: %fossil changes|status ?OPTIONS? ?PATHS ...?
** Usage: %fossil changes|status ?OPTIONS? ?--? ?PATHS ...?
**
** Report the change status of files in the current checkout.  If one or
** more PATHS are specified, only changes among the named files and
** directories are reported.  Directories are searched recursively.
**
** The status command is similar to the changes command, except it lacks
** several of the options supported by changes and it has its own header
437
438
439
440
441
442
443


444
445
446
447
448
449
450
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452







+
+







**    --meta            Display files with metadata changes.
**    --unchanged       Display unchanged files.
**    --all             Display all managed files, i.e. all of the above.
**    --extra           Display unmanaged files.
**    --differ          Display modified and extra files.
**    --merge           Display merge contributors.
**    --no-merge        Do not display merge contributors.
**    --                Treat all following arguments as files,
**                      even if they look like flags.
**
** See also: extras, ls
*/
void status_cmd(void){
  /* Affirmative and negative flag option tables. */
  static const struct {
    const char *option; /* Flag name. */
524
525
526
527
528
529
530
531

532
533
534
535
536
537
538
526
527
528
529
530
531
532

533
534
535
536
537
538
539
540







-
+








  /* Get the --dotfiles argument, or read it from the dotfiles setting. */
  if( find_option("dotfiles", 0, 0) || db_get_boolean("dotfiles", 0) ){
    scanFlags = SCAN_ALL;
  }

  /* We should be done with options. */
  verify_all_options();
  verify_all_options2();

  /* Check for changed files. */
  vfile_check_signature(vid, useHash ? CKSIG_HASH : 0);

  /* Search for unmanaged files if requested. */
  if( flags & C_EXTRA ){
    Glob *pIgnore = glob_create(zIgnoreFlag);
645
646
647
648
649
650
651
652

653
654
655
656
657
658
659
647
648
649
650
651
652
653

654
655
656
657
658
659
660
661







-
+







  }
  db_finalize(&q);
}

/*
** COMMAND: ls
**
** Usage: %fossil ls ?OPTIONS? ?PATHS ...?
** Usage: %fossil ls ?OPTIONS? ?--? ?PATHS ...?
**
** List all files in the current checkout.  If PATHS is included, only the
** named files (or their children if directories) are shown.
**
** The ls command is essentially two related commands in one, depending on
** whether or not the -r option is given.  -r selects a specific check-in
** version to list, in which case -R can be used to select the repository.
673
674
675
676
677
678
679


680
681
682
683
684
685
686
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690







+
+







**
** Options:
**   --age                 Show when each file was committed.
**   -v|--verbose          Provide extra information about each file.
**   -t                    Sort output in time order.
**   -r VERSION            The specific check-in to list.
**   -R|--repository FILE  Extract info from repository FILE.
**   --                    Treat all following arguments as files,
**                         even if they look like flags.
**
** See also: changes, extras, status
*/
void ls_cmd(void){
  int vid;
  Stmt q;
  int verboseFlag;
698
699
700
701
702
703
704
705

706
707
708
709
710
711
712
702
703
704
705
706
707
708

709
710
711
712
713
714
715
716







-
+







  }
  showAge = find_option("age",0,0)!=0;
  zRev = find_option("r","r",1);
  timeOrder = find_option("t","t",0)!=0;

  if( zRev!=0 ){
    db_find_and_open_repository(0, 0);
    verify_all_options();
    verify_all_options2();
    ls_cmd_rev(zRev,verboseFlag,showAge,timeOrder);
    return;
  }else if( find_option("R",0,1)!=0 ){
    fossil_fatal("the -r is required in addition to -R");
  }

  db_must_be_within_tree();
803
804
805
806
807
808
809
810

811
812
813
814
815
816
817
807
808
809
810
811
812
813

814
815
816
817
818
819
820
821







-
+







  }
  db_finalize(&q);
}

/*
** COMMAND: extras
**
** Usage: %fossil extras ?OPTIONS? ?PATH1 ...?
** Usage: %fossil extras ?OPTIONS? ?--? ?PATH1 ...?
**
** Print a list of all files in the source tree that are not part of the
** current checkout. See also the "clean" command. If paths are specified,
** only files in the given directories will be listed.
**
** Files and subdirectories whose names begin with "." are normally
** ignored but can be included by adding the --dotfiles option.
827
828
829
830
831
832
833


834
835
836
837
838
839
840
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846







+
+







**    --abs-paths      Display absolute pathnames.
**    --case-sensitive <BOOL> override case-sensitive setting
**    --dotfiles       include files beginning with a dot (".")
**    --header         Identify the repository if there are extras
**    --ignore <CSG>   ignore files matching patterns from the argument
**    --rel-paths      Display pathnames relative to the current working
**                     directory.
**    --               Treat all following arguments as files,
**                     even if they look like flags.
**
** See also: changes, clean, status
*/
void extras_cmd(void){
  Blob report = BLOB_INITIALIZER;
  const char *zIgnoreFlag = find_option("ignore",0,1);
  unsigned scanFlags = find_option("dotfiles",0,0)!=0 ? SCAN_ALL : 0;
848
849
850
851
852
853
854
855

856
857
858
859
860
861
862
854
855
856
857
858
859
860

861
862
863
864
865
866
867
868







-
+







  if( determine_cwd_relative_option() ){
    flags |= C_RELPATH;
  }

  if( db_get_boolean("dotfiles", 0) ) scanFlags |= SCAN_ALL;

  /* We should be done with options.. */
  verify_all_options();
  verify_all_options2();

  if( zIgnoreFlag==0 ){
    zIgnoreFlag = db_get("ignore-glob", 0);
  }
  pIgnore = glob_create(zIgnoreFlag);
  /* Always consider symlinks. */
  g.allowSymlinks = db_allow_symlinks_by_default();
874
875
876
877
878
879
880
881

882
883
884
885
886
887
888
880
881
882
883
884
885
886

887
888
889
890
891
892
893
894







-
+







  }
  blob_reset(&report);
}

/*
** COMMAND: clean
**
** Usage: %fossil clean ?OPTIONS? ?PATH ...?
** Usage: %fossil clean ?OPTIONS? ?--? ?PATH ...?
**
** Delete all "extra" files in the source tree.  "Extra" files are files
** that are not officially part of the checkout.  If one or more PATH
** arguments appear, then only the files named, or files contained with
** directories named, will be removed.
**
** If the --prompt option is used, prompts are issued to confirm the
951
952
953
954
955
956
957


958
959
960
961
962
963
964
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972







+
+







**                     list of glob patterns.
**    -n|--dry-run     Delete nothing, but display what would have been
**                     deleted.
**    --no-prompt      This option disables prompting the user for input
**                     and assumes an answer of 'No' for every question.
**    --temp           Remove only Fossil-generated temporary files.
**    -v|--verbose     Show all files as they are removed.
**    --               Treat all following arguments as files,
**                     even if they look like flags.
**
** See also: addremove, extras, status
*/
void clean_cmd(void){
  int allFileFlag, allDirFlag, dryRunFlag, verboseFlag;
  int emptyDirsFlag, dirsOnlyFlag;
  int disableUndo, noPrompt;
1008
1009
1010
1011
1012
1013
1014
1015

1016
1017
1018
1019
1020
1021
1022
1016
1017
1018
1019
1020
1021
1022

1023
1024
1025
1026
1027
1028
1029
1030







-
+







  if( zKeepFlag==0 && !verilyFlag ){
    zKeepFlag = db_get("keep-glob", 0);
  }
  if( zCleanFlag==0 && !verilyFlag ){
    zCleanFlag = db_get("clean-glob", 0);
  }
  if( db_get_boolean("dotfiles", 0) ) scanFlags |= SCAN_ALL;
  verify_all_options();
  verify_all_options2();
  pIgnore = glob_create(zIgnoreFlag);
  pKeep = glob_create(zKeepFlag);
  pClean = glob_create(zCleanFlag);
  nRoot = (int)strlen(g.zLocalRoot);
  /* Always consider symlinks. */
  g.allowSymlinks = db_allow_symlinks_by_default();
  if( !dirsOnlyFlag ){
1936
1937
1938
1939
1940
1941
1942
1943
1944


1945
1946
1947
1948
1949
1950
1951
1944
1945
1946
1947
1948
1949
1950


1951
1952
1953
1954
1955
1956
1957
1958
1959







-
-
+
+







  return fossil_strcmp(pA[0], pB[0]);
}

/*
** COMMAND: ci*
** COMMAND: commit
**
** Usage: %fossil commit ?OPTIONS? ?FILE...?
**    or: %fossil ci ?OPTIONS? ?FILE...?
** Usage: %fossil commit ?OPTIONS? ?--? ?FILE...?
**    or: %fossil ci ?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
** file containing the comment using -M.  The editor defined in the
** "editor" fossil option (see %fossil help set) will be used, or from
** the "VISUAL" or "EDITOR" environment variables (in that order) if
2018
2019
2020
2021
2022
2023
2024


2025
2026
2027
2028
2029
2030
2031
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041







+
+







**    --override-lock            allow a check-in even though parent is locked
**    --private                  do not sync changes and their descendants
**    --hash                     verify file status using hashing rather
**                               than relying on file mtimes
**    --tag TAG-NAME             assign given tag TAG-NAME to the check-in
**    --date-override DATETIME   DATE to use instead of 'now'
**    --user-override USER       USER to use instead of the current default
**    --                         Treat all following arguments as files,
**                               even if they look like flags.
**
** DATETIME may be "now" or "YYYY-MM-DDTHH:MM:SS.SSS". If in
** year-month-day form, it may be truncated, the "T" may be replaced by
** a space, and it may also name a timezone offset from UTC as "-HH:MM"
** (westward) or "+HH:MM" (eastward). Either no timezone suffix or "Z"
** means UTC.
**
2121
2122
2123
2124
2125
2126
2127
2128

2129
2130
2131
2132
2133
2134
2135
2131
2132
2133
2134
2135
2136
2137

2138
2139
2140
2141
2142
2143
2144
2145







-
+







  sCiInfo.zDateOvrd = find_option("date-override",0,1);
  sCiInfo.zUserOvrd = find_option("user-override",0,1);
  db_must_be_within_tree();
  noSign = db_get_boolean("omitsign", 0)|noSign;
  if( db_get_boolean("clearsign", 0)==0 ){ noSign = 1; }
  useCksum = db_get_boolean("repo-cksum", 1);
  outputManifest = db_get_manifest_setting();
  verify_all_options();
  verify_all_options2();

  /* Get the ID of the parent manifest artifact */
  vid = db_lget_int("checkout", 0);
  if( vid==0 ){
    useCksum = 1;
    if( sCiInfo.zBranch==0 ) {
      sCiInfo.zBranch=db_get("main-branch", 0);
Changes to src/clone.c.
78
79
80
81
82
83
84
85

86
87
88
89
90
91
92
78
79
80
81
82
83
84

85
86
87
88
89
90
91
92







-
+







  );
}


/*
** COMMAND: clone
**
** Usage: %fossil clone ?OPTIONS? URI FILENAME
** Usage: %fossil clone ?OPTIONS? URI ?--? FILENAME
**
** Make a clone of a repository specified by URI in the local
** file named FILENAME.
**
** URI may be one of the following form: ([...] mean optional)
**   HTTP/HTTPS protocol:
**     http[s]://[userid[:password]@]host[:port][/path]
116
117
118
119
120
121
122


123
124
125
126
127
128
129
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131







+
+







**    --once                     Don't remember the URI.
**    --private                  Also clone private branches
**    --save-http-password       Remember the HTTP password without asking
**    --ssh-command|-c SSH       Use SSH as the "ssh" command
**    --ssl-identity FILENAME    Use the SSL identity if requested by the server
**    -u|--unversioned           Also sync unversioned content
**    -v|--verbose               Show more statistics in output
**    --                         Treat all following arguments as files,
**                               even if they look like flags.
**
** See also: init
*/
void clone_cmd(void){
  char *zPassword;
  const char *zDefaultUser;   /* Optional name of the default user */
  const char *zHttpAuth;      /* HTTP Authorization user:pass information */
143
144
145
146
147
148
149
150

151
152
153
154
155
156
157
145
146
147
148
149
150
151

152
153
154
155
156
157
158
159







-
+







  if( find_option("unversioned","u",0)!=0 ) syncFlags |= SYNC_UNVERSIONED;
  zHttpAuth = find_option("httpauth","B",1);
  zDefaultUser = find_option("admin-user","A",1);
  clone_ssh_find_options();
  url_proxy_options();

  /* We should be done with options.. */
  verify_all_options();
  verify_all_options2();

  if( g.argc < 4 ){
    usage("?OPTIONS? FILE-OR-URL NEW-REPOSITORY");
  }
  db_open_config(0, 0);
  if( -1 != file_size(g.argv[3], ExtFILE) ){
    fossil_fatal("file already exists: %s", g.argv[3]);
Changes to src/content.c.
308
309
310
311
312
313
314
315

316
317
318
319
320
321
322




323
324
325
326
327
328
329
330

331
332


333
334
335
336
337
338
339
308
309
310
311
312
313
314

315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335


336
337
338
339
340
341
342
343
344







-
+







+
+
+
+








+
-
-
+
+







  }
  return rc;
}

/*
** COMMAND: artifact*
**
** Usage: %fossil artifact ARTIFACT-ID ?OUTPUT-FILENAME? ?OPTIONS?
** Usage: %fossil artifact ARTIFACT-ID ?OPTIONS? ?--? ?OUTPUT-FILENAME?
**
** Extract an artifact by its artifact hash and write the results on
** standard output, or if the optional 4th argument is given, in
** the named output file.
**
** Options:
**    -R|--repository FILE       Extract artifacts from repository FILE
**    --                         Treat all following arguments as files,
**                               even if they look like flags and treat
**                               output filename "-" as a literal filename
**                               instead of an alias for stdout.
**
** See also: finfo
*/
void artifact_cmd(void){
  int rid;
  Blob content;
  const char *zFile;
  db_find_and_open_repository(OPEN_ANY_SCHEMA, 0);
  verify_all_options2();
  if( g.argc!=4 && g.argc!=3 ) usage("ARTIFACT-ID ?FILENAME? ?OPTIONS?");
  zFile = g.argc==4 ? g.argv[3] : "-";
  if( g.argc!=4 && g.argc!=3 ) usage("ARTIFACT-ID ?OPTIONS? ?--? ?FILENAME?");
  zFile = g.argc==4 ? get_dash_filename_arg(3) : "-";
  rid = name_to_rid(g.argv[2]);
  if( rid==0 ){
    fossil_fatal("%s",g.zErrMsg);
  }
  content_get(rid, &content);
  blob_write_to_file(&content, zFile);
}
Changes to src/db.c.
2211
2212
2213
2214
2215
2216
2217
2218
2219


2220
2221
2222
2223
2224
2225
2226
2211
2212
2213
2214
2215
2216
2217


2218
2219
2220
2221
2222
2223
2224
2225
2226







-
-
+
+







  }
}

/*
** COMMAND: new*
** COMMAND: init
**
** Usage: %fossil new ?OPTIONS? FILENAME
**    or: %fossil init ?OPTIONS? FILENAME
** 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
** a copy of an existing project.  This command starts a new project.
**
** By default, your current login name is used to create the default
** admin user. This can be overridden using the -A|--admin-user
2236
2237
2238
2239
2240
2241
2242


2243
2244
2245
2246
2247
2248
2249
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251







+
+







** associated permissions will be copied.
**
** Options:
**    --template      FILE         Copy settings from repository file
**    --admin-user|-A USERNAME     Select given USERNAME as admin user
**    --date-override DATETIME     Use DATETIME as time of the initial check-in
**    --sha1                       Use a initial hash policy of "sha1"
**    --                           Treat all following arguments as files,
**                                 even if they look like flags.
**
** DATETIME may be "now" or "YYYY-MM-DDTHH:MM:SS.SSS". If in
** year-month-day form, it may be truncated, the "T" may be replaced by
** a space, and it may also name a timezone offset from UTC as "-HH:MM"
** (westward) or "+HH:MM" (eastward). Either no timezone suffix or "Z"
** means UTC.
**
2258
2259
2260
2261
2262
2263
2264
2265

2266
2267
2268
2269
2270
2271
2272
2260
2261
2262
2263
2264
2265
2266

2267
2268
2269
2270
2271
2272
2273
2274







-
+









  zTemplate = find_option("template",0,1);
  zDate = find_option("date-override",0,1);
  zDefaultUser = find_option("admin-user","A",1);
  bUseSha1 = find_option("sha1",0,0)!=0;
  /* We should be done with options.. */
  verify_all_options();
  verify_all_options2();

  if( g.argc!=3 ){
    usage("REPOSITORY-NAME");
  }

  if( -1 != file_size(g.argv[2], ExtFILE) ){
    fossil_fatal("file already exists: %s", g.argv[2]);
2900
2901
2902
2903
2904
2905
2906
2907

2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924



2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945

2946
2947
2948
2949
2950
2951
2952
2902
2903
2904
2905
2906
2907
2908

2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949

2950
2951
2952
2953
2954
2955
2956
2957







-
+

















+
+
+




















-
+







  }
  blob_reset(&full);
}

/*
** COMMAND: open
**
** Usage: %fossil open FILENAME ?VERSION? ?OPTIONS?
** Usage: %fossil open ?OPTIONS? ?--? FILENAME ?VERSION?
**
** Open a connection to the local repository in FILENAME.  A checkout
** for the repository is created with its root at the working directory.
** If VERSION is specified then that version is checked out.  Otherwise
** the latest version is checked out.  No files other than "manifest"
** and "manifest.uuid" are modified if the --keep option is present.
**
** Options:
**   --empty           Initialize checkout as being empty, but still connected
**                     with the local repository. If you commit this checkout,
**                     it will become a new "initial" commit in the repository.
**   --keep            Only modify the manifest and manifest.uuid files
**   --nested          Allow opening a repository inside an opened checkout
**   --force-missing   Force opening a repository with missing content
**   --setmtime        Set timestamps of all files to match their SCM-side
**                     times (the timestamp of the last checkin which modified
**                     them).
**   --                Treat all following arguments as files, even if they
**                     look like flags. Use before the FILENAME or VERSION,
**                     but not both.
**
** See also: close
*/
void cmd_open(void){
  int emptyFlag;
  int keepFlag;
  int forceMissingFlag;
  int allowNested;
  int allowSymlinks;
  int setmtimeFlag;              /* --setmtime.  Set mtimes on files */
  static char *azNewArgv[] = { 0, "checkout", "--prompt", 0, 0, 0, 0 };

  url_proxy_options();
  emptyFlag = find_option("empty",0,0)!=0;
  keepFlag = find_option("keep",0,0)!=0;
  forceMissingFlag = find_option("force-missing",0,0)!=0;
  allowNested = find_option("nested",0,0)!=0;
  setmtimeFlag = find_option("setmtime",0,0)!=0;

  /* We should be done with options.. */
  verify_all_options();
  verify_all_options2();

  if( g.argc!=3 && g.argc!=4 ){
    usage("REPOSITORY-FILENAME ?VERSION?");
  }
  if( !allowNested && db_open_local(0) ){
    fossil_fatal("already within an open tree rooted at %s", g.zLocalRoot);
  }
Changes to src/diff.c.
2532
2533
2534
2535
2536
2537
2538
2539

2540
2541
2542
2543
2544
2545
2546
2532
2533
2534
2535
2536
2537
2538

2539
2540
2541
2542
2543
2544
2545
2546







-
+







}

/*
** COMMAND: annotate
** COMMAND: blame
** COMMAND: praise
**
** Usage: %fossil annotate|blame|praise ?OPTIONS? FILENAME
** Usage: %fossil annotate|blame|praise ?OPTIONS? ?--? FILENAME
**
** Output the text of a file with markings to show when each line of the file
** was last modified.  The version currently checked out is shown by default.
** Other versions may be specified using the -r option.  The "annotate" command
** shows line numbers and omits the username.  The "blame" and "praise" commands
** show the user who made each check-in.
**
2563
2564
2565
2566
2567
2568
2569


2570
2571
2572
2573
2574
2575
2576
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578







+
+







**                                 Xs     As much as possible in X seconds
**                                 none   No limit
**   -o|--origin VERSION         The origin check-in. By default this is the
**                                 root of the repository. Set to "trunk" or
**                                 similar for a reverse annotation.
**   -w|--ignore-all-space       Ignore white space when comparing lines
**   -Z|--ignore-trailing-space  Ignore whitespace at line end
**   --                          Treat all following arguments as files,
**                               even if they look like flags.
**
** See also: info, finfo, timeline
*/
void annotate_cmd(void){
  const char *zRevision; /* Revision name, or NULL for current check-in */
  Annotator ann;         /* The annotation of the file */
  int i;                 /* Loop counter */
2595
2596
2597
2598
2599
2600
2601
2602

2603
2604
2605
2606
2607
2608
2609
2597
2598
2599
2600
2601
2602
2603

2604
2605
2606
2607
2608
2609
2610
2611







-
+







  if( find_option("ignore-all-space","w",0)!=0 ){
    annFlags = DIFF_IGNORE_ALLWS; /* stronger than DIFF_IGNORE_EOLWS */
  }
  fileVers = find_option("filevers",0,0)!=0;
  db_must_be_within_tree();

  /* We should be done with options.. */
  verify_all_options();
  verify_all_options2();

  if( g.argc<3 ) {
    usage("FILENAME");
  }

  annFlags |= DIFF_STRIP_EOLCR;
  file_tree_name(g.argv[2], &treename, 0, 1);
Changes to src/diffcmd.c.
778
779
780
781
782
783
784
785

786
787
788
789
790
791
792
778
779
780
781
782
783
784

785
786
787
788
789
790
791
792







-
+







  return zBinGlob;
}

/*
** COMMAND: diff
** COMMAND: gdiff
**
** Usage: %fossil diff|gdiff ?OPTIONS? ?FILE1? ?FILE2 ...?
** Usage: %fossil diff|gdiff ?OPTIONS? ?--? ?FILE1? ?FILE2 ...?
**
** Show the difference between the current version of each of the FILEs
** specified (as they exist on disk) and that same file as it was checked
** out.  Or if the FILE arguments are omitted, show the unsaved changes
** currently in the working check-out.
**
** If the "--from VERSION" or "-r VERSION" option is used it specifies
837
838
839
840
841
842
843


844
845
846
847
848
849
850
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852







+
+







**   --to VERSION               Select VERSION as target for the diff
**   --undo                     Diff against the "undo" buffer
**   --unified                  Unified diff
**   -v|--verbose               Output complete text of added or deleted files
**   -w|--ignore-all-space      Ignore white space when comparing lines
**   -W|--width <num>           Width of lines in side-by-side diff
**   -Z|--ignore-trailing-space Ignore changes to end-of-line whitespace
**   --                         Treat all following arguments as files,
**                              even if they look like flags.
*/
void diff_cmd(void){
  int isGDiff;               /* True for gdiff.  False for normal diff */
  int isInternDiff;          /* True for internal diff */
  int verboseFlag;           /* True if -v or --verbose flag is used */
  const char *zFrom;         /* Source version number */
  const char *zTo;           /* Target version number */
898
899
900
901
902
903
904
905

906
907
908
909
910
911
912
900
901
902
903
904
905
906

907
908
909
910
911
912
913
914







-
+







  if( !isInternDiff ){
    zDiffCmd = find_option("command", 0, 1);
    if( zDiffCmd==0 ) zDiffCmd = diff_command_external(isGDiff);
  }
  zBinGlob = diff_get_binary_glob();
  fIncludeBinary = diff_include_binary_files();
  determine_exec_relative_option(1);
  verify_all_options();
  verify_all_options2();
  if( g.argc>=3 ){
    int i;
    Blob fname;
    pFileDir = fossil_malloc( sizeof(*pFileDir) * (g.argc-1) );
    memset(pFileDir, 0, sizeof(*pFileDir) * (g.argc-1));
    for(i=2; i<g.argc; i++){
      file_tree_name(g.argv[i], &fname, 0, 1);
Changes to src/file.c.
1997
1998
1999
2000
2001
2002
2003
2004

2005
2006
2007
2008
2009
2010
2011
1997
1998
1999
2000
2001
2002
2003

2004
2005
2006
2007
2008
2009
2010
2011







-
+







  db_reset(&q);
  return mrid;
}

/*
** COMMAND: touch*
**
** Usage: %fossil touch ?OPTIONS? ?FILENAME...?
** Usage: %fossil touch ?OPTIONS? ?--? ?FILENAME...?
**
** For each file in the current checkout matching one of the provided
** list of glob patterns and/or file names, the file's mtime is
** updated to a value specified by one of the flags --checkout,
** --checkin, or --now.
**
** If neither glob patterns nor filenames are provided, it operates on
2026
2027
2028
2029
2030
2031
2032


2033
2034
2035
2036
2037
2038
2039
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041







+
+







**                  fossil-conventional glob list file.
**   -v|-verbose    Outputs extra information about its globs
**                  and each file it touches.
**   -n|--dry-run   Outputs which files would require touching,
**                  but does not touch them.
**   -q|--quiet     Suppress warnings, e.g. when skipping unmanaged
**                  or out-of-tree files.
**   --             Treat all following arguments as non-flags, even if
**                  they look like flags.
**
** Only one of --now, --checkin, and --checkout may be used. The
** default is --now.
**
** Only one of -g or -G may be used. If neither is provided and no
** additional filenames are provided, the effect is as if a glob of
** '*' were provided, i.e. all files belonging to the
2098
2099
2100
2101
2102
2103
2104
2105

2106
2107
2108
2109
2110
2111
2112
2100
2101
2102
2103
2104
2105
2106

2107
2108
2109
2110
2111
2112
2113
2114







-
+







      timeFlag = 0;
      if(verboseFlag){
        fossil_print("Timestamp = current system time.\n");
      }
    }
  }

  verify_all_options();
  verify_all_options2();

  db_must_be_within_tree();
  vid = db_lget_int("checkout", 0);
  if(vid==0){
    fossil_fatal("Cannot determine checkout version.");
  }

Changes to src/finfo.c.
19
20
21
22
23
24
25
26

27
28
29
30
31
32
33
19
20
21
22
23
24
25

26
27
28
29
30
31
32
33







-
+







*/
#include "config.h"
#include "finfo.h"

/*
** COMMAND: finfo
**
** Usage: %fossil finfo ?OPTIONS? FILENAME
** Usage: %fossil finfo ?OPTIONS? ?--? FILENAME
**
** Print the complete change history for a single file going backwards
** in time.  The default mode is -l.
**
** For the -l|--log mode: If "-b|--brief" is specified one line per revision
** is printed, otherwise the full comment is printed.  The "-n|--limit N"
** and "--offset P" options limits the output to the first N changes
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
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







+
+












-
+







**   -p|--print           select print mode
**   -r|--revision R      print the given revision (or ckout, if none is given)
**                        to stdout (only in print mode)
**   -s|--status          select status mode (print a status indicator for FILE)
**   -W|--width <num>     Width of lines (default is to auto-detect). Must be
**                        >22 or 0 (= no limit, resulting in a single line per
**                        entry).
**   --                   Treat all following arguments as files, even if they
**                        look like flags.
**
** See also: artifact, cat, descendants, info, leaves
*/
void finfo_cmd(void){
  db_must_be_within_tree();
  if( find_option("status","s",0) ){
    Stmt q;
    Blob line;
    Blob fname;
    int vid;

    /* We should be done with options.. */
    verify_all_options();
    verify_all_options2();

    if( g.argc!=3 ) usage("-s|--status FILENAME");
    vid = db_lget_int("checkout", 0);
    if( vid==0 ){
      fossil_fatal("no checkout to finfo files in");
    }
    vfile_check_signature(vid, CKSIG_ENOTFILE);
118
119
120
121
122
123
124
125

126
127
128
129
130
131
132
120
121
122
123
124
125
126

127
128
129
130
131
132
133
134







-
+







    blob_reset(&line);
  }else if( find_option("print","p",0) ){
    Blob record;
    Blob fname;
    const char *zRevision = find_option("revision", "r", 1);

    /* We should be done with options.. */
    verify_all_options();
    verify_all_options2();

    file_tree_name(g.argv[2], &fname, 0, 1);
    if( zRevision ){
      historical_blob(zRevision, blob_str(&fname), &record, 1);
    }else{
      int rid = db_int(0, "SELECT rid FROM vfile WHERE pathname=%B %s",
                       &fname, filename_collation());
167
168
169
170
171
172
173
174

175
176
177
178
179
180
181
169
170
171
172
173
174
175

176
177
178
179
180
181
182
183







-
+







        fossil_fatal("-W|--width value must be >22 or 0");
      }
    }else{
      iWidth = -1;
    }

    /* We should be done with options.. */
    verify_all_options();
    verify_all_options2();

    if( g.argc!=3 ){
      usage("?-l|--log? ?-b|--brief? FILENAME");
    }
    file_tree_name(g.argv[2], &fname, 0, 1);
    rid = db_int(0, "SELECT rid FROM vfile WHERE pathname=%B %s",
                 &fname, filename_collation());
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
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







-
+








+
+











-
+







    blob_reset(&fname);
  }
}

/*
** COMMAND: cat
**
** Usage: %fossil cat FILENAME ... ?OPTIONS?
** Usage: %fossil cat ?OPTIONS? ?--? FILENAME ...
**
** Print on standard output the content of one or more files as they exist
** in the repository.  The version currently checked out is shown by default.
** Other versions may be specified using the -r option.
**
** Options:
**    -R|--repository FILE       Extract artifacts from repository FILE
**    -r VERSION                 The specific check-in containing the file
**    --                         Treat all following arguments as files,
**                               even if they look like flags.
**
** See also: finfo
*/
void cat_cmd(void){
  int i;
  Blob content, fname;
  const char *zRev;
  db_find_and_open_repository(0, 0);
  zRev = find_option("r","r",1);

  /* We should be done with options.. */
  verify_all_options();
  verify_all_options2();

  for(i=2; i<g.argc; i++){
    file_tree_name(g.argv[i], &fname, 0, 1);
    blob_zero(&content);
    historical_blob(zRev, blob_str(&fname), &content, 1);
    blob_write_to_file(&content, "-");
    blob_reset(&fname);
Changes to src/main.c.
139
140
141
142
143
144
145



146
147
148
149
150
151
152
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155







+
+
+







  void *xPostEval;       /* Optional, called after Tcl_Eval*(). */
  void *pPostContext;    /* Optional, provided to xPostEval(). */
};
#endif

struct Global {
  int argc; char **argv;  /* Command-line arguments to the program */
  int argDashDashIndex;   /* Index of the "--" flag in g.argv, if provided
                          ** (else 0). Not valid until verify_all_options()
                          ** or verify_all_options2() is called. */;
  char *nameOfExe;        /* Full path of executable. */
  const char *zErrlog;    /* Log errors to this file, if not NULL */
  int isConst;            /* True if the output is unchanging & cacheable */
  const char *zVfsName;   /* The VFS to use for database connections */
  sqlite3 *db;            /* The connection to the databases */
  sqlite3 *dbConfig;      /* Separate connection for global_config table */
  char *zAuxSchema;       /* Main repository aux-schema */
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
925
926

927
928
929
930
931
932
933
901
902
903
904
905
906
907


908
909
910
911
912
913
914
915
916
917


918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940

941
942
943
944
945
946
947
948







-
-
+
+
+
+

+
+
+
+

-
-
+
+
+
+
+
+
+
+















-
+







    g.argv[i] = g.argv[j];
  }
  g.argc = i;
}


/*
** Look for a command-line option.  If present, return a pointer.
** Return NULL if missing.
** Look for a command-line option.  If present, remove it from the
** argument list and return a pointer to either the flag's name (if
** hasArg==0), sans leading - or --, or its value (if hasArg==1).
** Return NULL if the flag is not found.
**
** zLong is the "long" form of the flag and zShort is the
** short/abbreviated form (typically a single letter, but it may be
** longer). zLong must not be NULL, but zShort may be.
**
** hasArg==0 means the option is a flag.  It is either present or not.
** hasArg==1 means the option has an argument.  Return a pointer to the
** argument.
** hasArg==1 means the option has an argument, in which case a pointer
** to the argument's value is returned. For zLong, a flag value (if
** hasValue==1) may either be in the form (--flag=value) or (--flag
** value). For zShort, only the latter form is accepted.
**
** If a standalone argument of "--" is encountered in the argument
** list while searching for the given flag(s), this routine stops
** searching and NULL is returned.
*/
const char *find_option(const char *zLong, const char *zShort, int hasArg){
  int i;
  int nLong;
  const char *zReturn = 0;
  assert( hasArg==0 || hasArg==1 );
  nLong = strlen(zLong);
  for(i=1; i<g.argc; i++){
    char *z;
    if( i+hasArg >= g.argc ) break;
    z = g.argv[i];
    if( z[0]!='-' ) continue;
    z++;
    if( z[0]=='-' ){
      if( z[1]==0 ){
        remove_from_argv(i, 1);
        /* Stop processing at "--" */
        break;
      }
      z++;
    }
    if( strncmp(z,zLong,nLong)==0 ){
      if( hasArg && z[nLong]=='=' ){
        zReturn = &z[nLong+1];
953
954
955
956
957
958
959
960







961
962
963
964
965
966
967
968
969
970
971
972
973
974




975
976
977
978
979
980
981
968
969
970
971
972
973
974

975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994

995
996
997
998
999
1000
1001
1002
1003
1004
1005







-
+
+
+
+
+
+
+













-
+
+
+
+







int has_option(const char *zOption){
  int i;
  int n = (int)strlen(zOption);
  for(i=1; i<g.argc; i++){
    char *z = g.argv[i];
    if( z[0]!='-' ) continue;
    z++;
    if( z[0]=='-' ) z++;
    if( z[0]=='-' ){
      z++;
      if( z[0]==0 ){
        /* Stop searching at "--" */
        break;
      }
    }
    if( strncmp(z,zOption,n)==0 && (z[n]==0 || z[n]=='=') ) return 1;
  }
  return 0;
}

/*
** Look for multiple occurrences of a command-line option with the
** corresponding argument.
**
** Return a malloc allocated array of pointers to the arguments.
**
** pnUsedArgs is used to store the number of matched arguments.
**
** Caller is responsible to free allocated memory.
** Caller is responsible for freeing allocated memory by passing the
** head of the array (not each entry) to fossil_free(). (The
** individual entries have the same lifetime as values returned from
** find_option().)
*/
const char **find_repeatable_option(
  const char *zLong,
  const char *zShort,
  int *pnUsedArgs
){
  const char *zOption;
1011
1012
1013
1014
1015
1016
1017


















1018
1019

1020

1021

1022
1023
1024
1025
1026
1027
1028
1029











































































1030
1031
1032
1033
1034
1035
1036
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060

1061
1062
1063
1064
1065








1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
+

+

+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







  return g.zRepositoryOption;
}

/*
** Verify that there are no unprocessed command-line options.  If
** Any remaining command-line argument begins with "-" print
** an error message and quit.
**
** If fAllowDoubleDash is true then if the flag "--" is found, it is
** removed from the list and arguments after that flag are not
** inspected by this function (they are assumed to be
** file/wiki/branch/etc. names, even if they syntactically look like
** flags). If fAllowDoubleDash is false then the "--" flag will
** trigger a fatal error exactly as if an unprocessed flag were
** encountered.
**
** Returns false (0) if fAllowDoubleDash is false or if "--" is not
** encountered. If fAllowDoubleDash is true and "--" is encountered,
** the argument index (in g.argv) at which "--" was encountered (and
** removed) is returned (that value will always be greater than 0).
**
** Sidebar: the question of whether fAllowDoubleDash should be true or
** false would seem to boil down to: does the calling routine
** expect/allow arbitrary file/page/branch/whatever name arguments
** after its required arguments?
*/
void verify_all_options(void){
static int verify_all_options_impl(int fAllowDoubleDash){
  int i;
  g.argDashDashIndex = 0;
  for(i=1; i<g.argc; i++){
    const char * arg = g.argv[i];
    if( g.argv[i][0]=='-' && g.argv[i][1]!=0 ){
      fossil_fatal(
        "unrecognized command-line option, or missing argument: %s",
        g.argv[i]);
    }
  }
}

    if( arg[0]=='-' ){
      if( arg[1]=='-' && arg[2]==0 ){
        if(fAllowDoubleDash){
          /* Remove "--" from the list and assume any following
          ** arguments are file names. */
          remove_from_argv(i, 1);
          return g.argDashDashIndex = i;
        }else{
          fossil_fatal("The -- flag is not allowed here.");
        }
      }else if( arg[1]!=0 ){
        fossil_fatal(
          "unrecognized command-line option, or missing argument: %s",
          arg);
      }
    }
  }
  return 0;
}

/*
** Must be called by all commands which process CLI flags, after
** consuming those flags (via find_option() and friends), to confirm
** that no unconsumed flags are still in the arguments list.  If the
** command should/can honor the "--" flag, call verify_all_options2()
** instead.
*/
void verify_all_options(void){
  verify_all_options_impl(0);
}

/*
** Identical to verify_all_options() except that it honors the "--"
** flag and returns true (non-0) if that flag was encountered/consumed.
*/
int verify_all_options2(void){
  return verify_all_options_impl(1);
}

/*
** Expects nArgPos to be a valid index of g.argv. If nArgPos is a
** string with the value "-" and g.argDashDashIndex is greater than 0
** and <= nArgPos then the value "-" gets transformed to "./-". In all
** other cases, the value of g.argv[nArgPos] is returned as-is.
**
** The intention is that this function be called by commands which
** accept a filename argument for which "-" is interpreted as stdin or
** stdout. If the "--" flag was found BEFORE that filename flag then
** "-" is transformed such that it will be seen as a file named "./-"
** rather than "-" (stdin or stdout, depending on the context). Returns
** a string from g.argv or the static string "./-", so its lifetime is
** effectively that of the app.
*/
const char * get_dash_filename_arg(int nArgPos){
  const char * zName;
  assert(nArgPos < g.argc);
  zName = g.argv[nArgPos];
  if(zName!=0
     && g.argDashDashIndex>0 && g.argDashDashIndex<=nArgPos
     && fossil_strcmp("-",zName)==0){
    zName = "./-";
  }
  return zName;
};

/*
 ** Only for debugging during "--"-related refactoring. To be deleted
 ** before merging with trunk.
 */
void dump_g_argv(){
  int i;
  for( i = 0; i < g.argc; ++i ){
    fossil_print("\tg.argv[%d] = %s\n", i, g.argv[i]);
  }
}

/*
** This function returns a human readable version string.
*/
const char *get_version(){
  static const char version[] = RELEASE_VERSION " " MANIFEST_VERSION " "
                                MANIFEST_DATE " UTC";
Changes to src/merge3.c.
340
341
342
343
344
345
346
347

348
349
350
351
352
353
354



355
356
357
358
359
360
361
340
341
342
343
344
345
346

347
348
349
350
351
352
353

354
355
356
357
358
359
360
361
362
363







-
+






-
+
+
+







  blob_reset(&file);
  return rc;
}

/*
** COMMAND: 3-way-merge*
**
** Usage: %fossil 3-way-merge BASELINE V1 V2 MERGED
** Usage: %fossil 3-way-merge ?--? BASELINE V1 V2 MERGED
**
** Inputs are files BASELINE, V1, and V2.  The file MERGED is generated
** as output.
**
** BASELINE is a common ancestor of two files V1 and V2 that have diverging
** edits.  The generated output file MERGED is the combination of all
** changes in both V1 and V2.
** changes in both V1 and V2. The -- flag may be used one time, anywhere
** in the argument list, to mean that all following arguments should be
** treated as filenames even if they look like flags.
**
** This command has no effect on the Fossil repository.  It is a utility
** command made available for the convenience of users.  This command can
** be used, for example, to help import changes from an upstream project.
**
** Suppose an upstream project has a file named "Xup.c" which is imported
** with modifications to the local project as "Xlocal.c".  Suppose further
369
370
371
372
373
374
375
376

377
378
379
380
381
382
383
371
372
373
374
375
376
377

378
379
380
381
382
383
384
385







-
+







**
*/
void delta_3waymerge_cmd(void){
  Blob pivot, v1, v2, merged;
  int nConflict;

  /* We should be done with options.. */
  verify_all_options();
  verify_all_options2();

  if( g.argc!=6 ){
    usage("PIVOT V1 V2 MERGED");
  }
  if( blob_read_from_file(&pivot, g.argv[2], ExtFILE)<0 ){
    fossil_fatal("cannot read %s", g.argv[2]);
  }
Changes to src/name.c.
788
789
790
791
792
793
794
795

796
797
798
799
800
801
802
803
804
805


806
807
808
809
810
811
812
813
814
815
816
817
818

819
820
821
822
823
824
825
788
789
790
791
792
793
794

795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819

820
821
822
823
824
825
826
827







-
+










+
+












-
+







  }
  db_finalize(&q);
}

/*
** COMMAND: whatis*
**
** Usage: %fossil whatis NAME
** Usage: %fossil whatis ?--? NAME
**
** Resolve the symbol NAME into its canonical artifact hash
** artifact name and provide a description of what role that artifact
** plays.
**
** Options:
**
**    --type TYPE          Only find artifacts of TYPE (one of: 'ci', 't',
**                         'w', 'g', or 'e').
**    -v|--verbose         Provide extra information (such as the RID)
**    --                   Treat all following arguments as non-flags, even if
**                         they look like flags.
*/
void whatis_cmd(void){
  int rid;
  const char *zName;
  int verboseFlag;
  int i;
  const char *zType = 0;
  db_find_and_open_repository(0,0);
  verboseFlag = find_option("verbose","v",0)!=0;
  zType = find_option("type",0,1);

  /* We should be done with options.. */
  verify_all_options();
  verify_all_options2();

  if( g.argc<3 ) usage("NAME ...");
  for(i=2; i<g.argc; i++){
    zName = g.argv[i];
    if( i>2 ) fossil_print("%.79c\n",'-');
    rid = symbolic_name_to_rid(zName, zType);
    if( rid<0 ){
Changes to src/regexp.c.
785
786
787
788
789
790
791
792

793
794
795
796
797
798
799
800
801
802



803
804
805
806
807
808
809
810
811
812
813
814
815
816

817
818
819
820
821
822
823
785
786
787
788
789
790
791

792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818

819
820
821
822
823
824
825
826







-
+










+
+
+













-
+







  }
  re_free(pRe);
}

/*
** COMMAND: grep
**
** Usage: %fossil grep [OPTIONS] PATTERN FILENAME
** Usage: %fossil grep [OPTIONS] ?--? PATTERN FILENAME
**
** Attempt to match the given POSIX extended regular expression PATTERN
** over all historic versions of FILENAME.  For details of the supported
** RE dialect, see https://fossil-scm.org/fossil/doc/trunk/www/grep.md
**
** Options:
**
**     -i|--ignore-case         Ignore case
**     -l|--files-with-matches  List only checkin ID for versions that match
**     -v|--verbose             Show each file as it is analyzed
**     --                       Treat all following arguments as non-flags,
**                              even if they look like flags. Use this before
**                              the PATTERN or FILENAME, but not both.
*/
void re_grep_cmd(void){
  u32 flags = 0;
  int bVerbose = 0;
  ReCompiled *pRe;
  const char *zErr;
  int ignoreCase = 0;
  Blob fullName;

  if( find_option("ignore-case","i",0)!=0 ) ignoreCase = 1;
  if( find_option("files-with-matches","l",0)!=0 ) flags |= GREP_EXISTS;
  if( find_option("verbose","v",0)!=0 ) bVerbose = 1;
  db_find_and_open_repository(0, 0);
  verify_all_options();
  verify_all_options2();
  if( g.argc<4 ){
    usage("REGEXP FILENAME");
  }
  zErr = re_compile(&pRe, g.argv[2], ignoreCase);
  if( zErr ) fossil_fatal("%s", zErr);

  if( file_tree_name(g.argv[3], &fullName, 0, 0) ){
Changes to src/stash.c.
257
258
259
260
261
262
263
264

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

264
265
266
267
268
269
270
271







-
+







*/
static int stash_create(void){
  const char *zComment;              /* Comment to add to the stash */
  int stashid;                       /* ID of the new stash */
  int vid;                           /* Current checkout */

  zComment = find_option("comment", "m", 1);
  verify_all_options();
  verify_all_options2();
  if( zComment==0 ){
    Blob prompt;                       /* Prompt for stash comment */
    Blob comment;                      /* User comment reply */
#if defined(_WIN32) || defined(__CYGWIN__)
    int bomSize;
    const unsigned char *bom = get_utf8_bom(&bomSize);
    blob_init(&prompt, (const char *) bom, bomSize);
509
510
511
512
513
514
515
516
517


518
519
520
521
522
523
524
509
510
511
512
513
514
515


516
517
518
519
520
521
522
523
524







-
-
+
+








/*
** COMMAND: stash
**
** Usage: %fossil stash SUBCOMMAND ARGS...
**
**  fossil stash
**  fossil stash save ?-m|--comment COMMENT? ?FILES...?
**  fossil stash snapshot ?-m|--comment COMMENT? ?FILES...?
**  fossil stash save ?-m|--comment COMMENT? ?--? ?FILES...?
**  fossil stash snapshot ?-m|--comment 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 checkout unchanged.
560
561
562
563
564
565
566
567
568


569
570
571
572
573
574
575
576





577
578
579
580
581
582
583
560
561
562
563
564
565
566


567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588







-
-
+
+








+
+
+
+
+







**
**     Show diffs of the current working directory and what that
**     directory would be if STASHID were applied. With gdiff,
**     gdiff-command is used instead of internal diff logic.
**
** SUMMARY:
**  fossil stash
**  fossil stash save ?-m|--comment COMMENT? ?FILES...?
**  fossil stash snapshot ?-m|--comment COMMENT? ?FILES...?
**  fossil stash save ?-m|--comment COMMENT? ?--? ?FILES...?
**  fossil stash snapshot ?-m|--comment COMMENT? ?--? ?FILES...?
**  fossil stash list|ls ?-v|--verbose? ?-W|--width <num>?
**  fossil stash show|cat ?STASHID? ?DIFF-OPTIONS?
**  fossil stash gshow|gcat ?STASHID? ?DIFF-OPTIONS?
**  fossil stash pop
**  fossil stash apply|goto ?STASHID?
**  fossil stash drop|rm ?STASHID? ?-a|--all?
**  fossil stash diff ?STASHID? ?DIFF-OPTIONS?
**  fossil stash gdiff ?STASHID? ?DIFF-OPTIONS?
**
**  Options:
**  --                 For commands which support it, treat all following
**                     arguments as non-flags, even if they look like flags.
**
*/
void stash_cmd(void){
  const char *zCmd;
  int nCmd;
  int stashid = 0;
  undo_capture_command_line();
  db_must_be_within_tree();
Changes to src/tar.c.
580
581
582
583
584
585
586
587

588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604



605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622

623
624
625
626
627
628
629
580
581
582
583
584
585
586

587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624

625
626
627
628
629
630
631
632







-
+

















+
+
+

















-
+







  blob_reset(&filename);
  tar_finish(pTar);
}

/*
** COMMAND: tarball*
**
** Usage: %fossil tarball VERSION OUTPUTFILE [OPTIONS]
** Usage: %fossil tarball ?OPTIONS? VERSION ?--? OUTPUTFILE
**
** 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
** name is derived from the project name, the check-in date and time, and
** the artifact ID of the check-in.
**
** The GLOBLIST argument to --exclude and --include can be a comma-separated
** list of glob patterns, where each glob pattern may optionally be enclosed
** in "..." or '...' so that it may contain commas.  If a file matches both
** --include and --exclude then it is excluded.
**
** Options:
**   -X|--exclude GLOBLIST   Comma-separated list of GLOBs of files to exclude
**   --include GLOBLIST      Comma-separated list of GLOBs of files to include
**   --name DIRECTORYNAME    The name of the top-level directory in the archive
**   -R REPOSITORY           Specify a Fossil repository
**   --                      Treat all following arguments as non-flags, even if
**                           they look like flags. Use before the VERSION or
**                           OUTPUTFILE, but not both.
*/
void tarball_cmd(void){
  int rid;
  Blob tarball;
  const char *zName;
  Glob *pInclude = 0;
  Glob *pExclude = 0;
  const char *zInclude;
  const char *zExclude;
  zName = find_option("name", 0, 1);
  zExclude = find_option("exclude", "X", 1);
  if( zExclude ) pExclude = glob_create(zExclude);
  zInclude = find_option("include", 0, 1);
  if( zInclude ) pInclude = glob_create(zInclude);
  db_find_and_open_repository(0, 0);

  /* We should be done with options.. */
  verify_all_options();
  verify_all_options2();

  if( g.argc!=4 ){
    usage("VERSION OUTPUTFILE");
  }
  g.zOpenRevision = g.argv[2];
  rid = name_to_typed_rid(g.argv[2], "ci");
  if( rid==0 ){
Changes to src/undo.c.
418
419
420
421
422
423
424
425
426


427
428
429
430
431
432
433
418
419
420
421
422
423
424


425
426
427
428
429
430
431
432
433







-
-
+
+







  undo_all_filesystem(0);
}

/*
** COMMAND: undo
** COMMAND: redo*
**
** Usage: %fossil undo ?OPTIONS? ?FILENAME...?
**    or: %fossil redo ?OPTIONS? ?FILENAME...?
** Usage: %fossil undo ?OPTIONS? ?--? ?FILENAME...?
**    or: %fossil redo ?OPTIONS? ?--? ?FILENAME...?
**
** Undo the changes to the working checkout caused by the most recent
** of the following operations:
**
**    (1) fossil update             (5) fossil stash apply
**    (2) fossil merge              (6) fossil stash drop
**    (3) fossil revert             (7) fossil stash goto
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
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







+
+













-
+







** have done had the -n|--dry-run been omitted.
**
** A single level of undo/redo is supported.  The undo/redo stack
** is cleared by the commit and checkout commands.
**
** Options:
**   -n|--dry-run   do not make changes but show what would be done
**   --             Treat all following arguments as non-flags, even if
**                  they look like flags.
**
** See also: commit, status
*/
void undo_cmd(void){
  int isRedo = g.argv[1][0]=='r';
  int undo_available;
  int dryRunFlag = find_option("dry-run", "n", 0)!=0;
  const char *zCmd = isRedo ? "redo" : "undo";

  if( !dryRunFlag ){
    dryRunFlag = find_option("explain", 0, 0)!=0;
  }
  db_must_be_within_tree();
  verify_all_options();
  verify_all_options2();
  db_begin_transaction();
  undo_available = db_lget_int("undo_available", 0);
  if( dryRunFlag ){
    if( undo_available==0 ){
      fossil_print("No undo or redo is available\n");
    }else{
      Stmt q;
Changes to src/unversioned.c.
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
276
277
278
279
280
281
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
327
328
329
330
331
332
333
334
335
336
337
338
339
340


341
342
343
344
345
346
347
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
276
277
278
279
280
281
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
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







-
+




-
+
+
+






-
+

-
+

+
-
+












-
+













-
+





+
+
+




















+


-

-
-
+
+

















+
-
+






-
+
















-
-
+
+







** Unversioned files (UV-files) are artifacts that are synced and are available
** for download but which do not preserve history.  Only the most recent version
** of each UV-file is retained.  Changes to an UV-file are permanent and cannot
** be undone, so use appropriate caution with this command.
**
** Subcommands:
**
**    add FILE ...           Add or update one or more unversioned files in
**    add ?--? FILE ...      Add or update one or more unversioned files in
**                           the local repository so that they match FILEs
**                           on disk. Changes are not pushed to other
**                           repositories until the next sync.
**
**    add FILE --as UVFILE   Add or update a single file named FILE on disk
**    add FILE --as UVFILE
**    add --as UVFILE -- FILE
**                           Add or update a single file named FILE on disk
**                           and UVFILE in the repository unversioned file
**                           namespace. This variant of the 'add' command allows
**                           the name to be different in the repository versus
**                           what appears on disk, but it only allows adding
**                           a single file at a time.
**
**    cat FILE ...           Concatenate the content of FILEs to stdout.
**    cat ?--? FILE ...      Concatenate the content of FILEs to stdout.
**
**    edit FILE              Bring up FILE in a text editor for modification.
**    edit ?--? FILE         Bring up FILE in a text editor for modification.
**
**    export ?--? FILE OUTPUT
**    export FILE OUTPUT     Write the content of FILE into OUTPUT on disk
**                           Write the content of FILE into OUTPUT on disk
**
**    list | ls              Show all unversioned files held in the local
**                           repository.
**
**    revert ?URL?           Restore the state of all unversioned files in the
**                           local repository to match the remote repository
**                           URL.
**
**                           Options:
**                              -v|--verbose     Extra diagnostic output
**                              -n|--dryrun      Show what would have happened
**
**    remove|rm|delete FILE ...
**    remove|rm|delete ?--? FILE ...
**                           Remove unversioned files from the local repository.
**                           Changes are not pushed to other repositories until
**                           the next sync.
**
**    sync ?URL?             Synchronize the state of all unversioned files with
**                           the remote repository URL.  The most recent version
**                           of each file is propagated to all repositories and
**                           all prior versions are permanently forgotten.
**
**                           Options:
**                              -v|--verbose     Extra diagnostic output
**                              -n|--dryrun      Show what would have happened
**
**    touch FILE ...         Update the TIMESTAMP on all of the listed files
**    touch ?--? FILE ...    Update the TIMESTAMP on all of the listed files
**
** Options:
**
**   --mtime TIMESTAMP       Use TIMESTAMP instead of "now" for the "add",
**                           "edit", "remove", and "touch" subcommands.
**   --                      For commands which support this, it means to treat
**                           all subsequent arguments as file names even if they
**                           start with a "-".
*/
void unversioned_cmd(void){
  const char *zCmd;
  int nCmd;
  const char *zMtime = find_option("mtime", 0, 1);
  sqlite3_int64 mtime;
  db_find_and_open_repository(0, 0);
  unversioned_schema();
  zCmd = g.argc>=3 ? g.argv[2] : "x";
  nCmd = (int)strlen(zCmd);
  if( zMtime==0 ){
    mtime = time(0);
  }else{
    mtime = db_int(0, "SELECT strftime('%%s',%Q)", zMtime);
    if( mtime<=0 ) fossil_fatal("bad timestamp: %Q", zMtime);
  }
  if( memcmp(zCmd, "add", nCmd)==0 ){
    const char *zError = 0;
    const char *zIn;
    const char *zAs;
    const char *zFileArg;
    Blob file;
    int i;

    zAs = find_option("as",0,1);
    if( zAs && g.argc!=4 ) usage("add DISKFILE --as UVFILE");
    verify_all_options();
    verify_all_options2();
    if( zAs && g.argc!=4 ) usage("add --as UVFILE ?--? DISKFILE");
    db_begin_transaction();
    content_rcvid_init("#!fossil unversioned add");
    for(i=3; i<g.argc; i++){
      zIn = zAs ? zAs : g.argv[i];
      if( zIn[0]==0 ){
        zError = "be empty string";
      }else if( zIn[0]=='/' ){
        zError = "be absolute";
      }else if ( !file_is_simple_pathname(zIn,1) ){
        zError = "contain complex paths";
      }else if( contains_whitespace(zIn) ){
        zError = "contain whitespace";
      }
      if( zError ){
        fossil_fatal("unversioned filenames may not %s: %Q", zError, zIn);
      }
      blob_init(&file,0,0);
      zFileArg = get_dash_filename_arg(i);
      blob_read_from_file(&file, g.argv[i], ExtFILE);
      blob_read_from_file(&file, zFileArg, ExtFILE);
      unversioned_write(zIn, &file, mtime);
      blob_reset(&file);
    }
    db_end_transaction(0);
  }else if( memcmp(zCmd, "cat", nCmd)==0 ){
    int i;
    verify_all_options();
    verify_all_options2();
    db_begin_transaction();
    for(i=3; i<g.argc; i++){
      Blob content;
      if( unversioned_content(g.argv[i], &content)==0 ){
        blob_write_to_file(&content, "-");
      }
      blob_reset(&content);
    }
    db_end_transaction(0);
  }else if( memcmp(zCmd, "edit", nCmd)==0 ){
    const char *zEditor;    /* Name of the text-editor command */
    const char *zTFile;     /* Temporary file */
    const char *zUVFile;    /* Name of the unversioned file */
    char *zCmd;             /* Command to run the text editor */
    Blob content;           /* Content of the unversioned file */

    verify_all_options();
    if( g.argc!=4) usage("edit UVFILE");
    verify_all_options2();
    if( g.argc!=4) usage("edit ?--? UVFILE");
    zUVFile = g.argv[3];
    zEditor = fossil_text_editor();
    if( zEditor==0 ) fossil_fatal("no text editor - set the VISUAL env variable");
    zTFile = fossil_temp_filename();
    if( zTFile==0 ) fossil_fatal("cannot find a temporary filename");
    db_begin_transaction();
    content_rcvid_init("#!fossil unversioned edit");
368
369
370
371
372
373
374

375
376


377
378
379












380

381
382
383
384
385
386
387
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







+
-
-
+
+



+
+
+
+
+
+
+
+
+
+
+
+
-
+







    file_delete(zTFile);
    if( zMtime==0 ) mtime = time(0);
    unversioned_write(zUVFile, &content, mtime);
    db_end_transaction(0);
    blob_reset(&content);
  }else if( memcmp(zCmd, "export", nCmd)==0 ){
    Blob content;
    const char * zOutfile;
    verify_all_options();
    if( g.argc!=5 ) usage("export UVFILE OUTPUT");
    verify_all_options2();
    if( g.argc!=5 ) usage("export ?--? UVFILE OUTPUT");
    if( unversioned_content(g.argv[3], &content) ){
      fossil_fatal("no such uv-file: %Q", g.argv[3]);
    }
    /*
    ** Pathological(?) corner case:
    **
    **   export -- --UVFILE -
    **
    ** We have no way of applying -- to just the UVFILE name but not
    ** the output file name, so the above would output the uv file
    ** literally named --UVFILE to a file literally named -. The only
    ** alternative is that we never apply -- to the output file name,
    ** which seems likely to cause yet more confusion.
    */
    zOutfile = get_dash_filename_arg(4);
    blob_write_to_file(&content, g.argv[4]);
    blob_write_to_file(&content, zOutfile);
    blob_reset(&content);
  }else if( memcmp(zCmd, "hash", nCmd)==0 ){  /* undocumented */
    /* Show the hash value used during uv sync */
    int debugFlag = find_option("debug",0,0)!=0;
    fossil_print("%s\n", unversioned_content_hash(debugFlag));
  }else if( memcmp(zCmd, "list", nCmd)==0 || memcmp(zCmd, "ls", nCmd)==0 ){
    Stmt q;
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
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







-
+

















-
+







    unsigned syncFlags = unversioned_sync_flags(SYNC_UNVERSIONED|SYNC_UV_REVERT);
    g.argv[1] = "sync";
    g.argv[2] = "--uv-noop";
    sync_unversioned(syncFlags);
  }else if( memcmp(zCmd, "remove", nCmd)==0 || memcmp(zCmd, "rm", nCmd)==0
         || memcmp(zCmd, "delete", nCmd)==0 ){
    int i;
    verify_all_options();
    verify_all_options2();
    db_begin_transaction();
    for(i=3; i<g.argc; i++){
      db_multi_exec(
        "UPDATE unversioned"
        "   SET hash=NULL, content=NULL, mtime=%lld, sz=0 WHERE name=%Q",
        mtime, g.argv[i]
      );
    }
    db_unset("uv-hash", 0);
    db_end_transaction(0);
  }else if( memcmp(zCmd,"sync",nCmd)==0 ){
    unsigned syncFlags = unversioned_sync_flags(SYNC_UNVERSIONED);
    g.argv[1] = "sync";
    g.argv[2] = "--uv-noop";
    sync_unversioned(syncFlags);
  }else if( memcmp(zCmd, "touch", nCmd)==0 ){
    int i;
    verify_all_options();
    verify_all_options2();
    db_begin_transaction();
    for(i=3; i<g.argc; i++){
      db_multi_exec(
        "UPDATE unversioned SET mtime=%lld WHERE name=%Q",
        mtime, g.argv[i]
      );
    }
Changes to src/update.c.
58
59
60
61
62
63
64
65

66
67
68
69
70
71
72
58
59
60
61
62
63
64

65
66
67
68
69
70
71
72







-
+







  g.argv = savedArgv;
  return internalConflictCnt;
}

/*
** COMMAND: update
**
** Usage: %fossil update ?OPTIONS? ?VERSION? ?FILES...?
** Usage: %fossil update ?OPTIONS? ?--? ?VERSION? ?FILES...?
**
** Change the version of the current checkout to VERSION.  Any
** uncommitted changes are retained and applied to the new checkout.
**
** The VERSION argument can be a specific version or tag or branch
** name.  If the VERSION argument is omitted, then the leaf of the
** subtree that begins at the current version is used, if there is
100
101
102
103
104
105
106



107
108
109
110
111
112
113
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116







+
+
+







**   -n|--dry-run     If given, display instead of run actions
**   -v|--verbose     print status information about all files
**   -W|--width <num> Width of lines (default is to auto-detect). Must be >20
**                    or 0 (= no limit, resulting in a single line per entry).
**   --setmtime       Set timestamps of all files to match their SCM-side
**                    times (the timestamp of the last checkin which modified
**                    them).
**   --               Treat all following arguments as non-flags, even if
**                    they look like flags. Use before the VERSION or
**                    FILES..., but not both.
**
** See also: revert
*/
void update_cmd(void){
  int vid;              /* Current version */
  int tid=0;            /* Target version - version we are changing to */
  Stmt q;
147
148
149
150
151
152
153
154

155
156
157
158
159
160
161
150
151
152
153
154
155
156

157
158
159
160
161
162
163
164







-
+







  }
  verboseFlag = find_option("verbose","v",0)!=0;
  forceMissingFlag = find_option("force-missing",0,0)!=0;
  debugFlag = find_option("debug",0,0)!=0;
  setmtimeFlag = find_option("setmtime",0,0)!=0;

  /* We should be done with options.. */
  verify_all_options();
  verify_all_options2();

  db_must_be_within_tree();
  vid = db_lget_int("checkout", 0);
  user_select();
  if( !dryRunFlag && !internalUpdate ){
    if( autosync_loop(SYNC_PULL + SYNC_VERBOSE*verboseFlag,
                      db_get_int("autosync-tries", 1), 1) ){
755
756
757
758
759
760
761
762

763
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
792
793
794

795
796
797
798
799
800
801
758
759
760
761
762
763
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
792
793
794
795
796
797
798

799
800
801
802
803
804
805
806







-
+















+
+
















-
+







  /* Return 1 on success and (assuming fatal is not set) 0 if not found. */
  return result;
}

/*
** COMMAND: revert
**
** Usage: %fossil revert ?-r REVISION? ?FILE ...?
** Usage: %fossil revert ?-r REVISION? ?--? ?FILE ...?
**
** Revert to the current repository version of FILE, or to
** the version associated with baseline REVISION if the -r flag
** appears.
**
** If FILE was part of a rename operation, both the original file
** and the renamed file are reverted.
**
** Revert all files if no file name is provided.
**
** If a file is reverted accidentally, it can be restored using
** the "fossil undo" command.
**
** Options:
**   -r REVISION    revert given FILE(s) back to given REVISION
**   --             Treat all following arguments as files, even
**                  if they look like flags.
**
** See also: redo, undo, update
*/
void revert_cmd(void){
  Manifest *pCoManifest;          /* Manifest of current checkout */
  Manifest *pRvManifest;          /* Manifest of selected revert version */
  ManifestFile *pCoFile;          /* File within current checkout manifest */
  ManifestFile *pRvFile;          /* File within revert version manifest */
  const char *zFile;              /* Filename relative to checkout root */
  const char *zRevision;          /* Selected revert version, NULL if current */
  Blob record = BLOB_INITIALIZER; /* Contents of each reverted file */
  int i;
  Stmt q;

  undo_capture_command_line();
  zRevision = find_option("revision", "r", 1);
  verify_all_options();
  verify_all_options2();

  if( g.argc<2 ){
    usage("?OPTIONS? [FILE] ...");
  }
  if( zRevision && g.argc<3 ){
    fossil_fatal("the --revision option does not work for the entire tree");
  }
Changes to src/wiki.c.
1362
1363
1364
1365
1366
1367
1368
1369
1370


1371
1372
1373
1374
1375
1376
1377
1362
1363
1364
1365
1366
1367
1368


1369
1370
1371
1372
1373
1374
1375
1376
1377







-
-
+
+







/*
** COMMAND: wiki*
**
** Usage: %fossil wiki (export|create|commit|list) WikiName
**
** Run various subcommands to work with wiki entries or tech notes.
**
**    %fossil wiki export PAGENAME ?FILE?
**    %fossil wiki export ?FILE? -t|--technote DATETIME|TECHNOTE-ID
**    %fossil wiki export PAGENAME ?--? ?FILE?
**    %fossil wiki export -t|--technote DATETIME|TECHNOTE-ID ?--? ?FILE?
**
**       Sends the latest version of either a wiki page or of a tech note
**       to the given file or standard output.
**       If PAGENAME is provided, the wiki page will be output. For
**       a tech note either DATETIME or TECHNOTE-ID must be specified. If
**       DATETIME is used, the most recently modified tech note with that
**       DATETIME will be sent.
1423
1424
1425
1426
1427
1428
1429





1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452

1453
1454
1455

1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469

1470
1471
1472

1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484

1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503

1504
1505

1506
1507

1508
1509
1510
1511
1512

1513

1514
1515
1516
1517
1518
1519
1520
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445

1446
1447
1448
1449
1450
1451
1452
1453
1454

1455
1456
1457
1458

1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472

1473
1474
1475

1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487

1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509

1510
1511

1512
1513
1514
1515
1516
1517
1518

1519
1520
1521
1522
1523
1524
1525
1526







+
+
+
+
+











-









-

+


-
+













-
+


-
+











-
+



















+

-
+

-
+





+
-
+







**
** DATETIME may be "now" or "YYYY-MM-DDTHH:MM:SS.SSS". If in
** year-month-day form, it may be truncated, the "T" may be replaced by
** a space, and it may also name a timezone offset from UTC as "-HH:MM"
** (westward) or "+HH:MM" (eastward). Either no timezone suffix or "Z"
** means UTC.
**
** Options:
**   --                      For commands which support this, it means to treat
**                           all subsequent arguments as file names even if they
**                           start with a "-".
**
*/
void wiki_cmd(void){
  int n;
  db_find_and_open_repository(0, 0);
  if( g.argc<3 ){
    goto wiki_cmd_usage;
  }
  n = strlen(g.argv[2]);
  if( n==0 ){
    goto wiki_cmd_usage;
  }

  if( strncmp(g.argv[2],"export",n)==0 ){
    const char *zPageName;        /* Name of the wiki page to export */
    const char *zFile;            /* Name of the output file (0=stdout) */
    const char *zETime;           /* The name of the technote to export */
    int rid;                      /* Artifact ID of the wiki page */
    int i;                        /* Loop counter */
    char *zBody = 0;              /* Wiki page content */
    Blob body;                    /* Wiki page content */
    Manifest *pWiki = 0;          /* Parsed wiki page content */

    zETime = find_option("technote","t",1);
    verify_all_options2();
    if( !zETime ){
      if( (g.argc!=4) && (g.argc!=5) ){
        usage("export PAGENAME ?FILE?");
        usage("export PAGENAME ?--? ?FILE?");
      }
      zPageName = g.argv[3];
      rid = db_int(0, "SELECT x.rid FROM tag t, tagxref x"
        " WHERE x.tagid=t.tagid AND t.tagname='wiki-%q'"
        " ORDER BY x.mtime DESC LIMIT 1",
        zPageName
      );
      if( (pWiki = manifest_get(rid, CFTYPE_WIKI, 0))!=0 ){
        zBody = pWiki->zWiki;
      }
      if( zBody==0 ){
        fossil_fatal("wiki page [%s] not found",zPageName);
      }
      zFile = (g.argc==4) ? "-" : g.argv[4];
      zFile = g.argc==4 ? "-" : get_dash_filename_arg(4);
    }else{
      if( (g.argc!=3) && (g.argc!=4) ){
        usage("export ?FILE? --technote DATETIME|TECHNOTE-ID");
        usage("export --technote DATETIME|TECHNOTE-ID ?--? ?FILE?");
      }
      rid = wiki_technote_to_rid(zETime);
      if ( rid==-1 ){
        fossil_fatal("ambiguous tech note id: %s", zETime);
      }
      if( (pWiki = manifest_get(rid, CFTYPE_EVENT, 0))!=0 ){
        zBody = pWiki->zWiki;
      }
      if( zBody==0 ){
        fossil_fatal("technote [%s] not found",zETime);
      }
      zFile = (g.argc==3) ? "-" : g.argv[3];
      zFile = g.argc==3 ? "-" : get_dash_filename_arg(3);
    }
    for(i=strlen(zBody); i>0 && fossil_isspace(zBody[i-1]); i--){}
    zBody[i] = 0;
    blob_init(&body, zBody, -1);
    blob_append(&body, "\n", 1);
    blob_write_to_file(&body, zFile);
    blob_reset(&body);
    manifest_destroy(pWiki);
    return;
  }else if( strncmp(g.argv[2],"commit",n)==0
            || strncmp(g.argv[2],"create",n)==0 ){
    const char *zPageName;        /* page name */
    Blob content;                 /* Input content */
    int rid = 0;
    Manifest *pWiki = 0;          /* Parsed wiki page content */
    const char *zMimeType = find_option("mimetype", "M", 1);
    const char *zETime = find_option("technote", "t", 1);
    const char *zTags = find_option("technote-tags", NULL, 1);
    const char *zClr = find_option("technote-bgcolor", NULL, 1);
    verify_all_options2();
    if( g.argc!=4 && g.argc!=5 ){
      usage("commit|create PAGENAME ?FILE? [--mimetype TEXT-FORMAT]"
      usage("commit|create PAGENAME [--mimetype TEXT-FORMAT]"
            " [--technote DATETIME] [--technote-tags TAGS]"
            " [--technote-bgcolor COLOR]");
            " [--technote-bgcolor COLOR] ?--? ?FILE?");
    }
    zPageName = g.argv[3];
    if( g.argc==4 ){
      blob_read_from_channel(&content, stdin, -1);
    }else{
      const char * zFilename = get_dash_filename_arg(4);
      blob_read_from_file(&content, g.argv[4], ExtFILE);
      blob_read_from_file(&content, zFilename, ExtFILE);
    }
    if( !zMimeType || !*zMimeType ){
      /* Try to deduce the mime type based on the prior version. */
      if ( !zETime ){
        rid = db_int(0, "SELECT x.rid FROM tag t, tagxref x"
                     " WHERE x.tagid=t.tagid AND t.tagname='wiki-%q'"
                     " ORDER BY x.mtime DESC LIMIT 1",
Changes to src/zip.c.
745
746
747
748
749
750
751
752

753
754
755
756
757
758
759
745
746
747
748
749
750
751

752
753
754
755
756
757
758
759







-
+







  zExclude = find_option("exclude", "X", 1);
  if( zExclude ) pExclude = glob_create(zExclude);
  zInclude = find_option("include", 0, 1);
  if( zInclude ) pInclude = glob_create(zInclude);
  db_find_and_open_repository(0, 0);

  /* We should be done with options.. */
  verify_all_options();
  verify_all_options2();

  if( g.argc!=4 ){
    usage("VERSION OUTPUTFILE");
  }
  g.zOpenRevision = g.argv[2];
  rid = name_to_typed_rid(g.argv[2], "ci");
  if( rid==0 ){
778
779
780
781
782
783
784
785

786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802



803
804
805
806
807
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
778
779
780
781
782
783
784

785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
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







-
+

















+
+
+








-
+

















+
+
+







  blob_write_to_file(&zip, g.argv[3]);
  blob_reset(&zip);
}

/*
** COMMAND: zip*
**
** Usage: %fossil zip VERSION OUTPUTFILE [OPTIONS]
** Usage: %fossil zip ?OPTIONS? VERSION ?--? OUTPUTFILE
**
** Generate a ZIP archive for a check-in.  If the --name option is
** used, its argument becomes the name of the top-level directory in the
** resulting ZIP archive.  If --name is omitted, the top-level directory
** name is derived from the project name, the check-in date and time, and
** the artifact ID of the check-in.
**
** The GLOBLIST argument to --exclude and --include can be a comma-separated
** list of glob patterns, where each glob pattern may optionally be enclosed
** in "..." or '...' so that it may contain commas.  If a file matches both
** --include and --exclude then it is excluded.
**
** Options:
**   -X|--exclude GLOBLIST   Comma-separated list of GLOBs of files to exclude
**   --include GLOBLIST      Comma-separated list of GLOBs of files to include
**   --name DIRECTORYNAME    The name of the top-level directory in the archive
**   -R REPOSITORY           Specify a Fossil repository
**   --                      Treat all following arguments as non-flags, even if
**                           they look like flags. Use before the VERSION or
**                           OUTPUTFILE, but not both.
*/
void zip_cmd(void){
  archive_cmd(ARCHIVE_ZIP);
}

/*
** COMMAND: sqlar*
**
** Usage: %fossil sqlar VERSION OUTPUTFILE [OPTIONS]
** Usage: %fossil sqlar ?OPTIONS? VERSION ?--? OUTPUTFILE
**
** Generate an SQLAR archive for a check-in.  If the --name option is
** used, its argument becomes the name of the top-level directory in the
** resulting SQLAR archive.  If --name is omitted, the top-level directory
** name is derived from the project name, the check-in date and time, and
** the artifact ID of the check-in.
**
** The GLOBLIST argument to --exclude and --include can be a comma-separated
** list of glob patterns, where each glob pattern may optionally be enclosed
** in "..." or '...' so that it may contain commas.  If a file matches both
** --include and --exclude then it is excluded.
**
** Options:
**   -X|--exclude GLOBLIST   Comma-separated list of GLOBs of files to exclude
**   --include GLOBLIST      Comma-separated list of GLOBs of files to include
**   --name DIRECTORYNAME    The name of the top-level directory in the archive
**   -R REPOSITORY           Specify a Fossil repository
**   --                      Treat all following arguments as non-flags, even if
**                           they look like flags. Use before the VERSION or
**                           OUTPUTFILE, but not both.
*/
void sqlar_cmd(void){
  archive_cmd(ARCHIVE_SQLAR);
}

/*
** WEBPAGE: sqlar