Still considering the much needed rewrite of the Platform Quirks section.

On 4/14/2017 9:15 PM, Warren Young wrote:
29. The Platform Quirks section needs a total rewrite.  Sorry, but it left me 
confused, and I know what’s going on.

How about this:

————————————————————

# Platform Quirks

Fossil glob patterns are based on the glob pattern feature of POSIX shells. 
Fossil glob patterns also have a quoting mechanism, discussed above. Because 
other parts of your operating system may interpret glob patterns and quotes 
separately from Fossil, it is often difficult to give glob patterns correctly 
to Fossil on the command line. Quotes and special characters in glob patterns 
are likely to interpreted when given as part of a `fossil` command, causing 
unexpected behavior.

These problems do not affect [versioned settings 
files](/doc/trunk/www/settings.wiki) or Admin → Settings in Fossil UI. 
Consequently, it is better to set long-term `*-glob` settings via these methods 
than to use `fossil settings` commands.

That advice doesn’t help you when you are giving one-off glob patterns in 
`fossil` commands. The remainder of this section gives remedies and workarounds 
for these problems.


## POSIX Systems

If you are using Fossil on a system with a POSIX-compatible shell — Linux, 
macOS, the BSDs, Unix, Cygwin, WSL etc. — the shell may expand the glob 
patterns before passing the result to the `fossil` executable.

Sometimes this is exactly what you want.  Consider this command for example:

     $ fossil add RE*

If you give that command in a directory containing `README.txt` and 
`RELEASE-NOTES.txt`, the shell will expand the command to:

     $ fossil add README.txt RELEASE-NOTES.txt

…which is compatible with the `fossil add` command’s argument list, which 
allows multiple files. Fossil doesn’t see the glob pattern at all, but since 
the command does what you almost certainly wanted anyway, it’s fine.

If it did see the glob pattern in "fossil add RE*" it would actually try to add a file named exactly "RE*" which is likely not at all what you want! The file name arguments to fossil add (and the command like it) are not globs, they are simply names relative to the current directory.

