@@ -0,0 +1,93 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | |||
<Import Project="..\packages\xunit.runner.visualstudio.2.1.0\build\net20\xunit.runner.visualstudio.props" Condition="Exists('..\packages\xunit.runner.visualstudio.2.1.0\build\net20\xunit.runner.visualstudio.props')" /> | |||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> | |||
<PropertyGroup> | |||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> | |||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> | |||
<ProjectGuid>{C66092B0-5C1E-44E9-B524-E0E8E1425379}</ProjectGuid> | |||
<OutputType>Library</OutputType> | |||
<AppDesignerFolder>Properties</AppDesignerFolder> | |||
<RootNamespace>IPA.Tests</RootNamespace> | |||
<AssemblyName>IPA.Tests</AssemblyName> | |||
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion> | |||
<FileAlignment>512</FileAlignment> | |||
<TargetFrameworkProfile /> | |||
<NuGetPackageImportStamp> | |||
</NuGetPackageImportStamp> | |||
</PropertyGroup> | |||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> | |||
<DebugSymbols>true</DebugSymbols> | |||
<DebugType>full</DebugType> | |||
<Optimize>false</Optimize> | |||
<OutputPath>bin\Debug\</OutputPath> | |||
<DefineConstants>DEBUG;TRACE</DefineConstants> | |||
<ErrorReport>prompt</ErrorReport> | |||
<WarningLevel>4</WarningLevel> | |||
</PropertyGroup> | |||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> | |||
<DebugType>pdbonly</DebugType> | |||
<Optimize>true</Optimize> | |||
<OutputPath>bin\Release\</OutputPath> | |||
<DefineConstants>TRACE</DefineConstants> | |||
<ErrorReport>prompt</ErrorReport> | |||
<WarningLevel>4</WarningLevel> | |||
</PropertyGroup> | |||
<ItemGroup> | |||
<Reference Include="System" /> | |||
<Reference Include="System.Core" /> | |||
<Reference Include="System.Xml.Linq" /> | |||
<Reference Include="System.Data.DataSetExtensions" /> | |||
<Reference Include="Microsoft.CSharp" /> | |||
<Reference Include="System.Data" /> | |||
<Reference Include="System.Net.Http" /> | |||
<Reference Include="System.Xml" /> | |||
<Reference Include="xunit.abstractions, Version=2.0.0.0, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL"> | |||
<HintPath>..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll</HintPath> | |||
<Private>True</Private> | |||
</Reference> | |||
<Reference Include="xunit.assert, Version=2.1.0.3179, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL"> | |||
<HintPath>..\packages\xunit.assert.2.1.0\lib\dotnet\xunit.assert.dll</HintPath> | |||
<Private>True</Private> | |||
</Reference> | |||
<Reference Include="xunit.core, Version=2.1.0.3179, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL"> | |||
<HintPath>..\packages\xunit.extensibility.core.2.1.0\lib\dotnet\xunit.core.dll</HintPath> | |||
<Private>True</Private> | |||
</Reference> | |||
<Reference Include="xunit.execution.desktop, Version=2.1.0.3179, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL"> | |||
<HintPath>..\packages\xunit.extensibility.execution.2.1.0\lib\net45\xunit.execution.desktop.dll</HintPath> | |||
<Private>True</Private> | |||
</Reference> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<Compile Include="ProgramTest.cs" /> | |||
<Compile Include="Properties\AssemblyInfo.cs" /> | |||
<Compile Include="ShortcutTest.cs" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<None Include="packages.config" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<ProjectReference Include="..\IPA\IPA.csproj"> | |||
<Project>{14092533-98bb-40a4-9afc-27bb75672a70}</Project> | |||
<Name>IPA</Name> | |||
</ProjectReference> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" /> | |||
</ItemGroup> | |||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> | |||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild"> | |||
<PropertyGroup> | |||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText> | |||
</PropertyGroup> | |||
<Error Condition="!Exists('..\packages\xunit.runner.visualstudio.2.1.0\build\net20\xunit.runner.visualstudio.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\xunit.runner.visualstudio.2.1.0\build\net20\xunit.runner.visualstudio.props'))" /> | |||
</Target> | |||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. | |||
Other similar extension points exist, see Microsoft.Common.targets. | |||
<Target Name="BeforeBuild"> | |||
</Target> | |||
<Target Name="AfterBuild"> | |||
</Target> | |||
--> | |||
</Project> |
@@ -0,0 +1,39 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.IO; | |||
using System.Linq; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
using Xunit; | |||
namespace IPA.Tests | |||
{ | |||
public class ProgramTest | |||
{ | |||
[Theory] | |||
// Unrelated path | |||
[InlineData("test/from.dll", "test/to.dll", "native", false, new string[] { "test/to.dll" })] | |||
// Flat -> Not-Flat | |||
[InlineData("native/from.dll", "native/to.dll", "native", false, new string[] { "native/x86/to.dll", "native/x86_64/to.dll" })] | |||
// Flat -> Flat | |||
[InlineData("native/from.dll", "native/to.dll", "native", true, new string[] { "native/to.dll" })] | |||
// Not-Flat -> Flat | |||
[InlineData("native/x86/from.dll", "native/x86/to.dll", "native", true, new string[] { })] | |||
[InlineData("native/x86_64/from.dll", "native/x86_64/to.dll", "native", true, new string[] { "native/to.dll" })] | |||
// Not-flat -> Not-Flat | |||
[InlineData("native/x86/from.dll", "native/x86/to.dll", "native", false, new string[] { "native/x86/to.dll" })] | |||
[InlineData("native/x86_64/from.dll", "native/x86_64/to.dll", "native", false, new string[] { "native/x86_64/to.dll" })] | |||
public void CopiesCorrectly(string from, string to, string nativeFolder, bool isFlat, string[] expected) | |||
{ | |||
var outcome = Program.NativePluginInterceptor(new FileInfo(from), new FileInfo(to), new DirectoryInfo(nativeFolder), isFlat).Select(f => f.FullName).ToList(); | |||
var expectedPaths = expected.Select(e => new FileInfo(e)).Select(f => f.FullName).ToList(); | |||
Assert.Equal(expectedPaths, outcome); | |||
} | |||
} | |||
} |
@@ -0,0 +1,36 @@ | |||
using System.Reflection; | |||
using System.Runtime.CompilerServices; | |||
using System.Runtime.InteropServices; | |||
// General Information about an assembly is controlled through the following | |||
// set of attributes. Change these attribute values to modify the information | |||
// associated with an assembly. | |||
[assembly: AssemblyTitle("IPA.Tests")] | |||
[assembly: AssemblyDescription("")] | |||
[assembly: AssemblyConfiguration("")] | |||
[assembly: AssemblyCompany("")] | |||
[assembly: AssemblyProduct("IPA.Tests")] | |||
[assembly: AssemblyCopyright("Copyright © 2017")] | |||
[assembly: AssemblyTrademark("")] | |||
[assembly: AssemblyCulture("")] | |||
// Setting ComVisible to false makes the types in this assembly not visible | |||
// to COM components. If you need to access a type in this assembly from | |||
// COM, set the ComVisible attribute to true on that type. | |||
[assembly: ComVisible(false)] | |||
// The following GUID is for the ID of the typelib if this project is exposed to COM | |||
[assembly: Guid("c66092b0-5c1e-44e9-b524-e0e8e1425379")] | |||
// Version information for an assembly consists of the following four values: | |||
// | |||
// Major Version | |||
// Minor Version | |||
// Build Number | |||
// Revision | |||
// | |||
// You can specify all the values or you can default the Build and Revision Numbers | |||
// by using the '*' as shown below: | |||
// [assembly: AssemblyVersion("1.0.*")] | |||
[assembly: AssemblyVersion("1.0.0.0")] | |||
[assembly: AssemblyFileVersion("1.0.0.0")] |
@@ -0,0 +1,37 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.IO; | |||
using System.Linq; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
using Xunit; | |||
namespace IPA.Tests | |||
{ | |||
public class ShortcutTest | |||
{ | |||
[Fact] | |||
public void CanDealWithEmptyFiles() | |||
{ | |||
Shortcut.Create(".lnk", "", "", "", "", "", ""); | |||
} | |||
[Fact] | |||
public void CanDealWithLongFiles() | |||
{ | |||
Shortcut.Create(".lnk", Path.Combine(Path.GetTempPath(), string.Join("_", new string[500])), "", "", "", "", ""); | |||
} | |||
[Fact] | |||
public void CantDealWithNull() | |||
{ | |||
Assert.Throws<ArgumentException>(() => Shortcut.Create(".lnk", null, "", "", "", "", "")); | |||
} | |||
[Fact] | |||
public void CanDealWithWeirdCharacters() | |||
{ | |||
Shortcut.Create(".lnk", "äöü", "", "", "", "", ""); | |||
} | |||
} | |||
} |
@@ -0,0 +1,11 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<packages> | |||
<package id="xunit" version="2.1.0" targetFramework="net452" /> | |||
<package id="xunit.abstractions" version="2.0.0" targetFramework="net452" /> | |||
<package id="xunit.assert" version="2.1.0" targetFramework="net452" /> | |||
<package id="xunit.core" version="2.1.0" targetFramework="net452" /> | |||
<package id="xunit.extensibility.core" version="2.1.0" targetFramework="net452" /> | |||
<package id="xunit.extensibility.execution" version="2.1.0" targetFramework="net452" /> | |||
<package id="xunit.runner.console" version="2.1.0" targetFramework="net452" /> | |||
<package id="xunit.runner.visualstudio" version="2.1.0" targetFramework="net452" /> | |||
</packages> |
@@ -1,7 +1,7 @@ | |||
| |||
Microsoft Visual Studio Solution File, Format Version 12.00 | |||
# Visual Studio 14 | |||
VisualStudioVersion = 14.0.25123.0 | |||
VisualStudioVersion = 14.0.25420.1 | |||
MinimumVisualStudioVersion = 10.0.40219.1 | |||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IPA", "IPA\IPA.csproj", "{14092533-98BB-40A4-9AFC-27BB75672A70}" | |||
ProjectSection(ProjectDependencies) = postProject | |||
@@ -16,6 +16,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IllusionPlugin", "IllusionP | |||
EndProject | |||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IllusionInjector", "IllusionInjector\IllusionInjector.csproj", "{D1C61AF5-0D2D-4752-8203-1C6929025F7C}" | |||
EndProject | |||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IPA.Tests", "IPA.Tests\IPA.Tests.csproj", "{C66092B0-5C1E-44E9-B524-E0E8E1425379}" | |||
EndProject | |||
Global | |||
GlobalSection(SolutionConfigurationPlatforms) = preSolution | |||
Debug|Any CPU = Debug|Any CPU | |||
@@ -38,6 +40,10 @@ Global | |||
{D1C61AF5-0D2D-4752-8203-1C6929025F7C}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||
{D1C61AF5-0D2D-4752-8203-1C6929025F7C}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||
{D1C61AF5-0D2D-4752-8203-1C6929025F7C}.Release|Any CPU.Build.0 = Release|Any CPU | |||
{C66092B0-5C1E-44E9-B524-E0E8E1425379}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||
{C66092B0-5C1E-44E9-B524-E0E8E1425379}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||
{C66092B0-5C1E-44E9-B524-E0E8E1425379}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||
{C66092B0-5C1E-44E9-B524-E0E8E1425379}.Release|Any CPU.Build.0 = Release|Any CPU | |||
EndGlobalSection | |||
GlobalSection(SolutionProperties) = preSolution | |||
HideSolutionNode = FALSE | |||
@@ -13,7 +13,7 @@ using System.Windows.Forms; | |||
namespace IPA | |||
{ | |||
class Program | |||
public class Program | |||
{ | |||
static void Main(string[] args) | |||
@@ -59,8 +59,11 @@ namespace IPA | |||
try | |||
{ | |||
// Copying | |||
Console.Write("Updating files... "); | |||
CopyAll(new DirectoryInfo(context.DataPathSrc), new DirectoryInfo(context.DataPathDst)); | |||
Console.WriteLine("Updating files... "); | |||
var nativePluginFolder = Path.Combine(context.DataPathDst, "Plugins"); | |||
bool isFlat = Directory.Exists(nativePluginFolder) && Directory.GetFiles(nativePluginFolder).Any(f => f.EndsWith(".dll")); | |||
CopyAll(new DirectoryInfo(context.DataPathSrc), new DirectoryInfo(context.DataPathDst), (from, to) => NativePluginInterceptor(from, to, new DirectoryInfo(nativePluginFolder), isFlat) ); | |||
Console.WriteLine("Successfully updated files!"); | |||
if (!Directory.Exists(context.PluginsFolder)) | |||
@@ -165,18 +168,65 @@ namespace IPA | |||
} | |||
} | |||
public static void CopyAll(DirectoryInfo source, DirectoryInfo target) | |||
public static IEnumerable<FileInfo> NativePluginInterceptor(FileInfo from, FileInfo to, DirectoryInfo nativePluginFolder, bool isFlat) | |||
{ | |||
if (to.FullName.StartsWith(nativePluginFolder.FullName)) | |||
{ | |||
var relevantBit = to.FullName.Substring(nativePluginFolder.FullName.Length + 1); | |||
// Goes into the plugin folder! | |||
bool isFileFlat = !relevantBit.StartsWith("x86"); | |||
if (isFlat && !isFileFlat) | |||
{ | |||
// Flatten structure | |||
if (relevantBit.StartsWith("x86_64")) | |||
{ | |||
yield return new FileInfo(Path.Combine(nativePluginFolder.FullName, relevantBit.Substring("x86_64".Length + 1))); | |||
} | |||
else | |||
{ | |||
// Throw away | |||
yield break; | |||
} | |||
} | |||
else if (!isFlat && isFileFlat) | |||
{ | |||
// Deepen structure | |||
yield return new FileInfo(Path.Combine(Path.Combine(nativePluginFolder.FullName, "x86"), relevantBit)); | |||
yield return new FileInfo(Path.Combine(Path.Combine(nativePluginFolder.FullName, "x86_64"), relevantBit)); | |||
} | |||
else | |||
{ | |||
yield return to; | |||
} | |||
} | |||
else | |||
{ | |||
yield return to; | |||
} | |||
} | |||
private static IEnumerable<FileInfo> PassThroughInterceptor(FileInfo from, FileInfo to) | |||
{ | |||
yield return to; | |||
} | |||
public static void CopyAll(DirectoryInfo source, DirectoryInfo target, Func<FileInfo, FileInfo, IEnumerable<FileInfo>> interceptor = null) | |||
{ | |||
if(interceptor == null) | |||
{ | |||
interceptor = PassThroughInterceptor; | |||
} | |||
Directory.CreateDirectory(target.FullName); | |||
// Copy each file into the new directory. | |||
foreach (FileInfo fi in source.GetFiles()) | |||
{ | |||
string targetFile = Path.Combine(target.FullName, fi.Name); | |||
if (!File.Exists(targetFile) || File.GetLastWriteTimeUtc(targetFile) < fi.LastWriteTimeUtc) | |||
{ | |||
Console.WriteLine(@"Copying {0}\{1}", target.FullName, fi.Name); | |||
fi.CopyTo(Path.Combine(target.FullName, fi.Name), true); | |||
foreach(var targetFile in interceptor(fi, new FileInfo(Path.Combine(target.FullName, fi.Name)))) { | |||
if (!targetFile.Exists || targetFile.LastWriteTimeUtc < fi.LastWriteTimeUtc) | |||
{ | |||
Console.WriteLine(@"Copying {0}", targetFile.FullName); | |||
fi.CopyTo(targetFile.FullName, true); | |||
} | |||
} | |||
} | |||
@@ -185,7 +235,7 @@ namespace IPA | |||
{ | |||
DirectoryInfo nextTargetSubDir = | |||
target.CreateSubdirectory(diSourceSubDir.Name); | |||
CopyAll(diSourceSubDir, nextTargetSubDir); | |||
CopyAll(diSourceSubDir, nextTargetSubDir, interceptor); | |||
} | |||
} | |||