Skip to content

Commit

Permalink
Fix installation on Ubuntu 20 🐛☠️
Browse files Browse the repository at this point in the history
Fix the issue with installation on Ubuntu 20 discovered at #5
Use a new strategy of installing on Linux: Copy the executable file into the directory `/bin/`: Assume most systems will already have the `PATH` environment variable include this directory.
  • Loading branch information
Viir committed Jun 16, 2021
1 parent a33392d commit 0774c4f
Showing 1 changed file with 65 additions and 21 deletions.
86 changes: 65 additions & 21 deletions implement/elm-fullstack/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,14 @@ static int Main(string[] args)

var installCmd = app.Command("install", installCmd =>
{
var (commandName, _, registerExecutableDirectoryOnPath) = CheckIfExecutableIsRegisteredOnPath();
var (commandName, checkInstallation) = CheckIfExecutableIsRegisteredOnPath();

installCmd.Description = "Installs the '" + commandName + "' command for the current user account.";
installCmd.UnrecognizedArgumentHandling = UnrecognizedArgumentHandling.Throw;

installCmd.OnExecute(() =>
{
registerExecutableDirectoryOnPath();
checkInstallation().registerExecutableDirectoryOnPath();
});
});

Expand Down Expand Up @@ -93,8 +93,10 @@ static int Main(string[] args)

allOption.ShortName = "a";

var checkedInstallation = CheckIfExecutableIsRegisteredOnPath().checkInstallation();

var setupGroupCommands =
CheckIfExecutableIsRegisteredOnPath().executableIsRegisteredOnPath
checkedInstallation.executableIsRegisteredOnPath
?
new CommandLineApplication[0] :
new[]
Expand Down Expand Up @@ -1376,7 +1378,7 @@ static public void ReplicateProcessAndLogToConsole(
httpResponse.Content.ReadAsStringAsync().Result);
}

static (string commandName, bool executableIsRegisteredOnPath, Action registerExecutableDirectoryOnPath)
static (string commandName, Func<(bool executableIsRegisteredOnPath, Action registerExecutableDirectoryOnPath)> checkInstallation)
CheckIfExecutableIsRegisteredOnPath()
{
var environmentVariableName = "PATH";
Expand All @@ -1390,29 +1392,71 @@ string getCurrentValueOfEnvironmentVariable() =>

var commandName = Regex.Match(executableFileName, @"(.+?)(?=\.exe$|$)").Groups[1].Value;

var registerExecutableForCurrentUser = new Action(() =>
(bool executableIsRegisteredOnPath, Action registerExecutableDirectoryOnPath) checkInstallation()
{
var newValueForPathEnv =
executableDirectoryPath +
System.IO.Path.PathSeparator +
getCurrentValueOfEnvironmentVariable();
if (System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows))
{
var executableIsRegisteredOnPath =
(getCurrentValueOfEnvironmentVariable() ?? "")
.Split(Path.PathSeparator).Contains(executableDirectoryPath);

var registerExecutableForCurrentUser = new Action(() =>
{
var newValueForPathEnv =
executableDirectoryPath +
Path.PathSeparator +
getCurrentValueOfEnvironmentVariable();

Environment.SetEnvironmentVariable(environmentVariableName, newValueForPathEnv, environmentVariableScope);
Environment.SetEnvironmentVariable(environmentVariableName, newValueForPathEnv, environmentVariableScope);

// https://stackoverflow.com/questions/32650063/get-environment-variable-out-of-new-process-in-c-sharp/32650213#32650213
// https://devblogs.microsoft.com/oldnewthing/?p=91591
// https://docs.microsoft.com/en-us/previous-versions//cc723564(v=technet.10)?redirectedfrom=MSDN#XSLTsection127121120120
// https://stackoverflow.com/questions/32650063/get-environment-variable-out-of-new-process-in-c-sharp/32650213#32650213
// https://devblogs.microsoft.com/oldnewthing/?p=91591
// https://docs.microsoft.com/en-us/previous-versions//cc723564(v=technet.10)?redirectedfrom=MSDN#XSLTsection127121120120

Console.WriteLine(
"I added the path '" + executableDirectoryPath + "' to the '" + environmentVariableName +
"' environment variable for the current user account. You will be able to use the '" + commandName + "' command in newer instances of the Command Prompt.");
});
Console.WriteLine(
"I added the path '" + executableDirectoryPath + "' to the '" + environmentVariableName +
"' environment variable for the current user account. You will be able to use the '" + commandName + "' command in newer instances of the Command Prompt.");
});

return (executableIsRegisteredOnPath, registerExecutableForCurrentUser);
}
else
{
var destinationExecutableFilePath = "/bin/" + commandName;

byte[] currentRegisteredFileContent = null;

if (File.Exists(destinationExecutableFilePath))
{
currentRegisteredFileContent = File.ReadAllBytes(destinationExecutableFilePath);
}

var currentExecuableFileContent = File.ReadAllBytes(executableFilePath);

var executableIsRegisteredOnPath =
currentRegisteredFileContent != null &&
currentRegisteredFileContent.SequenceEqual(currentExecuableFileContent);

var registerExecutableForCurrentUser = new Action(() =>
{
File.WriteAllBytes(destinationExecutableFilePath, currentExecuableFileContent);

var executableIsRegisteredOnPath =
(getCurrentValueOfEnvironmentVariable() ?? "")
.Split(Path.PathSeparator).Contains(executableDirectoryPath);
var unixFileInfo = new Mono.Unix.UnixFileInfo(destinationExecutableFilePath);

unixFileInfo.FileAccessPermissions |=
Mono.Unix.FileAccessPermissions.GroupExecute | Mono.Unix.FileAccessPermissions.UserExecute | Mono.Unix.FileAccessPermissions.OtherExecute |
Mono.Unix.FileAccessPermissions.GroupRead | Mono.Unix.FileAccessPermissions.UserRead | Mono.Unix.FileAccessPermissions.OtherRead;

Console.WriteLine(
"I copied the executable file to '" + destinationExecutableFilePath +
"'. You will be able to use the '" + commandName + "' command in newer terminal instances.");
});

return (executableIsRegisteredOnPath, registerExecutableForCurrentUser);
}
};

return (commandName, executableIsRegisteredOnPath, registerExecutableForCurrentUser);
return (commandName, checkInstallation);
}

static public void BuildConfiguration(
Expand Down

0 comments on commit 0774c4f

Please sign in to comment.