Now consider what happens instead if you say:

     $ fossil add --ignore RE* src/*.c

This*doesn’t*  do what you want because the shell will expand both `RE*` and 
`src/*.c`, causing one of the two files matching the `RE*` glob pattern to be 
ignored and the other to be added to the repository. You need to say this in 
that case:

     $ fossil add --ignore 'RE*' src/*.c

The single quotes force a POSIX shell to pass the `RE*` glob pattern through to 
Fossil untouched, which will do its own glob pattern matching. There are other 
methods of quoting a glob pattern or escaping its special characters; see your 
shell’s manual.

POSIX shells also interpret the same quotation marks Fossil uses to handle 
things like spaces in file names, as discussed above. For example, if you 
needed to add all files matching `RE*` to the repository except for a file 
called `REALLY SECRET STUFF.txt`, you could use nested quotes:

     $ fossil add --ignore "'REALLY SECRET STUFF.txt'" RE*

The --ignore will not override a file name on the command line, but it will cause a prompt asking what to do with the file. The very dangerous -f or --force option will answer YES to that prompt for you, in this case committing your secrets.

Bottom line there is don't put any secrets in a folder where fossil (or any VCS) can touch it because an accident will happen and if that secret is your Amazon AWS password, it can cost you an immense amount of money in a surprisingly short amount of time!

You could instead escape a second set of double quotation marks:

     $ fossil add --ignore "\"REALLY SECRET STUFF.txt\"" RE*

It bears repeating that the two glob patterns here are not interpreted the same 
way when running this command from a*subdirectory*  of the top checkout 
directory as when running it at the top of the checkout tree. If these files 
were in a subdirectory of the checkout tree called `doc` and that was your 
current working directory, the command would have to be:

     $ fossil add --ignore "'doc/REALLY SECRET STUFF.txt'" RE*

instead. The Fossil glob pattern still needs the `doc/` prefix because Fossil 
always interprets glob patterns from the base of the checkout directory, not 
from the current working directory as POSIX shells do.


## Windows

Neither standard Windows command shell — `cmd.exe` or PowerShell — 
expands glob patterns the way POSIX shells do. Windows command shells rely on the 
command itself to do the glob pattern expansion. The way this works depends on several 
factors:

*   the version of Windows you’re using
*   which OS upgrades have been applied to it
*   the compiler that built your Fossil executable
*   whether you’re running the command interactively
*   whether the command is built against a runtime system that does this at all
*   whether the Fossil command is being run from a file named `*.BAT` vs being 
named `*.CMD`
*   the phase of the moon and whether this is an odd-numbered Thursday.  (No, 
not really, but the other caveats are all true.  Yay, Windows!)

These factors also affect how a program like `fossil.exe` interprets quotation 
marks on its command line.

The fifth item above doesn’t apply to `fossil.exe` when built with typical tool 
chains, but we’ll see an example below where the exception applies in a way 
that affects how Fossil interprets the glob pattern.

The most common problem is figuring out how to get a glob pattern passed on the 
command line into `fossil.exe` without it being expanded by the C runtime 
library that your particular Fossil executable is linked to, which tries to act 
like the POSIX systems described above. Windows is not strongly governed by 
POSIX, so it has not historically hewed closely to its strictures.

(This section does not cover the [Microsoft POSIX 
subsystem](https://en.wikipedia.org/wiki/Microsoft_POSIX_subsystem), Windows’ 
obsolete [Services for Unix 
3.*x*](https://en.wikipedia.org/wiki/Windows_Services_for_UNIX) feature, or the 
[Windows Subsystem for 
Linux](https://en.wikipedia.org/wiki/Windows_Subsystem_for_Linux). (The latter 
is sometimes incorrectly called “Bash on Windows” or “Ubuntu on Windows.”) See 
the POSIX Systems section above for those cases.)

For example, consider how you would set `crlf-glob` to `*`. The naïve 
approach will not work:

     c:\...> fossil setting crlf-glob *

The C runtime library will expand that to the list of all files in the current 
directory, which will probably cause a Fossil error because Fossil expects 
either “`global`” or nothing after command line parameter giving the setting’s 
new value. If you happened to run this in a directory with two files, one of 
which was called `global`, it might appear to work but do the wrong thing, 
depending on whether the `global` file name was expanded first or second.

Actually, the magic name would be --global which is much less likely to be a file name due to the difficulty with getting most *nix commands to create such a file. I was going to observe that the leading dash would likely sort that name to the front of the command line, except despite the help text telling you it must be after the value, fossil actually doesn't care.

The sorting of wildcards does vary depending on the underlying file system. If run in a FAT32 folder, I believe * will expand in disk order which varies depending on the exact sequence of file creation and deletion to this point in time. If run in an NTFS folder, * will expand in alphabetical order (really in Unicode codepoint order) since the underlying file system is more like a database than you might expect.

Let’s try again:

     c:\...> fossil setting crlf-glob '*'

That may or may not work, depending on the factors listed above. On one system 
where this was tested, it failed because the command shell sees that no file in 
the current directory matches the glob pattern `'*'`, so the command shell 
passed those three characters unchanged to `fossil.exe`, which stored them 
as-is. Then when Fossil went to apply that glob pattern to file names, it saw 
that the glob pattern is quoted, so it didn’t interpret `*` as meaning “any 
series of characters;” the quotes made Fossil skip the “looks like a text file” 
rules only for a file called exactly `'*'` rather than what we wanted, which 
was to skip those rule checks for all files at the top of the checkout 
directory.

I think that should actually work, at least using CMD not Powershell. Yes, the stored value of crlf-glob would be '*' (with the single quotes) but the glob list parser should strip the quotes off when it reads the setting to use it.

C:...> fossil test-glob '*' abc
SQL expression: (x GLOB '*')
pattern[0] = [*]
1 abc

I wish I had a good link to point at discussing Windows shell quoting in depth.

Powershell seems to have completely different quoting rules. I have heard rumors the next revision of Windows will be making it the default shell. Brace for the avalanche of confused users.

PS C:...> fossil test-glob '*' abc
SQL expression: (x GLOB '.all-help-9c65b5432e.html.espell')
pattern[0] = [.all-help-9c65b5432e.html.espell]
0 .dockerignore
0 .fossil-settings
.... (lots of lines omitted here)
0 abc
PS C:...> fossil test-glob "'* ?'" a "a bc" "ab c"
SQL expression: (x GLOB '* ?')
pattern[0] = [* ?]
0 a
0 a bc
1 ab c
PS C:...>

I think the file .all-help-9c65b5432e.html.espell is a result of my text editor having been used once upon a time to spell check the output of the fossil test-all-help command. (Which, IIRC, I added so that I could do that spell check.)

An approach that*will*  work reliably is:

     c:\...> echo * | fossil setting crlf-glob --args -

This works because the built-in command `echo` does not expand its arguments, 
and the global Fossil option `--args` makes it read further command arguments 
from `-`, meaning Fossil’s standard input, which is connected to the output of 
`echo` by the pipe.

Another correct approach is:

     c:\...> fossil setting crlf-glob *,

This works because the trailing comma prevents the command shell from matching 
any files, unless you happen to have files named with a trailing comma in the 
current directory. If the pattern matches no files, it is passed into Fossil’s 
`main()` function as-is by the C runtime system. Since Fossil uses commas to 
separate multiple glob patterns, this means “all files at the root of the 
Fossil checkout directory and nothing else.”


--
Ross Berteig                               r...@cheshireeng.com
Cheshire Engineering Corp.           http://www.CheshireEng.com/
+1 626 303 1602

_______________________________________________
fossil-dev mailing list
fossil-dev@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/fossil-dev

Reply via email to