Set local-programs-path relative to $STACK_ROOT - haskell-stack

On Windows, local-programs-path (where GHC gets installed) defaults to $LOCALAPPDATA\Programs\stack. I'd like to change that to be $STACK_ROOT\programs (like it is on Linux). I can specify an absolute path, e.g. C:/sr/programs, but how can I specify a path relative to $STACK_ROOT? I can see a few possible solutions:
There is some general environment variable substitution in Stack YAML files (seems generally useful, but not yet implemented).
The default could be changed to always use $STACK_ROOT/programs on all platforms (which is what I would have expected anyway).
Relative paths could be interpreted relative to $STACK_ROOT.
However, none seems to be available as of Stack 1.3.2.

Related

What is the difference between Delphi library routines IsUNCRooted and IsUNCPath?

The current documentation of both functions reads very similar to each another:
System.IOUtils.TPath.IsUNCRooted
System.IOUtils.TPath.IsUNCPath
Both are static members of the same class, with one of them decorated inline, so I wouldn't think they are separate implementations with equivalent functionality you often find across various Delphi classes (although examples within a common class do exist in Embarcadero's standard library).
Specifically, I can't come up with a case where a path is a valid UNC path but not a rooted UNC path. So what does IsUNCRooted even mean?
IsUNCRooted only checks if the parameter starts with an UNC sequence, while IsUNCPath also checks the rest for valid path names. So a valid UNCPath is indeed also UNC rooted, but not always the other way round.

% in Windows environmental variables value

What does % mean in windows environmental variables ?
%SystemRoot%\system32;
%SystemRoot%;
%SystemRoot%\System32\Wbem;
Especially the Path, TMP, TEMP variable values have this sign. There might be other variables also, but I came across only these three.
Do I need to bother about it while setting my own path variables ?
Do I need to bother about it while setting my own path variables ?
Under normal circumstances, no, you don't. You would only do this if you wanted the effective value of PATH to depend on some other environment variable. Even then it is only a convenience, never a necessity.
As a real-world example of when it might be convenient, suppose you've written a program that automates updating the Java SDK to the latest version, so your users don't have to do it by hand. Updating the SDK moves it to a different location, so you probably want to add the new location of the SDK to the path, and remove the old one.
You could do that the hard way, by parsing PATH each time, locating the part that points to the old location and changing it appropriately. But that's a pain, and if you're doing this globally, the users don't have any choice over whether Java is in the path, even if they don't use it. So instead you might create a variable JAVA_PATH that points to the current SDK location. That way, it is easy to change, and individual users can choose whether or not to put %JAVA_PATH% in their own paths.
In Microsoft's case (the examples you noticed) the system root is never going to move, but by using a variable they could hard-code the default value of PATH rather than having to explicitly generate it during operating system installation.
PS: the environment variables referenced in PATH must all be system variables. Referencing a user variable will not work.
%VariableName% is the syntax for referencing an environment variable. The actual name is the part between the % symbols.
So your first line, when fully expanded, would evaluate to the value of the SystemRoot variable, followed by \system32;.
You'll need to use %...% if you want to make use of environment variables in the Windows shell, or if you want to define environment variables that reference other variables.

What are the minimum required environment variables?

