Fossil

Artifact [9904cbb81d]
Login

Artifact 9904cbb81d6a2999b59e5d9ec8df9935998fb5f64a7b5c865457e02ea6694f15:

Wiki page [branch/double-dash-flag] by stephan 2019-09-28 12:46:31.
D 2019-09-28T12:46:31.915
L branch/double-dash-flag
N text/x-markdown
P b5450b8c3d9f6e52acdbd4ba768de7fb886093a9897fe7a334977852921bd066
U stephan
W 4979
# Management Summary

The `double-dash-flag` branch aims to add support for the conventional interpretation of a `--` flag: all arguments after the first instance of `--` are to be treated as non-flag arguments (e.g. file/wiki/branch/whatever names).

This feature request is from: <https://fossil-scm.org/forum/forumpost/64acc6b653>

The implementation is not *100%* compliant with POSIX/Unix conventions because it cannot be without *Breaking Stuff*, but it "should" be close enough to be useful/conventional for the contexts where using `--` makes sense in Fossil. For example, `uv add` treats a filename of `-` as `stdin` by default (and has valid use cases enabled by that), and `--` could be used to make `uv add` treat `-` as a filename ([that's the original use case for which conventional `--` support was proposed](https://www.fossil-scm.org/forum/forumpost/d6fa7422db)).


# Compatibility vs. Historical Behaviour

Fossil's [historical handling of `--` is really weird](/artifact?ln=925-928&name=a35b33b329ab2038): the *first* time `find_option()` encounters `--`, it *removes* that flag and stops processing arguments. Subsequent calls to `find_option()` then never see `--` and thus treat all arguments as potential flags (even those after the prior position of `--`). Since that behaviour was never useful, and potentially confusing, it is unexpected that the changes made in this branch will break any historical usage of the CLI commands.

For example:

    fossil foo -- -a -b -c

The current (trunk, as of this writing) interpretation of `-a -b -c`, because of the "one-time-swallowing" of `--`, depends on what order those flags are checked for via `find_option()`. It seems highly unlikely that anyone could have reliably depended on that, and therefore seems unlikely that this change will break anyone's scripts.

Commands which accept a filename as the value of a flag are unaffected by these changes, provided the flag comes before `--`:

    fossil foo -R - -- -a -b -c

Would (both before and after this change) treat `-` as a repository file name, but this change will cause the subsequent `-a -b -c` flags to be interpreted as non-flags (it's then up to the `foo` command to deal with them). 

# This Implementation's Behaviour

1) `find_option()` and its variants always stop looking for flags when they encounter `--`.
2) `verify_all_options()` triggers a fatal error if `--` is found in the argument list.
3) `verify_all_options2()` consumes the first instance of `--` and records the `g.argv` index where `--` was found in `g.argDashDashIndex`, so that commands which need to can determine whether, e.g., an argument of `-` should be treated as an alias for `stdin`/`stdout` or as a literal filename (the latter only applies if `--` *precedes* the `-` argument). The utility function `get_dash_filename_arg()` makes that particular use case trivial to implement.

It seems, after having migrated many of the commands, that it would be harmless/risk-free, and probably desirable, to eliminate `verify_all_options2()` and have `verify_all_options()` adopt that function's behaviour. That would make a stray `--` flag at the end of a command a harmless no-op for commands which don't/can't make any special use of it, whereas it would "hide" flags (treating them as non-flags) if it's used before the end of such a command (indeed, that's its whole intention).

# List of commands/subcommands extended to support `--`

(Alphabetized by command/subcommand name.)

* `3-way-merge`
* `add`
* `annotate`
* `artifact`
* `branch new`: you might recall Johnny Cash's song *The Branch Named --Sue*.
* `cat`
* `changes`/`status`
* `clean`
* `clone`
* `commit`
* `diff`/`gdiff`
* `extras`
* `finfo`
* `grep`
* `ls`
* `mv`/`rename`
* `new`/`init`
* `open`
* `revert`
* `rm`/`delete`/`forget`
* `stash save | snapshot`
* `sqlar`
* `tarball`
* `uv add | cat | edit | export | rm` (noting that `export` has one pathological(?) corner case which we can't 100% accommodate: double-dashing the UVFILE name without applying double-dash to the output file name).
* `wiki commit | create | export`
* `zip`

# The Obligatory Exceptions

* `diff -tk` and `stash diff -tk`: `diff_tk()` does not use `verify_all_options()`, so it has historically silently ignored unknown flags. To avoid breaking existing user behaviour, it was not modified. Ideally it should be updated to call `verify_all_options2()`.
* `stash gdiff|show|gshow|cat|gcat` do not currently call `verify_all_options()`, but probably should. 
* `search` does not use `verify_all_options()`, instead treating all unconsumed flag arguments as a search pattern. It can easily be made to treat `--` as the other commands, but doing so may break existing expectations, so that command was left unmodified.
* `tag` does not use `verify_all_options()`, instead using strictly positional arguments, thus it supports tags with leading dashes as-is.
Z 6c8c7f7d3ed423d953e6cdcf6e55acf3