Package: thunderbird Version: 1:45.7.1-2 Severity: grave Justification: renders package unusable (for new installations)
Steps to reproduce: * Use a new account that has never run thunderbird or icedove * Start thunderbird Expected result: * Account creation wizard or something (I can't actually remember what the new user UX is) Actual result: """ An existing profile folder (or symlink) '.thunderbird' was found ... """ However, my test user definitely does not have ~/.thunderbird or ~/.icedove, and has never run either program before today (I used a fresh VM to verify). Looking at the /usr/bin/thunderbird script, this issue seems to be caused by trying to combine comments with backslash line continuations. I'm honestly not sure what that parses as, but I'm sure it is not what you intended. In this conditional: elif { [ -d "${ID_PROFILE_FOLDER}" ] || [ -L "${ID_PROFILE_FOLDER}" ]; } && \ # .icedove exists as folder or symlink { [ -d "${TB_PROFILE_FOLDER}" ] || [ -L "${TB_PROFILE_FOLDER}" ]; } && \ # .thunderbird exists as folder or symlink [ "$(readlink -e "${TB_PROFILE_FOLDER}")" != "${ID_PROFILE_FOLDER}" ]; then # compare if canonical name of both folders equal the overall expression somehow evaluates to true for my test account, because the last [ ] expression evaluates to true. Here is a simplified form of the same thing: if { echo "eval 1"; false; } && \ # { echo "eval 2"; false; } && \ # [ "$(readlink -e "${TB_PROFILE_FOLDER}")" != "${ID_PROFILE_FOLDER}" ]; then # echo "wtf" fi which outputs "eval 1", "eval 2", "wtf", indicating that the first two { } blocks were evaluated but the overall expression did not short-circuit, and the last expression was used for the "if". I think this *might* be parsing as the equivalent of this (redundant semicolons inserted for clarity): if { { echo "eval 1"; false; } && " "; { echo "eval 2"; false; } && " "; [ "$(readlink -e ...)" != "..." ]; } then echo "wtf" fi in which the whole {} block evaluates to the result of its last statement. The backslash turns the following space into an unusual command name containing only a space, then the comment eats everything until the end of the line; and you don't see an error for the nonexistent executable " " because the false statement before it causes the && operator to short-circuit. Shell scripts are less a programming language, and more a historical accident. They are a terrible implementation language for anything complicated or affecting data-integrity, particularly if you do not know every last corner of the language - a bit like the bad reputation PHP has built up, they make it easy to construct a script that mostly works most of the time, but extremely difficult to construct a script that works correctly in every case. There are several things you could do to mitigate this: * Have an expert on the pitfalls of shell scripts review your scripts before releasing them to unstable - it's somewhat too late for this now, since these scripts are already in unstable * Write as conservatively as possible, avoiding anything that might be considered weird or subtle (and trying to combine backslash escapes with comment-until-end-of-line is definitely that) * Use a structured programming language instead, perhaps Python 3 (the subprocess module is excellent) or Perl (IPC::Run is a bit weird but works) - either is relatively small when compared with the Gecko engine * Have a test plan enumerating the supported scenarios (as a starting point: new user, user with ~/.icedove, user with ~/.thunderbird, error case with both ~/.icedove and ~/.thunderbird), and test all supported scenarios for each change to the scripts Policy ยง10.4 contains some excellent advice on shell scripts https://www.debian.org/doc/debian-policy/ch-files.html#s-scripts including: "Shell scripts (sh and bash) other than init.d scripts should almost certainly start with set -e so that errors are detected ... Every script should use set -e or check the exit status of *every* command." My personal rule of thumb is that if the entire content of a shell script doesn't all fit on your screen (and in your short-term memory!) at the same time, or if it uses ". /some/library/code", then it is probably too long to be a shell script and should probably be rewritten in a programming language. I like Python 3 with the subprocess module as an implementation of that programming language. S