Check-in [78a30d8d7c]
Not logged in

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

Overview
Comment:Added -- support to: (branch new) (uv add/cat/edit/export/rm)
Timelines: family | ancestors | descendants | both | double-dash-flag
Files: files | file ages | folders
SHA3-256: 78a30d8d7c3d5e2e2591f9d29938ae64a7673a489fb7e6f3e6e9c4f977e62ef5
User & Date: stephan 2019-09-27 11:47:17.819
Context
2019-09-27
14:32
Added -- support to wiki create/commit/export. Refactored/simplified how fetching of a dash-as-stdin/stdout argument is done from command-side code. check-in: dba4fd9b69 user: stephan tags: double-dash-flag
11:47
Added -- support to: (branch new) (uv add/cat/edit/export/rm) check-in: 78a30d8d7c user: stephan tags: double-dash-flag
09:55
Simplified the verify_all_options() porting strategy, such that -- is disallowed by default and routines which should/can support it need to call verify_all_options2() instead of us changing the signature of verify_all_options(). This will result in far fewer changes than the previous approach. check-in: a9b9b5bcee user: stephan tags: double-dash-flag
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/branch.c.
47
48
49
50
51
52
53






54
55
56
57
58
59
60
  }
  return zBr;
}

/*
**  fossil branch new    NAME  BASIS ?OPTIONS?
**  argv0  argv1  argv2  argv3 argv4






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







>
>
>
>
>
>







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
  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();
  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; }








|







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_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
**        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?

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


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







>








>
>







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/main.c.
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
** 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.





**
** 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?
*/
static void verify_all_options_impl(int fAllowDoubleDash){
  int i;
  for(i=1; i<g.argc; i++){
    const char * arg = 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);
          break;
        }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);
      }
    }
  }

}

/*
** 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.
*/
void verify_all_options2(void){
  verify_all_options_impl(1);
}

/*
** This function returns a human readable version string.
*/
const char *get_version(){
  static const char version[] = RELEASE_VERSION " " MANIFEST_VERSION " "







>
>
>
>
>






|









|










>















|

|
|







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
** 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.
**
** 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?
*/
static int verify_all_options_impl(int fAllowDoubleDash){
  int i;
  for(i=1; i<g.argc; i++){
    const char * arg = 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 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);
}

/*
** This function returns a human readable version string.
*/
const char *get_version(){
  static const char version[] = RELEASE_VERSION " " MANIFEST_VERSION " "
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
** 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
**                           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


**                           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.
**
**    edit FILE              Bring up FILE in a text editor for modification.
**

**    export FILE OUTPUT     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 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
**
** Options:
**
**   --mtime TIMESTAMP       Use TIMESTAMP instead of "now" for the "add",
**                           "edit", "remove", and "touch" subcommands.



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

    Blob file;
    int i;

    zAs = find_option("as",0,1);

    if( zAs && g.argc!=4 ) usage("add DISKFILE --as UVFILE");
    verify_all_options();
    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);





      blob_read_from_file(&file, g.argv[i], 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();
    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");
    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");







|




|
>
>






|

|

>
|












|













|





>
>
>




















>


|

>

<

















>
>
>
>
>
|






|
















|
|







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
355
356
357
358
359
** 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
**                           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 --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.
**
**    edit [--] FILE         Bring up FILE in a text editor for modification.
**
**    export [--] FILE OUTPUT
**                           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 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
**
** 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;
    int fDoubleDash;         /* True if "--" flag is provided */
    zAs = find_option("as",0,1);
    fDoubleDash = verify_all_options2();
    if( zAs && g.argc!=4 ) usage("add DISKFILE --as UVFILE");

    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 = g.argv[i];
      if(fDoubleDash>0 && fDoubleDash<=i
         && fossil_strcmp("-",zFileArg)==0){
        zFileArg = "./-" /* do not treat "-" as stdin! */;
      }
      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_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_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
    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;
    verify_all_options();
    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]);
    }
    blob_write_to_file(&content, g.argv[4]);
    blob_reset(&content);
  }else if( memcmp(zCmd, "hash", nCmd)==0 ){  /* undocumented */







|







380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
    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;
    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]);
    }
    blob_write_to_file(&content, g.argv[4]);
    blob_reset(&content);
  }else if( memcmp(zCmd, "hash", nCmd)==0 ){  /* undocumented */
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
    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();
    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();
    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]
      );
    }







|

















|







440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
    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_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_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]
      );
    }