Sitelet https://github.com/DarkDaskin/UnityModStudio/commit/b756d09fce53dfafe29a8c719b38e8507fc73540
Skip to content

Commit b756d09

Browse files
committed
Reworked mod deployment.
Added an option to disable deployment. Added an option to create symbolic link to mod sources. Added possibility to deploy mod content files.
1 parent 566fead commit b756d09

15 files changed

Lines changed: 394 additions & 45 deletions
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
using System;
2+
using System.IO;
3+
using FileSystemLinks;
4+
using Microsoft.Build.Framework;
5+
using Microsoft.Build.Utilities;
6+
7+
namespace UnityModStudio.Build.Tasks;
8+
9+
public class CreateSymbolicLink : Task
10+
{
11+
[Required]
12+
public string? SymbolicLink { get; set; }
13+
14+
[Required]
15+
public string? Target { get; set; }
16+
17+
public override bool Execute()
18+
{
19+
if (string.IsNullOrWhiteSpace(SymbolicLink))
20+
{
21+
Log.LogError("SymbolicLink is empty.");
22+
return false;
23+
}
24+
if (string.IsNullOrWhiteSpace(Target))
25+
{
26+
Log.LogError("Target is empty.");
27+
return false;
28+
}
29+
30+
try
31+
{
32+
if (File.Exists(Target))
33+
{
34+
Log.LogMessage(MessageImportance.Normal, "Creating symbolic link to file \"{0}\".", Target!);
35+
FileSystemLink.CreateFileSymbolicLink(SymbolicLink!, Target!);
36+
}
37+
else if (Directory.Exists(Target))
38+
{
39+
Log.LogMessage(MessageImportance.Normal, "Creating symbolic link to directory \"{0}\".", Target!);
40+
FileSystemLink.CreateDirectorySymbolicLink(SymbolicLink!, Target!);
41+
}
42+
else
43+
{
44+
Log.LogError("Target does not exist.");
45+
return false;
46+
}
47+
}
48+
catch (Exception exception)
49+
{
50+
Log.LogErrorFromException(exception);
51+
return false;
52+
}
53+
54+
return true;
55+
}
56+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
using System;
2+
using System.IO;
3+
using Microsoft.Build.Framework;
4+
using Microsoft.Build.Utilities;
5+
6+
namespace UnityModStudio.Build.Tasks;
7+
8+
public class DeleteSymbolicLink : Task
9+
{
10+
[Required]
11+
public string? Path { get; set; }
12+
13+
public override bool Execute()
14+
{
15+
if (string.IsNullOrWhiteSpace(Path))
16+
{
17+
Log.LogError("Path is empty.");
18+
return false;
19+
}
20+
21+
const string deletingMessageFormat = "Deleting \"{0}\".";
22+
try
23+
{
24+
if (File.Exists(Path))
25+
{
26+
Log.LogMessage(MessageImportance.Normal, deletingMessageFormat, Path);
27+
File.Delete(Path!);
28+
}
29+
else if (Directory.Exists(Path))
30+
{
31+
Log.LogMessage(MessageImportance.Normal, deletingMessageFormat, Path);
32+
Directory.Delete(Path!);
33+
}
34+
else
35+
Log.LogMessage(MessageImportance.Low, "File or directory \"{0}\" does not exist. Skipping.", Path);
36+
}
37+
catch (Exception exception)
38+
{
39+
Log.LogErrorFromException(exception);
40+
return false;
41+
}
42+
43+
return true;
44+
}
45+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
using System.IO;
2+
using System;
3+
using FileSystemLinks;
4+
using Microsoft.Build.Framework;
5+
using Microsoft.Build.Utilities;
6+
7+
namespace UnityModStudio.Build.Tasks;
8+
9+
public class GetSymbolicLinkTarget : Task
10+
{
11+
[Required]
12+
public string? SymbolicLink { get; set; }
13+
14+
[Output]
15+
public string? Target { get; set; }
16+
17+
public override bool Execute()
18+
{
19+
if (string.IsNullOrWhiteSpace(SymbolicLink))
20+
{
21+
Log.LogError("SymbolicLink is empty.");
22+
return false;
23+
}
24+
25+
try
26+
{
27+
if (File.Exists(SymbolicLink))
28+
Target = FileSystemLink.GetFileLinkTarget(SymbolicLink!);
29+
else if (Directory.Exists(SymbolicLink))
30+
Target = FileSystemLink.GetDirectoryLinkTarget(SymbolicLink!);
31+
}
32+
catch (Exception exception)
33+
{
34+
Log.LogErrorFromException(exception);
35+
return false;
36+
}
37+
38+
return true;
39+
}
40+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
using System.IO;
2+
using System.Linq;
3+
using Microsoft.Build.Framework;
4+
using Microsoft.Build.Utilities;
5+
6+
namespace UnityModStudio.Build.Tasks;
7+
8+
public class RemoveEmptyDirectories : Task
9+
{
10+
[Required]
11+
public ITaskItem[] Directories { get; set; } = [];
12+
13+
public override bool Execute()
14+
{
15+
foreach (var directory in Directories)
16+
RemoveEmptyDirectoriesImpl(directory.ItemSpec);
17+
18+
return true;
19+
}
20+
21+
private void RemoveEmptyDirectoriesImpl(string path)
22+
{
23+
foreach (var subDirectoryPath in Directory.EnumerateDirectories(path))
24+
RemoveEmptyDirectoriesImpl(subDirectoryPath);
25+
26+
if (!Directory.EnumerateFileSystemEntries(path).Any())
27+
{
28+
Log.LogMessage("Deleting empty directory \"{0}\".", path);
29+
Directory.Delete(path);
30+
}
31+
}
32+
}

‎UnityModStudio.Build/Tasks/ResolveGameProperties.cs‎

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,15 @@ namespace UnityModStudio.Build.Tasks
1010
public class ResolveGameProperties : Task
1111
{
1212
[Required]
13-
public ITaskItem[] LookupProperties { get; set; } = Array.Empty<ITaskItem>();
13+
public ITaskItem[] LookupProperties { get; set; } = [];
1414

1515
public bool BuildingInsideVisualStudio { get; set; }
1616

1717
[Output]
1818
public ITaskItem? GamePath { get; private set; }
1919

2020
[Output]
21-
public ITaskItem? ModRootPath { get; private set; }
21+
public ITaskItem? GameModsPath { get; private set; }
2222

2323
[Output]
2424
public string? GameExecutableFileName { get; private set; }
@@ -29,6 +29,9 @@ public class ResolveGameProperties : Task
2929
[Output]
3030
public string? DoorstopMode { get; private set; }
3131

32+
[Output]
33+
public string? ModDeploymentMode { get; private set; }
34+
3235
[Output]
3336
public bool UseAlternateDoorstopDllName { get; private set; }
3437

@@ -51,11 +54,12 @@ public override bool Execute()
5154
{
5255
case GameMatchResult.Match match:
5356
GamePath = new TaskItem(Utils.AppendTrailingSlash(match.Game.Path));
54-
ModRootPath = match.Game.ModRootPath != null ? new TaskItem(Utils.AppendTrailingSlash(match.Game.ModRootPath)) : null;
57+
GameModsPath = match.Game.ModsPath != null ? new TaskItem(Utils.AppendTrailingSlash(match.Game.ModsPath)) : null;
5558
GameExecutableFileName = match.Game.GameExecutableFileName;
5659
GameInstanceId = match.Game.Id.ToString();
5760
DoorstopMode = match.Game.DoorstopMode.ToString();
5861
UseAlternateDoorstopDllName = match.Game.UseAlternateDoorstopDllName;
62+
ModDeploymentMode = match.Game.ModDeploymentMode.ToString();
5963
return true;
6064

6165
case GameMatchResult.NoMatch:
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
using System;
2+
using System.IO;
3+
using System.Linq;
4+
using Microsoft.Build.Framework;
5+
using Microsoft.Build.Utilities;
6+
using UnityModStudio.Common;
7+
8+
namespace UnityModStudio.Build.Tasks;
9+
10+
public class ResolveTargetPath : Task
11+
{
12+
private const string TargetPathMetadataName = "TargetPath";
13+
14+
[Required]
15+
public string RelativeToPath { get; set; } = "";
16+
17+
[Required]
18+
public ITaskItem[] Input { get; set; } = [];
19+
20+
[Output]
21+
public ITaskItem[]? Output { get; set; }
22+
23+
public override bool Execute()
24+
{
25+
var relativeToFullPath = Utils.AppendTrailingSlash(Path.GetFullPath(RelativeToPath));
26+
27+
Output = new ITaskItem[Input.Length];
28+
for (var i = 0; i < Input.Length; i++)
29+
{
30+
var outputItem = new TaskItem(Input[i].ItemSpec);
31+
Input[i].CopyMetadataTo(outputItem);
32+
33+
string? targetPath = null;
34+
if (!outputItem.MetadataNames.Cast<string>().Contains(TargetPathMetadataName))
35+
{
36+
var fullPath = outputItem.GetMetadata("FullPath");
37+
var directoryName = Path.GetDirectoryName(fullPath) ?? "";
38+
if (directoryName.StartsWith(relativeToFullPath, StringComparison.OrdinalIgnoreCase))
39+
targetPath = directoryName.Substring(relativeToFullPath.Length);
40+
}
41+
else
42+
targetPath = outputItem.GetMetadata(TargetPathMetadataName);
43+
44+
if (!string.IsNullOrEmpty(targetPath))
45+
targetPath = Utils.AppendTrailingSlash(targetPath!);
46+
47+
if (targetPath is not null)
48+
outputItem.SetMetadata(TargetPathMetadataName, targetPath);
49+
50+
Output[i] = outputItem;
51+
}
52+
53+
return true;
54+
}
55+
}

‎UnityModStudio.Build/UnityModStudio.Build.csproj‎

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
</PropertyGroup>
1313

1414
<ItemGroup>
15+
<PackageReference Include="FileSystemLinks" Version="1.0.3" />
1516
<PackageReference Include="Microsoft.Build.Framework" Version="17.4.0" PrivateAssets="all" />
1617
<PackageReference Include="Microsoft.Build.Utilities.Core" Version="17.4.0" PrivateAssets="all" />
1718
<PackageReference Include="Nullable" Version="1.3.1" PrivateAssets="all" IncludeAssets="contentfiles" />
@@ -23,8 +24,8 @@
2324
</ItemGroup>
2425

2526
<ItemGroup>
26-
<None Include="build\*" Pack="true" PackagePath="build\" />
27-
<None Include="README.md" Pack="true" PackagePath="" />
27+
<None Include="build\*" Pack="true" PackagePath="build\" TargetPath="build2\" />
28+
<None Include="README.md" Pack="true" PackagePath="" TargetPath="docs\" />
2829
<!-- This is the recommended way to get rid of the NU5128 warning. -->
2930
<!-- See https://docs.microsoft.com/en-us/nuget/reference/errors-and-warnings/nu5128 -->
3031
<None Include="_._" Visible="false" Pack="true" PackagePath="lib\netstandard2.0\" />
@@ -33,8 +34,8 @@
3334
<!-- Merge UnityDoorstop package into this project package. -->
3435
<!-- Can't just set Visible="false" due to https://github.com/microsoft/VSProjectSystem/issues/162, so put it into a folder instead. -->
3536
<ItemGroup>
36-
<None Include="$(PkgUnityDoorstop)\content\**" Link="UnityDoorstop\content\%(RecursiveDir)%(Filename)%(Extension)" Pack="true" PackagePath="content\" />
37-
<None Include="$(PkgUnityDoorstop)\runtimes\**" Link="UnityDoorstop\runtimes\%(RecursiveDir)%(Filename)%(Extension)" Pack="true" PackagePath="runtimes\" />
37+
<None Include="$(PkgUnityDoorstop)\content\**" LinkBase="UnityDoorstop\content\" Visible="false" Pack="true" PackagePath="content\" />
38+
<None Include="$(PkgUnityDoorstop)\runtimes\**" LinkBase="UnityDoorstop\runtimes\" Visible="false" Pack="true" PackagePath="runtimes\" />
3839
</ItemGroup>
3940

4041
<ItemGroup>
@@ -49,4 +50,8 @@
4950
</ItemGroup>
5051
</Target>
5152

53+
<Target Name="DeleteLocalCache" BeforeTargets="Pack">
54+
<RemoveDir Directories="$(NugetPackageRoot)/$(PackageId.ToLower())/$(PackageVersion)"/>
55+
</Target>
56+
5257
</Project>

0 commit comments

Comments
 (0)