{"action":"created","issue":{"url":"https://api.github.com/repos/cake-build/cake/issues/261","repository_url":"https://api.github.com/repos/cake-build/cake","labels_url":"https://api.github.com/repos/cake-build/cake/issues/261/labels{/name}","comments_url":"https://api.github.com/repos/cake-build/cake/issues/261/comments","events_url":"https://api.github.com/repos/cake-build/cake/issues/261/events","html_url":"https://github.com/cake-build/cake/pull/261","id":84125026,"number":261,"title":"[WIP] OMG Don't merge! - Inital work on Win32 long path support","user":{"login":"devlead","id":1647294,"avatar_url":"https://avatars.githubusercontent.com/u/1647294?v=3","gravatar_id":"","url":"https://api.github.com/users/devlead","html_url":"https://github.com/devlead","followers_url":"https://api.github.com/users/devlead/followers","following_url":"https://api.github.com/users/devlead/following{/other_user}","gists_url":"https://api.github.com/users/devlead/gists{/gist_id}","starred_url":"https://api.github.com/users/devlead/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/devlead/subscriptions","organizations_url":"https://api.github.com/users/devlead/orgs","repos_url":"https://api.github.com/users/devlead/repos","events_url":"https://api.github.com/users/devlead/events{/privacy}","received_events_url":"https://api.github.com/users/devlead/received_events","type":"User","site_admin":false},"labels":[],"state":"closed","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":6,"created_at":"2015-06-02T17:47:49Z","updated_at":"2016-07-19T12:02:57Z","closed_at":"2016-01-18T21:05:51Z","pull_request":{"url":"https://api.github.com/repos/cake-build/cake/pulls/261","html_url":"https://github.com/cake-build/cake/pull/261","diff_url":"https://github.com/cake-build/cake/pull/261.diff","patch_url":"https://github.com/cake-build/cake/pull/261.patch"},"body":"This is just an ugly hack for discussion and see what's the minimal work needen to support long paths on Windows.\r\n\r\nIssue currently .Net only supports max 260 chars in paths and even less for folders names, this is a real issue especially in web projects and deployments which can have more complex folder structures.\r\nWindows itself support longer paths thru other API's, there are a couple of libraries enabling this, for this prof of concept I've chosen [Pri.LongPath](https://github.com/peteraritchie/LongPath) which has drop in replacements for standard .Net classes i.e. `Path`, `DirectoryInfo`, `FileInfo`, etc.\r\n\r\nWhat would have been nice would be if we could have some kind of directive or similar for replacing/patching `IFileSystem` via an add-in at runtime. This could also enable support for other foreign file systems.\r\n\r\nWhat this PR adds is an new `Cake.Core.IO.LongPath` project/assembly with `Pri.LongPath` implementations of `IFileSystem`, `IFile` and `IDirectory`.\r\n\r\nIt also really adds a bad piece of code to patch the `IContext`/`IGlobber` file system via an `IContext.OmgTestFileSystemMethod(IFileSystem)` \r\n\r\nIn `.\\src\\Cake.Core.IO.LongPath\\` there's a `TestFileSystem.cake` that does a simple directory & globber test with standard .Net and then switches to `Cake.Core.IO.LongPath`.\r\n\r\nThe script first loads needed assemblies\r\n```csharp\r\n#r \"bin/Debug/Pri.LongPath.dll\"\r\n#r \"bin/Debug/Cake.Core.IO.LongPath.dll\"\r\n```\r\nThen defines some test data and tests\r\n```csharp\r\nvar binDir = Directory(\"bin/Debug\");\r\nvar testPaths = new DirectoryPath[]\r\n                    {\r\n                        \"so this is a quick and dirty test of handling long paths within Cake.\",\r\n                        \"using Pri.LongPath for Dotnet\",\r\n                        \"though it has to be very long path like a namespace\",\r\n                        \"Somtehing like Cake.Core.IO.LongPath\",\r\n                        \"would probably put it over the top.\"\r\n                    };\r\n\r\nAction<string, Action> test = (scope, action) =>\r\n{\r\n    try\r\n    {\r\n        Information(\"Test: {0}\", scope);\r\n        action();\r\n        Information(\"Success!\");\r\n    }\r\n    catch(Exception ex)\r\n    {\r\n        Error(\"Failed {0}\", ex);\r\n    }\r\n};\r\n\r\nAction testCreateDir = () => {\r\n    DirectoryPath current = binDir;\r\n    foreach(var testPath in testPaths)\r\n    {\r\n        Information(\"Start processing {0}\", testPath);\r\n        current = current.Combine(testPath);\r\n        if (!DirectoryExists(current))\r\n        {\r\n            CreateDirectory(current);\r\n        }\r\n    }\r\n};\r\n```\r\nAnd then executes the tests using standard .Net\r\n```csharp\r\ntest(\"Create dir using standard .Net\", testCreateDir);\r\ntest(\"Globber using standard .Net\", ()=>GetFiles(binDir.Path + \"/**/*.sln\"));\r\n```\r\nThen patches/changes `IFileSystem` to use `Cake.Core.IO.LongPath` implementation.\r\n```csharp\r\nContext.OmgTestFileSystemMethod(new Cake.Core.IO.LongPath.FileSystem());\r\n```\r\nAnd executes same tests.\r\n```csharp\r\ntest(\"Create dir using Pri.LongPath\", testCreateDir);\r\ntest(\"Globber using Pri.LongPath\", ()=>GetFiles(binDir.Path + \"/**/*.sln\"));\r\n```\r\nOutput first tests are\r\n```\r\nTest: Create dir using standard .Net\r\nStart processing so this is a quick and dirty test of handling long paths within Cake.\r\nStart processing using Pri.LongPath for Dotnet\r\nStart processing though it has to be very long path like a namespace\r\nStart processing Somtehing like Cake.Core.IO.LongPath\r\nStart processing would probably put it over the top.\r\nFailed System.IO.PathTooLongException: The specified path, file name, or both are too long. The fully qualified file name must be less than 260 characters, and the directory name must be less than 248 characters.\r\n   at System.IO.PathHelper.GetFullPathName()\r\n   at System.IO.Path.NormalizePath(String path, Boolean fullCheck, Int32 maxPathLength, Boolean expandShortPaths)\r\n   at System.IO.Path.GetFullPathInternal(String path)\r\n   at System.IO.DirectoryInfo.Init(String path, Boolean checkHost)\r\n   at Cake.Core.IO.Directory..ctor(DirectoryPath path) in c:\\temp\\dev\\gh\\devlead\\cake\\src\\Cake.Core\\IO\\Directory.cs:line 35\r\n   at Cake.Core.IO.FileSystem.GetDirectory(DirectoryPath path) in c:\\temp\\dev\\gh\\devlead\\cake\\src\\Cake.Core\\IO\\FileSystem.cs:line 25\r\n   at Cake.Common.IO.DirectoryAliases.DirectoryExists(ICakeContext context, DirectoryPath path) in c:\\temp\\dev\\gh\\devlead\\cake\\src\\Cake.Common\\IO\\DirectoryAliases.cs:line 377\r\n   at Submission#0.<.ctor>b__2()\r\n   at Submission#0.<.ctor>b__0(String scope, Action action)\r\nTest: Globber using standard .Net\r\nFailed System.IO.PathTooLongException: The specified path, file name, or both are too long. The fully qualified file name must be less than 260 characters, and the directory name must be less than 248 characters.\r\n   at System.IO.Path.NormalizePath(String path, Boolean fullCheck, Int32 maxPathLength, Boolean expandShortPaths)\r\n   at System.IO.Path.GetDirectoryName(String path)\r\n   at System.IO.FileSystemEnumerableIterator`1..ctor(String path, String originalUserPath, String searchPattern, SearchOption searchOption, SearchResultHandler`1 resultHandler, Boolean checkHost)\r\n   at System.IO.DirectoryInfo.InternalGetDirectories(String searchPattern, SearchOption searchOption)\r\n   at Cake.Core.IO.Directory.GetDirectories(String filter, SearchScope scope) in c:\\temp\\dev\\gh\\devlead\\cake\\src\\Cake.Core\\IO\\Directory.cs:line 51\r\n   at Cake.Core.DirectoryExtensions.GetDirectories(IDirectory directory, String filter, SearchScope scope, Func`2 predicate, Action`1 action) in c:\\temp\\dev\\gh\\devlead\\cake\\src\\Cake.Core\\Extensions\\DirectoryExtensions.cs:line 43\r\n   at Cake.Core.DirectoryExtensions.GetDirectories(IDirectory directory, String filter, SearchScope scope, Func`2 predicate) in c:\\temp\\dev\\gh\\devlead\\cake\\src\\Cake.Core\\Extensions\\DirectoryExtensions.cs:line 24\r\n   at Cake.Core.IO.Globber.Walk(DirectoryPath rootPath, Stack`1 segments, Func`2 predicate) in c:\\temp\\dev\\gh\\devlead\\cake\\src\\Cake.Core\\IO\\Globber.cs:line 172\r\n   at Cake.Core.IO.Globber.Walk(DirectoryPath rootPath, Stack`1 segments, Func`2 predicate) in c:\\temp\\dev\\gh\\devlead\\cake\\src\\Cake.Core\\IO\\Globber.cs:line 183\r\n   at Cake.Core.IO.Globber.Walk(DirectoryPath rootPath, Stack`1 segments, Func`2 predicate) in c:\\temp\\dev\\gh\\devlead\\cake\\src\\Cake.Core\\IO\\Globber.cs:line 183\r\n   at Cake.Core.IO.Globber.Walk(DirectoryPath rootPath, Stack`1 segments, Func`2 predicate) in c:\\temp\\dev\\gh\\devlead\\cake\\src\\Cake.Core\\IO\\Globber.cs:line 183\r\n   at Cake.Core.IO.Globber.Walk(DirectoryPath rootPath, Stack`1 segments, Func`2 predicate) in c:\\temp\\dev\\gh\\devlead\\cake\\src\\Cake.Core\\IO\\Globber.cs:line 183\r\n   at Cake.Core.IO.Globber.Walk(DirectoryPath rootPath, Stack`1 segments, Func`2 predicate) in c:\\temp\\dev\\gh\\devlead\\cake\\src\\Cake.Core\\IO\\Globber.cs:line 183\r\n   at Cake.Core.IO.Globber.Walk(DirectoryPath rootPath, Stack`1 segments, Func`2 predicate) in c:\\temp\\dev\\gh\\devlead\\cake\\src\\Cake.Core\\IO\\Globber.cs:line 183\r\n   at Cake.Core.IO.Globber.Walk(DirectoryPath rootPath, Stack`1 segments, Func`2 predicate) in c:\\temp\\dev\\gh\\devlead\\cake\\src\\Cake.Core\\IO\\Globber.cs:line 183\r\n   at Cake.Core.IO.Globber.Walk(DirectoryPath rootPath, Stack`1 segments, Func`2 predicate) in c:\\temp\\dev\\gh\\devlead\\cake\\src\\Cake.Core\\IO\\Globber.cs:line 183\r\n   at Cake.Core.IO.Globber.Walk(DirectoryPath rootPath, Stack`1 segments, Func`2 predicate) in c:\\temp\\dev\\gh\\devlead\\cake\\src\\Cake.Core\\IO\\Globber.cs:line 183\r\n   at Cake.Core.IO.Globber.Walk(DirectoryPath rootPath, Stack`1 segments, Func`2 predicate) in c:\\temp\\dev\\gh\\devlead\\cake\\src\\Cake.Core\\IO\\Globber.cs:line 183\r\n   at Cake.Core.IO.Globber.Walk(DirectoryPath rootPath, Stack`1 segments, Func`2 predicate) in c:\\temp\\dev\\gh\\devlead\\cake\\src\\Cake.Core\\IO\\Globber.cs:line 183\r\n   at Cake.Core.IO.Globber.Walk(DirectoryPath rootPath, Stack`1 segments, Func`2 predicate) in c:\\temp\\dev\\gh\\devlead\\cake\\src\\Cake.Core\\IO\\Globber.cs:line 183\r\n   at Cake.Core.IO.Globber.Walk(DirectoryPath rootPath, Stack`1 segments, Func`2 predicate) in c:\\temp\\dev\\gh\\devlead\\cake\\src\\Cake.Core\\IO\\Globber.cs:line 183\r\n   at Cake.Core.IO.Globber.Walk(DirectoryPath rootPath, Stack`1 segments, Func`2 predicate) in c:\\temp\\dev\\gh\\devlead\\cake\\src\\Cake.Core\\IO\\Globber.cs:line 183\r\n   at Cake.Core.IO.Globber.Walk(DirectoryPath rootPath, Stack`1 segments, Func`2 predicate) in c:\\temp\\dev\\gh\\devlead\\cake\\src\\Cake.Core\\IO\\Globber.cs:line 183\r\n   at Cake.Core.IO.Globber.Walk(DirectoryPath rootPath, Stack`1 segments, Func`2 predicate) in c:\\temp\\dev\\gh\\devlead\\cake\\src\\Cake.Core\\IO\\Globber.cs:line 183\r\n   at Cake.Core.IO.Globber.Walk(DirectoryPath rootPath, Stack`1 segments, Func`2 predicate) in c:\\temp\\dev\\gh\\devlead\\cake\\src\\Cake.Core\\IO\\Globber.cs:line 183\r\n   at Cake.Core.IO.Globber.Walk(DirectoryPath rootPath, Stack`1 segments, Func`2 predicate) in c:\\temp\\dev\\gh\\devlead\\cake\\src\\Cake.Core\\IO\\Globber.cs:line 183\r\n   at Cake.Core.IO.Globber.Walk(DirectoryPath rootPath, Stack`1 segments, Func`2 predicate) in c:\\temp\\dev\\gh\\devlead\\cake\\src\\Cake.Core\\IO\\Globber.cs:line 183\r\n   at Cake.Core.IO.Globber.Walk(DirectoryPath rootPath, Stack`1 segments, Func`2 predicate) in c:\\temp\\dev\\gh\\devlead\\cake\\src\\Cake.Core\\IO\\Globber.cs:line 183\r\n   at Cake.Core.IO.Globber.Walk(DirectoryPath rootPath, Stack`1 segments, Func`2 predicate) in c:\\temp\\dev\\gh\\devlead\\cake\\src\\Cake.Core\\IO\\Globber.cs:line 183\r\n   at Cake.Core.IO.Globber.Walk(DirectoryPath rootPath, Stack`1 segments, Func`2 predicate) in c:\\temp\\dev\\gh\\devlead\\cake\\src\\Cake.Core\\IO\\Globber.cs:line 183\r\n   at Cake.Core.IO.Globber.Walk(DirectoryPath rootPath, Stack`1 segments, Func`2 predicate) in c:\\temp\\dev\\gh\\devlead\\cake\\src\\Cake.Core\\IO\\Globber.cs:line 183\r\n   at Cake.Core.IO.Globber.Walk(DirectoryPath rootPath, Stack`1 segments, Func`2 predicate) in c:\\temp\\dev\\gh\\devlead\\cake\\src\\Cake.Core\\IO\\Globber.cs:line 183\r\n   at Cake.Core.IO.Globber.Walk(DirectoryPath rootPath, Stack`1 segments, Func`2 predicate) in c:\\temp\\dev\\gh\\devlead\\cake\\src\\Cake.Core\\IO\\Globber.cs:line 183\r\n   at Cake.Core.IO.Globber.Walk(DirectoryPath rootPath, Stack`1 segments, Func`2 predicate) in c:\\temp\\dev\\gh\\devlead\\cake\\src\\Cake.Core\\IO\\Globber.cs:line 183\r\n   at Cake.Core.IO.Globber.Walk(DirectoryPath rootPath, Stack`1 segments, Func`2 predicate) in c:\\temp\\dev\\gh\\devlead\\cake\\src\\Cake.Core\\IO\\Globber.cs:line 183\r\n   at Cake.Core.IO.Globber.Walk(DirectoryPath rootPath, Stack`1 segments, Func`2 predicate) in c:\\temp\\dev\\gh\\devlead\\cake\\src\\Cake.Core\\IO\\Globber.cs:line 183\r\n   at Cake.Core.IO.Globber.Walk(DirectoryPath rootPath, Stack`1 segments, Func`2 predicate) in c:\\temp\\dev\\gh\\devlead\\cake\\src\\Cake.Core\\IO\\Globber.cs:line 183\r\n   at Cake.Core.IO.Globber.Walk(DirectoryPath rootPath, Stack`1 segments, Func`2 predicate) in c:\\temp\\dev\\gh\\devlead\\cake\\src\\Cake.Core\\IO\\Globber.cs:line 183\r\n   at Cake.Core.IO.Globber.Walk(DirectoryPath rootPath, Stack`1 segments, Func`2 predicate) in c:\\temp\\dev\\gh\\devlead\\cake\\src\\Cake.Core\\IO\\Globber.cs:line 183\r\n   at Cake.Core.IO.Globber.Walk(DirectoryPath rootPath, Stack`1 segments, Func`2 predicate) in c:\\temp\\dev\\gh\\devlead\\cake\\src\\Cake.Core\\IO\\Globber.cs:line 183\r\n   at Cake.Core.IO.Globber.Walk(DirectoryPath rootPath, Stack`1 segments, Func`2 predicate) in c:\\temp\\dev\\gh\\devlead\\cake\\src\\Cake.Core\\IO\\Globber.cs:line 183\r\n   at Cake.Core.IO.Globber.Walk(DirectoryPath rootPath, Stack`1 segments, Func`2 predicate) in c:\\temp\\dev\\gh\\devlead\\cake\\src\\Cake.Core\\IO\\Globber.cs:line 183\r\n   at Cake.Core.IO.Globber.Match(String pattern, Func`2 predicate) in c:\\temp\\dev\\gh\\devlead\\cake\\src\\Cake.Core\\IO\\Globber.cs:line 99\r\n   at Cake.Core.IO.GlobberExtensions.Match(IGlobber globber, String pattern) in c:\\temp\\dev\\gh\\devlead\\cake\\src\\Cake.Core\\IO\\GlobberExtensions.cs:line 52\r\n   at Cake.Common.IO.GlobbingAliases.GetFiles(ICakeContext context, String pattern) in c:\\temp\\dev\\gh\\devlead\\cake\\src\\Cake.Common\\IO\\GlobbingAliases.cs:line 39\r\n   at Submission#0.GetFiles(String pattern)\r\n   at Submission#0.<.ctor>b__4()\r\n   at Submission#0.<.ctor>b__0(String scope, Action acti on)\r\n```\r\n\r\nA bit shorter output using `Cake.Core.IO.LongPath` \r\n```\r\nTest: Create dir using Pri.LongPath\r\nStart processing so this is a quick and dirty test of handling long paths within Cake.\r\nStart processing using Pri.LongPath for Dotnet\r\nStart processing though it has to be very long path like a namespace\r\nStart processing Somtehing like Cake.Core.IO.LongPath\r\nStart processing would probably put it over the top.\r\nSuccess!\r\nTest: Globber using Pri.LongPath\r\nSuccess!\r\n```\r\n\r\nThis functionality could really affect core, want a clean and good solution we could live with, so just leaving this PR for discussion & ideas. "},"comment":{"url":"https://api.github.com/repos/cake-build/cake/issues/comments/233611474","html_url":"https://github.com/cake-build/cake/pull/261#issuecomment-233611474","issue_url":"https://api.github.com/repos/cake-build/cake/issues/261","id":233611474,"user":{"login":"devlead","id":1647294,"avatar_url":"https://avatars.githubusercontent.com/u/1647294?v=3","gravatar_id":"","url":"https://api.github.com/users/devlead","html_url":"https://github.com/devlead","followers_url":"https://api.github.com/users/devlead/followers","following_url":"https://api.github.com/users/devlead/following{/other_user}","gists_url":"https://api.github.com/users/devlead/gists{/gist_id}","starred_url":"https://api.github.com/users/devlead/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/devlead/subscriptions","organizations_url":"https://api.github.com/users/devlead/orgs","repos_url":"https://api.github.com/users/devlead/repos","events_url":"https://api.github.com/users/devlead/events{/privacy}","received_events_url":"https://api.github.com/users/devlead/received_events","type":"User","site_admin":false},"created_at":"2016-07-19T12:02:57Z","updated_at":"2016-07-19T12:02:57Z","body":".Net 4.6 and CoreCLR comes with long name support, in this case it was an ugly hack, but would likely be better redone as it's own module and not incorporated into Cake core."}}
{"actor":{"display_login":"devlead"}}