I am writing a shell.
With the execvpe system call, I can run a program and control its environment. What are the minimum values I need to pass through here?
Alternatively, I understand that child processes should have a copy of their parent's environment, possibly with some values added. While testing my shell, I am running it from within bash from within my terminal from within a window manager, etc etc. What are the bare basics that I can assume are in my environment? If I were to run my shell straight from a TTY (the "lowest level", as far as I understand), what can I expect?
That’s a very broad question.  To a certain extent,
programs should be able to run with no environment at all.
“X” display (i.e., GUI) programs need to know
where they are supposed to display. 
This information is usually provided
through the DISPLAY environment variable,
but can also be passed on the command line. 
There are probably other environment variables that are essential
(or nearly so) to “X” programs;
it’s been a while since I’ve looked under that hood.
Any program that needs to use special characteristics of your terminal
needs the TERM environment variable. 
“Special characteristics” means being able to set colors
(as ls and grep can do, subject to options),
move around the screen (like vi / vim),
or even know the size of the screen (like less). 
Note that size of the screen may also be available
through ROWS and COLUMNS.
Any program that needs to know the date and time
as perceived / understood by the user needs to know the time zone (TZ) —
although, if you’re willing to work with absolute (GMT / UTC),
you don’t need this.
etc.
The minimum that you need is a working PATH variable. Any extras beyond that depend on what programs you want to execute.
POSIX has a list of commonly-used environment variables, very few programs use more than a few of those.
Generally if you're using execvp*, you're not giving full pathnames for the executables. It makes your programs much simpler, you do not have to provide a full pathname for each executable, as is needed by the plain execv. POSIX describes these functions as
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
and (referring to the parameters of the various exec* functions):
The argument path points to a pathname that identifies the new process image file.
The argument file is used to construct a pathname that identifies the new process image file. If the file argument contains a slash character, the file argument shall be used as the pathname for this file. Otherwise, the path prefix for this file is obtained by a search of the directories passed as the environment variable PATH (see XBD Environment Variables). If this environment variable is not present, the results of the search are implementation-defined.
and (remember that "file" is referring to execvp rather than execv, so the environ variable applies to the search using PATH for the "file" parameter):
For those forms not containing an envp pointer (execl(), execv(), execlp(), and execvp()), the environment for the new process image shall be taken from the external variable environ in the calling process.
So... you could technically remove the entire PATH variable, but the result would be implementation-defined.
The minimum neccessary environment is empty. You don't need anything.
e.g.
$ env -i env
$
We can see that env -i has created a blank environment.
We can take this further:
$ env -i /bin/bash
sweh#server:/home/sweh$ env
LS_COLORS=
PWD=/home/sweh
SHLVL=1
_=/usr/bin/env
We can see that bash has set a few variables, but nothing was inherited.
Now such an environment may break some things; e.g. a missing TERM variable means that vi or less may not work properly
$ less foo
WARNING: terminal is not fully functional
foo (press RETURN)
So, really, you need to determine what programs you expect to run inside the environment and what their needs are.

What is the purpose of adding a "." in a path to a file?

While looking over documentation of projects, tools etc. I have noticed individuals prepending a period to a file path:
I have tried with and without and it still works, but why do people use the convention?
It depends on the specific environment whether a . has a specific meaning. In general . stands for the current directory (and .. being the parent directory). If the environment uses a PATH-like lookup system, there may well be a difference between ./foo and foo.
The PATH is an environment variable in many systems which defines several paths in which files are looked up. E.g. PATH=/bar:/baz:.. This mean, when you try to refer to file foo, this will be looked up as /bar/foo, /baz/foo and ./foo, the first one to match wins.
As such, the difference can be important if the system uses such a relative lookup. I'm not clear on whether gulp does specifically. If it doesn't, it's relatively redundant to use ..

One liner to set environment variable if doesn't exist, else append

I am using bash.
There is an environment variable that I want to either append if it is already set like:
PATH=$PATH":/path/to/bin"
Or if it doesn't already exist I want to simply set it:
PATH="/path/to/bin"
Is there a one line statement to do this?
Obviously the PATH environment variable is pretty much always set but it was easiest to write this question with.
A little improvement on Michael Burr's answer. This works with set -u (set -o nounset) as well:
PATH=${PATH:+$PATH:}/path/to/bin
PATH=${PATH}${PATH:+:}/path/to/bin
${PATH} evaluates to nothing if PATH is not set/empty, otherwise it evaluates to the current path
${PATH:+:} evaluates to nothing if PATH is not set, otherwise it evaluates to ":"
The answers from Michael Burr and user spbnick are already excellent and illustrate the principle. I just want to add two more details:
In their versions, the new path is added to the end of PATH. This is what the OP asked, but it is a less common practice. Adding to the end means that the commands will only be picked if no other commands match from earlier paths. More commonly, users will add to the front to path. This is not what the OP asked, but for other users coming here it may be closer to what they expect. Since the syntax is different I'm highlighting it here.
Also, in the previous versions, the PATH is not quoted. While its unlikely on most Un*x-like operating systems to have spaces in PATH, it is still better practice to always quote.
My slightly improved version, for most typical use cases, is
PATH="/path/to/bin${PATH:+:$PATH}"

Resources