Skip to content

Commit

Permalink
Merge pull request #38 from gariel/main
Browse files Browse the repository at this point in the history
  • Loading branch information
jolexxa authored Nov 20, 2023
2 parents 8a705d8 + 592b243 commit 8d9daf7
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 0 deletions.
21 changes: 21 additions & 0 deletions GodotEnv/src/common/clients/FileClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,16 @@ public interface IFileClient {
/// link.</param>
Task CreateSymlink(string path, string pathToTarget);

/// <summary>
/// Creates symbolic links recursively on <paramref name="path" />,
/// these links points to <paramref name="pathToTarget" /> by the same structure.
/// Directories are not symlinked but created.
/// </summary>
/// <param name="path">Path to the symbolic link.</param>
/// <param name="pathToTarget">Path to the target of the symbolic
/// link.</param>
Task CreateSymlinkRecursively(string path, string pathToTarget);

/// <summary>
/// Determines if the given directory path is a symlink.
/// </summary>
Expand Down Expand Up @@ -409,6 +419,17 @@ await ProcessRunner.RunElevatedOnWindows(
}
}

public async Task CreateSymlinkRecursively(string path, string pathToTarget) {
CreateDirectory(path);
foreach (var sub in Files.Directory.GetDirectories(pathToTarget)) {
await CreateSymlinkRecursively(Files.Path.Join(path, Files.Path.GetFileName(sub)), sub);
}

foreach (var file in Files.Directory.GetFiles(pathToTarget)) {
await CreateSymlink(Files.Path.Join(path, Files.Path.GetFileName(file)), file);
}
}

public bool IsDirectorySymlink(string path)
=> Files.DirectoryInfo.FromDirectoryName(path).LinkTarget != null;

Expand Down
32 changes: 32 additions & 0 deletions GodotEnv/src/common/clients/NetworkClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@ Task DownloadFileAsync(
CancellationToken token
);

Task DownloadFileAsync(
string url,
string destinationDirectory,
string filename,
CancellationToken token
);

public Task<HttpResponseMessage> WebRequestGetAsync(string url);
}

Expand Down Expand Up @@ -92,4 +99,29 @@ void done(
download.DownloadProgressChanged -= internalProgress;
download.DownloadFileCompleted -= done;
}

public async Task DownloadFileAsync(
string url,
string destinationDirectory,
string filename,
CancellationToken token
) {
var download = DownloadBuilder
.New()
.WithUrl(url)
.WithDirectory(destinationDirectory)
.WithFileName(filename)
.WithConfiguration(DownloadConfiguration)
.Build();

token.Register(
() => {
if (download.Status == DownloadStatus.Running) {
download.Stop();
}
}
);

await download.StartAsync(token);
}
}
73 changes: 73 additions & 0 deletions GodotEnv/src/features/godot/domain/GodotRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,7 @@ public async Task UpdateGodotSymlink(
) {
// Create or update the symlink to the new version of Godot.
await FileClient.CreateSymlink(GodotSymlinkPath, installation.ExecutionPath);
await CreateShortcuts(installation);

if (installation.IsDotnetVersion) {
// Update GodotSharp symlinks
Expand Down Expand Up @@ -385,6 +386,78 @@ await FileClient.CreateSymlink(
log.Print(GodotSymlinkPath);
}

public async Task CreateShortcuts(GodotInstallation instalation) {
switch (FileClient.OS) {
case OSType.MacOS: {
var appFilePath = FileClient.Files.Directory.GetDirectories(instalation.Path).First();
var applicationsPath = FileClient.Combine(FileClient.UserDirectory, "Applications", "Godot.app");
await FileClient.DeleteDirectory(applicationsPath);
await FileClient.CreateSymlinkRecursively(applicationsPath, appFilePath);
break;
}

case OSType.Linux: {
var userApplicationsPath = FileClient.Combine(FileClient.UserDirectory, ".local", "share", "applications");
var userIconsPath = FileClient.Combine(FileClient.UserDirectory, ".local", "share", "icons");

FileClient.CreateDirectory(userApplicationsPath);
FileClient.CreateDirectory(userIconsPath);

await NetworkClient.DownloadFileAsync(
url: "https://godotengine.org/assets/press/icon_color.png",
destinationDirectory: userIconsPath,
filename: "godot.png",
CancellationToken.None);

// https://github.com/godotengine/godot/blob/master/misc/dist/linux/org.godotengine.Godot.desktop
FileClient.CreateFile(FileClient.Combine(userApplicationsPath, "Godot.desktop"),
$"""
[Desktop Entry]
Name=Godot Engine
GenericName=Libre game engine
GenericName[el]=Ελεύθερη μηχανή παιχνιδιού
GenericName[fr]=Moteur de jeu libre
GenericName[zh_CN]=自由的游戏引擎
Comment=Multi-platform 2D and 3D game engine with a feature-rich editor
Comment[el]=2D και 3D μηχανή παιχνιδιού πολλαπλών πλατφορμών με επεξεργαστή πλούσιο σε χαρακτηριστικά
Comment[fr]=Moteur de jeu 2D et 3D multiplateforme avec un éditeur riche en fonctionnalités
Comment[zh_CN]=多平台 2D 和 3D 游戏引擎,带有功能丰富的编辑器
Exec={GodotSymlinkPath} %f
Icon=godot
Terminal=false
PrefersNonDefaultGPU=true
Type=Application
MimeType=application/x-godot-project;
Categories=Development;IDE;
StartupWMClass=Godot
""");
break;
}

case OSType.Windows: {
var hardLinkPath = $"{GodotSymlinkPath}.exe";
await FileClient.DeleteFile(hardLinkPath);
await FileClient.ProcessRunner.RunElevatedOnWindows(
"cmd.exe", $"/c mklink /H \"{hardLinkPath}\" \"{instalation.ExecutionPath}\""
);

var commonStartMenuPath = Environment.GetFolderPath(Environment.SpecialFolder.StartMenu);
var applicationsPath = FileClient.Combine(commonStartMenuPath, "Programs", "Godot.lnk");
var command = string.Join(";",
"$ws = New-Object -ComObject (\"WScript.Shell\")",
$"$s = $ws.CreateShortcut(\"{applicationsPath}\")",
$"$s.TargetPath = \"{hardLinkPath}\"",
"$s.save();"
);
await FileClient.ProcessRunner.Run(".", "powershell", new[] { "-c", command });
break;
}
case OSType.Unknown:
default:
break;
}
}

public async Task AddOrUpdateGodotEnvVariable(ILog log) {
var symlinkPath = GodotSymlinkPath;
var godotVar = Defaults.GODOT_ENV_VAR_NAME;
Expand Down

0 comments on commit 8d9daf7

Please sign in to comment.