diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..1ff0c42 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,63 @@ +############################################################################### +# Set default behavior to automatically normalize line endings. +############################################################################### +* text=auto + +############################################################################### +# Set default behavior for command prompt diff. +# +# This is need for earlier builds of msysgit that does not have it on by +# default for csharp files. +# Note: This is only used by command line +############################################################################### +#*.cs diff=csharp + +############################################################################### +# Set the merge driver for project and solution files +# +# Merging from the command prompt will add diff markers to the files if there +# are conflicts (Merging from VS is not affected by the settings below, in VS +# the diff markers are never inserted). Diff markers may cause the following +# file extensions to fail to load in VS. An alternative would be to treat +# these files as binary and thus will always conflict and require user +# intervention with every merge. To do so, just uncomment the entries below +############################################################################### +#*.sln merge=binary +#*.csproj merge=binary +#*.vbproj merge=binary +#*.vcxproj merge=binary +#*.vcproj merge=binary +#*.dbproj merge=binary +#*.fsproj merge=binary +#*.lsproj merge=binary +#*.wixproj merge=binary +#*.modelproj merge=binary +#*.sqlproj merge=binary +#*.wwaproj merge=binary + +############################################################################### +# behavior for image files +# +# image files are treated as binary by default. +############################################################################### +#*.jpg binary +#*.png binary +#*.gif binary + +############################################################################### +# diff behavior for common document formats +# +# Convert binary document formats to text before diffing them. This feature +# is only available from the command line. Turn it on by uncommenting the +# entries below. +############################################################################### +#*.doc diff=astextplain +#*.DOC diff=astextplain +#*.docx diff=astextplain +#*.DOCX diff=astextplain +#*.dot diff=astextplain +#*.DOT diff=astextplain +#*.pdf diff=astextplain +#*.PDF diff=astextplain +#*.rtf diff=astextplain +#*.RTF diff=astextplain diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 0000000..d8b1dff --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,29 @@ +*IF BUG, INCLUDE THIS PART:* + +### Steps to reproduce + +1. +2. +3. + +Platform: +.NET version: + +### Expected behaviour + +Tell us what should happen + +### Actual behaviour + +Tell us what happens instead +Can you also include a screen shot? + + + +*IF IT IS A NEW FEATURE REQUEST, INCLUDE THIS PART:* + +### Feature description + +Write a description of the feature. How should it work? How should it look? +Include some graphics if this could help! + diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..bc1c632 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,14 @@ +Fixes # . + +### Checklist + +- [ ] I have included examples or tests +- [ ] I have updated the change log +- [ ] I am listed in the CONTRIBUTORS file +- [ ] I have cleaned up the commit history (use rebase and squash) + +### Changes proposed in this pull request: + +- +- +- diff --git a/.gitignore b/.gitignore index 0fa3c20..c2c5710 100644 --- a/.gitignore +++ b/.gitignore @@ -121,4 +121,5 @@ Thumbs.db Desktop.ini # mstest test results -TestResults \ No newline at end of file +TestResults +/.vs diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..9f4ce2d --- /dev/null +++ b/AUTHORS @@ -0,0 +1,12 @@ +# This is the official list of authors for copyright purposes. +# This file is distinct from the CONTRIBUTORS file. +# See the latter for an explanation. + +# Names should be added to this file as +# Name or Organization +# The email address is not required for organizations. + +# Please keep the list sorted. +# Please notify the first person on the list to be added here. + +CatenaLogic diff --git a/CONTRIBUTORS b/CONTRIBUTORS new file mode 100644 index 0000000..694781d --- /dev/null +++ b/CONTRIBUTORS @@ -0,0 +1,15 @@ +# This is the official list of people who have contributed +# to this repository. +# The AUTHORS file lists the copyright holders; this file +# lists people. + +# People submitting code should be listed in this file (by email address). + +# Names should be added to this file like so: +# Name + +# Please keep the list sorted. + +Geert van Horrik +Wesley Eledui +Marek Fišera \ No newline at end of file diff --git a/LICENSE b/LICENSE index 0c8ff6f..a46c961 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2014 CatenaLogic +Copyright (c) 2014 - 2016 CatenaLogic Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index a9d532e..de69bff 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,7 @@ GitLink ========== [![Join the chat at https://gitter.im/GitTools/GitLink](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/GitTools/GitLink?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) - ![License](https://img.shields.io/github/license/gittools/gitlink.svg) -![NuGet downloads](https://img.shields.io/nuget/dt/gitlink.svg) ![Version](https://img.shields.io/nuget/v/gitlink.svg) ![Pre-release version](https://img.shields.io/nuget/vpre/gitlink.svg) ![Chocolatey count](https://img.shields.io/chocolatey/dt/gitlink.svg) @@ -18,11 +16,13 @@ GitLink let's users step through your code hosted on GitHub! **Help make .NET op -- -**Important note** +**Important** *GitLink* was formerly named *GitHubLink*. By adding support to more Git hosting services the name seemed not covering the whole package. The old GitHubLink packages on NuGet and Chocolatey will no longer be updated or maintained. --- +*Private git repositories* might be problematic. [More info](#source-stepping-returns-html). + +-- GitLink makes symbol servers obsolete which saves you both time with uploading source files with symbols and the user no longer has to specify custom symbol servers (such as symbolsource.org). @@ -46,11 +46,22 @@ When using GitLink, the user no longer has to specify symbol servers. The only r ![Enabling source server support](doc/images/visualstudio_symbolslocation.png) +* Verify that there is not a case mismatch in git folder names vs. references in the .csproj that was used during packaging. E.g. GitHub will not serve /Folder/Somefile.cs if Visual Studio requests /FOLdeR/Somefile.cs. + ## Source Stepping returns HTML If your repository is private, you are likely seeing the logon HTML from your git host. * Log onto your git host in Internet Explorer -* Purge your local symbol cache +* Purge your local symbol cache + +Note that this approach is not guaranteed to work. Visual Studio needs to authenticate to retrieve the source files +but does not ask the user for credentials to do so. There are ways to work around this, but no mechanism is currently +provided out-of-the-box in *GitLink*. + +Possible workarounds +* Include a mechanism in the pdb to retrieve credentials (using PowerShell and Windows credentials store) (see [#37](https://github.com/GitTools/GitLink/issues/37)) +* Use a proxy service that does not require authentication (see [#66](https://github.com/GitTools/GitLink/issues/66) and [Source server with Git repository](https://shonnlyga.wordpress.com/2016/05/28/source-server-with-git-repository)) + # Supported git providers @@ -218,6 +229,7 @@ Below is a list of projects already using GitLink (alphabetically ordered). - Catel - eXpand +- FakeItEasy - Fluent.Ribbon - GitLink - MahApps.Metro @@ -250,6 +262,8 @@ Below is a list of projects already using GitLink (alphabetically ordered). - QBitNinja - ReactiveUI - Romantic Web +- Roslyn +- Serenity - xUnit.net - xUnit.net Visual Studio Runner diff --git a/deployment/Chocolatey/template/GitHubLink/GitHubLink.nuspec b/deployment/Chocolatey/template/GitHubLink/GitHubLink.nuspec index 906a7cd..07d91ae 100644 --- a/deployment/Chocolatey/template/GitHubLink/GitHubLink.nuspec +++ b/deployment/Chocolatey/template/GitHubLink/GitHubLink.nuspec @@ -16,9 +16,9 @@ source symbol symbols server sourcelink github bitbucket git stepping debugging en-US - https://github.com/CatenaLogic/GitLink/ - https://github.com/CatenaLogic/GitLink/blob/develop/LICENSE - https://raw.githubusercontent.com/CatenaLogic/GitLink/develop/design/logo/logo_64.png + https://github.com/GitTools/GitLink/ + https://github.com/GitTools/GitLink/blob/develop/LICENSE + https://raw.githubusercontent.com/GitTools/GitLink/develop/design/logo/logo_64.png diff --git a/deployment/Chocolatey/template/GitHubLink/tools/LICENSE.txt b/deployment/Chocolatey/template/GitHubLink/tools/LICENSE.txt new file mode 100644 index 0000000..a46c961 --- /dev/null +++ b/deployment/Chocolatey/template/GitHubLink/tools/LICENSE.txt @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 - 2016 CatenaLogic + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/deployment/Chocolatey/template/GitLink/GitLink.nuspec b/deployment/Chocolatey/template/GitLink/GitLink.nuspec index 658b187..2b6ec9f 100644 --- a/deployment/Chocolatey/template/GitLink/GitLink.nuspec +++ b/deployment/Chocolatey/template/GitLink/GitLink.nuspec @@ -17,8 +17,8 @@ gitlink githublinksource symbol symbols server sourcelink github bitbucket git stepping debugging en-US - https://github.com/CatenaLogic/GitLink/ - https://github.com/CatenaLogic/GitLink/blob/develop/LICENSE - https://raw.githubusercontent.com/CatenaLogic/GitLink/develop/design/logo/logo_128.png + https://github.com/GitTools/GitLink/ + https://github.com/GitTools/GitLink/blob/develop/LICENSE + https://raw.githubusercontent.com/GitTools/GitLink/develop/design/logo/logo_128.png \ No newline at end of file diff --git a/deployment/Chocolatey/template/GitLink/tools/LICENSE.txt b/deployment/Chocolatey/template/GitLink/tools/LICENSE.txt new file mode 100644 index 0000000..a46c961 --- /dev/null +++ b/deployment/Chocolatey/template/GitLink/tools/LICENSE.txt @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 - 2016 CatenaLogic + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/deployment/FinalBuilder/GitLink.CreatePackages.fbp7 b/deployment/FinalBuilder/GitLink.CreatePackages.fbp7 index 26d6cb3..2fe26a3 100644 Binary files a/deployment/FinalBuilder/GitLink.CreatePackages.fbp7 and b/deployment/FinalBuilder/GitLink.CreatePackages.fbp7 differ diff --git a/deployment/NuGet/template/GitHubLink/GitHubLink.nuspec b/deployment/NuGet/template/GitHubLink/GitHubLink.nuspec index 5d1ff8e..d261a25 100644 --- a/deployment/NuGet/template/GitHubLink/GitHubLink.nuspec +++ b/deployment/NuGet/template/GitHubLink/GitHubLink.nuspec @@ -5,6 +5,7 @@ [VERSION] GitHubLink GeertvanHorrik + true ** Note: this is a maintenance package, GitHubLink is replaced by GitLink ** @@ -16,9 +17,9 @@ source symbol symbols server sourcelink github bitbucket git stepping debugging en-US - https://github.com/CatenaLogic/GitLink/ - https://github.com/CatenaLogic/GitLink/blob/develop/LICENSE - https://raw.githubusercontent.com/CatenaLogic/GitLink/develop/design/logo/logo_64.png + https://github.com/GitTools/GitLink/ + https://github.com/GitTools/GitLink/blob/develop/LICENSE + https://raw.githubusercontent.com/GitTools/GitLink/develop/design/logo/logo_64.png diff --git a/deployment/NuGet/template/GitLink/GitLink.nuspec b/deployment/NuGet/template/GitLink/GitLink.nuspec index f232d93..2aef4b3 100644 --- a/deployment/NuGet/template/GitLink/GitLink.nuspec +++ b/deployment/NuGet/template/GitLink/GitLink.nuspec @@ -5,6 +5,7 @@ [VERSION] GitLink GeertvanHorrik + true GitLink let's users step through your code hosted on any Git hosting service! This makes symbol servers obsolete which saves you both time @@ -17,8 +18,8 @@ gitlink githublink source symbol symbols server sourcelink github bitbucket git stepping debugging en-US - https://github.com/CatenaLogic/GitLink/ - https://github.com/CatenaLogic/GitLink/blob/develop/LICENSE - https://raw.githubusercontent.com/CatenaLogic/GitLink/develop/design/logo/logo_64.png + https://github.com/GitTools/GitLink/ + https://github.com/GitTools/GitLink/blob/develop/LICENSE + https://raw.githubusercontent.com/GitTools/GitLink/develop/design/logo/logo_64.png \ No newline at end of file diff --git a/deployment/NuGet/template/GitLinkTask/Build/dotnet/GitLink.targets b/deployment/NuGet/template/GitLinkTask/Build/dotnet/GitLink.targets new file mode 100644 index 0000000..c4e1f49 --- /dev/null +++ b/deployment/NuGet/template/GitLinkTask/Build/dotnet/GitLink.targets @@ -0,0 +1,11 @@ + + + + + + + + + \ No newline at end of file diff --git a/deployment/NuGet/template/GitLinkTask/GitLinkTask.nuspec b/deployment/NuGet/template/GitLinkTask/GitLinkTask.nuspec new file mode 100644 index 0000000..e00e962 --- /dev/null +++ b/deployment/NuGet/template/GitLinkTask/GitLinkTask.nuspec @@ -0,0 +1,25 @@ + + + + gitlinktask + [VERSION] + GitLinkTask + GeertvanHorrik + true + + + GitLink let's users step through your code hosted on any Git hosting service! This makes symbol servers obsolete which saves you both time + with uploading source files with symbols and the user no longer has to specify custom symbol servers (such as symbolsource.org). + + + + + + gitlink githublink source symbol symbols server sourcelink github bitbucket git stepping debugging + + en-US + https://github.com/GitTools/GitLink/ + https://github.com/GitTools/GitLink/blob/develop/LICENSE + https://raw.githubusercontent.com/GitTools/GitLink/develop/design/logo/logo_64.png + + \ No newline at end of file diff --git a/src/GitLink.Tests/GitLink.Tests.csproj b/src/GitLink.Tests/GitLink.Tests.csproj index 337ceeb..5f8601f 100644 --- a/src/GitLink.Tests/GitLink.Tests.csproj +++ b/src/GitLink.Tests/GitLink.Tests.csproj @@ -52,9 +52,8 @@ ..\..\lib\ApprovalUtilities.3.0.8\lib\net45\ApprovalUtilities.Net45.dll True - - False - ..\..\lib\Catel.Core.4.3.0\lib\net45\Catel.Core.dll + + ..\..\lib\Catel.Core.4.5.3\lib\net45\Catel.Core.dll True @@ -67,6 +66,7 @@ ..\..\lib\LibGit2Sharp.0.21.0.176\lib\net40\LibGit2Sharp.dll True + ..\..\lib\NUnit.2.6.4\lib\nunit.framework.dll @@ -90,6 +90,7 @@ + @@ -97,6 +98,8 @@ + + @@ -110,7 +113,20 @@ + + Always + + + Always + + + Always + + + Always + + diff --git a/src/GitLink.Tests/ProjectHelperFacts.cs b/src/GitLink.Tests/ProjectHelperFacts.cs new file mode 100644 index 0000000..b153332 --- /dev/null +++ b/src/GitLink.Tests/ProjectHelperFacts.cs @@ -0,0 +1,67 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) 2014 - 2016 CatenaLogic. All rights reserved. +// +// -------------------------------------------------------------------------------------------------------------------- +namespace GitLink.Tests +{ + using System.IO; + using System.Linq; + using System.Reflection; + using NUnit.Framework; + + [TestFixture] + public class ProjectHelperFacts + { + // Full path with executing assembly required for NUnit 3+ + private const string SolutionFile = @"TestSolution\TestSolution.sln"; + // private static readonly string SolutionFile = Path.Combine( + // Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), + // @"TestSolution\TestSolution.sln"); + + + [Test] + public void GettingProjectsFromSolution() + { + Assert.AreEqual(3, ProjectHelper.GetProjects(SolutionFile, Configuration.Debug, Platform.AnyCpu).Count()); + } + + [Test] + public void GettingProjectsFromSolution_SkipsProjectNotSelectedForPlatform() + { + var projects = ProjectHelper.GetProjects(SolutionFile, Configuration.Debug, Platform.x64).ToList(); + + Assert.AreEqual(2, projects.Count); + Assert.False(projects.Any(c => c.GetProjectName() == "BuiltInAnyCpuOnly")); + } + + [Test] + public void GettingProjectsFromSolution_SkipsProjectNotSelectedForConfiguration() + { + var projects = ProjectHelper.GetProjects(SolutionFile, Configuration.Release, Platform.AnyCpu).ToList(); + + Assert.AreEqual(2, projects.Count); + Assert.False(projects.Any(c => c.GetProjectName() == "BuiltInDebugOnly")); + } + + [Test] + public void GettingProjectsFromSolution_SkipsProjectNotSelectedForEitherConfigurationOrPlatform() + { + var project = ProjectHelper.GetProjects(SolutionFile, Configuration.Release, Platform.x64).Single(); + + Assert.AreEqual("BuiltAlways", project.GetProjectName()); + } + + private static class Configuration + { + public const string Debug = "Debug"; + public const string Release = "Release"; + } + + private static class Platform + { + public const string AnyCpu = "Any CPU"; + public const string x64 = "x64"; + } + } +} \ No newline at end of file diff --git a/src/GitLink.Tests/Providers/UncProviderFacts.cs b/src/GitLink.Tests/Providers/UncProviderFacts.cs new file mode 100644 index 0000000..bbd79bd --- /dev/null +++ b/src/GitLink.Tests/Providers/UncProviderFacts.cs @@ -0,0 +1,49 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) 2014 - 2016 CatenaLogic. All rights reserved. +// +// -------------------------------------------------------------------------------------------------------------------- + + +namespace GitLink.Tests.Providers +{ + using GitLink.Providers; + using NUnit.Framework; + + /// + /// Test cases for . + /// + public class UncProviderFacts + { + [TestFixture] + public class TheInitialization + { + [TestCase(@"//home/repo/{filename}", true)] + [TestCase(@"//home/repo/{revision}/{filename}", true)] + [TestCase(@"\\home\repo\{filename}", true)] + [TestCase(@"\\home\repo\{revision}\{filename}", true)] + [TestCase(@"//home/repo/", false)] + [TestCase(@"\\home\repo\", false)] + public void CorrectlyValidatesUncPath(string path, bool expectedValue) + { + var provider = new UncProvider(); + var valid = provider.Initialize(path); + + Assert.AreEqual(expectedValue, valid); + } + + [TestCase(@"//home/repo/{filename}")] + [TestCase(@"//home/repo/{revision}/{filename}")] + [TestCase(@"\\home\repo\{filename}")] + [TestCase(@"\\home\repo\{revision}\{filename}")] + public void CorrenctlyReplacesPlaceHolders(string path) + { + var provider = new UncProvider(); + Assert.IsTrue(provider.Initialize(path)); + + string expectedPath = path.Replace("{filename}", "%var2%").Replace("{revision}", "{0}"); + Assert.AreEqual(expectedPath, provider.RawGitUrl); + } + } + } +} diff --git a/src/GitLink.Tests/Providers/VisualStudioTeamServicesProviderFacts.cs b/src/GitLink.Tests/Providers/VisualStudioTeamServicesProviderFacts.cs new file mode 100644 index 0000000..eeaf596 --- /dev/null +++ b/src/GitLink.Tests/Providers/VisualStudioTeamServicesProviderFacts.cs @@ -0,0 +1,95 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) 2014 - 2014 CatenaLogic. All rights reserved. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace GitLink.Tests.Providers +{ + using GitLink.Providers; + using NUnit.Framework; + + public class VisualStudioTeamServicesProviderFacts + { + [TestFixture] + public class TheVisualStudioTeamServicesProviderInitialization + { + [TestCase] + public void ReturnsValidInitialization() + { + var provider = new VisualStudioTeamServicesProvider(); + var valid = provider.Initialize("https://my-account.visualstudio.com/_git/main-repo"); + + Assert.IsTrue(valid); + } + + [TestCase] + public void ReturnsInValidInitialization() + { + var provider = new VisualStudioTeamServicesProvider(); + var valid = provider.Initialize("https://github.com/CatenaLogic/GitLink"); + + Assert.IsFalse(valid); + } + + [TestFixture] + public class TheVisualStudioTeamServicesProviderProperties + { + [TestCase] + public void ReturnsValidCompany() + { + var provider = new VisualStudioTeamServicesProvider(); + provider.Initialize("https://CatenaLogic.visualstudio.com/_git/main-repo"); + + Assert.AreEqual("CatenaLogic", provider.CompanyName); + } + + [TestCase] + public void ReturnsValidCompanyUrl() + { + var provider = new VisualStudioTeamServicesProvider(); + provider.Initialize("https://CatenaLogic.visualstudio.com/_git/main-repo"); + + Assert.AreEqual("https://CatenaLogic.visualstudio.com/", provider.CompanyUrl); + } + + [TestCase] + public void ReturnsValidProject() + { + var provider = new VisualStudioTeamServicesProvider(); + provider.Initialize("https://CatenaLogic.visualstudio.com/_git/main-repo"); + + Assert.AreEqual("main-repo", provider.ProjectName); + } + + [TestCase] + public void ReturnsValidProject2() + { + var provider = new VisualStudioTeamServicesProvider(); + provider.Initialize("https://CatenaLogic.visualstudio.com/BigProject/_git/main-repo"); + + Assert.AreEqual("BigProject", provider.ProjectName); + } + + [TestCase] + public void ReturnsValidRepositoryName() + { + var provider = new VisualStudioTeamServicesProvider(); + provider.Initialize("https://CatenaLogic.visualstudio.com/Project/_git/main-repo"); + + Assert.AreEqual("main-repo", provider.ProjectUrl); + } + + [TestCase] + public void ReturnsValidRepositoryNameWhenContainsPeriod() + { + var provider = new VisualStudioTeamServicesProvider(); + provider.Initialize("https://CatenaLogic.visualstudio.com/Big.Project/_git/main.repo"); + + Assert.AreEqual("main.repo", provider.ProjectUrl); + } + + } + } + } +} diff --git a/src/GitLink.Tests/TestSolution/BuiltAlways/BuiltAlways.csproj b/src/GitLink.Tests/TestSolution/BuiltAlways/BuiltAlways.csproj new file mode 100644 index 0000000..77ce902 --- /dev/null +++ b/src/GitLink.Tests/TestSolution/BuiltAlways/BuiltAlways.csproj @@ -0,0 +1,71 @@ + + + + + Debug + AnyCPU + {EA6EEEA6-E220-4F8E-AEF9-54B4FE4EAFAE} + Library + Properties + BuiltAlways + BuiltAlways + v4.5 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + true + bin\x64\Debug\ + DEBUG;TRACE + full + x64 + prompt + MinimumRecommendedRules.ruleset + + + bin\x64\Release\ + TRACE + true + pdbonly + x64 + prompt + MinimumRecommendedRules.ruleset + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/GitLink.Tests/TestSolution/BuiltInAnyCpuOnly/BuiltInAnyCpuOnly.csproj b/src/GitLink.Tests/TestSolution/BuiltInAnyCpuOnly/BuiltInAnyCpuOnly.csproj new file mode 100644 index 0000000..8f3cc20 --- /dev/null +++ b/src/GitLink.Tests/TestSolution/BuiltInAnyCpuOnly/BuiltInAnyCpuOnly.csproj @@ -0,0 +1,71 @@ + + + + + Debug + AnyCPU + {79250F2E-A3C3-4F3E-A05A-9B3F0A3E4DB8} + Library + Properties + BuiltInAnyCpuOnly + BuiltInAnyCpuOnly + v4.5 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + true + bin\x64\Debug\ + DEBUG;TRACE + full + x64 + prompt + MinimumRecommendedRules.ruleset + + + bin\x64\Release\ + TRACE + true + pdbonly + x64 + prompt + MinimumRecommendedRules.ruleset + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/GitLink.Tests/TestSolution/BuiltInDebugOnly/BuiltInDebugOnly.csproj b/src/GitLink.Tests/TestSolution/BuiltInDebugOnly/BuiltInDebugOnly.csproj new file mode 100644 index 0000000..3136ea3 --- /dev/null +++ b/src/GitLink.Tests/TestSolution/BuiltInDebugOnly/BuiltInDebugOnly.csproj @@ -0,0 +1,71 @@ + + + + + Debug + AnyCPU + {EAF71B49-AB0C-4298-9280-E508A1D95FC7} + Library + Properties + BuiltInDebugOnly + BuiltInDebugOnly + v4.5 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + true + bin\x64\Debug\ + DEBUG;TRACE + full + x64 + prompt + MinimumRecommendedRules.ruleset + + + bin\x64\Release\ + TRACE + true + pdbonly + x64 + prompt + MinimumRecommendedRules.ruleset + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/GitLink.Tests/TestSolution/TestSolution.sln b/src/GitLink.Tests/TestSolution/TestSolution.sln new file mode 100644 index 0000000..229dd39 --- /dev/null +++ b/src/GitLink.Tests/TestSolution/TestSolution.sln @@ -0,0 +1,44 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.23107.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BuiltAlways", "BuiltAlways\BuiltAlways.csproj", "{EA6EEEA6-E220-4F8E-AEF9-54B4FE4EAFAE}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BuiltInDebugOnly", "BuiltInDebugOnly\BuiltInDebugOnly.csproj", "{EAF71B49-AB0C-4298-9280-E508A1D95FC7}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BuiltInAnyCpuOnly", "BuiltInAnyCpuOnly\BuiltInAnyCpuOnly.csproj", "{79250F2E-A3C3-4F3E-A05A-9B3F0A3E4DB8}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {EA6EEEA6-E220-4F8E-AEF9-54B4FE4EAFAE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EA6EEEA6-E220-4F8E-AEF9-54B4FE4EAFAE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EA6EEEA6-E220-4F8E-AEF9-54B4FE4EAFAE}.Debug|x64.ActiveCfg = Debug|x64 + {EA6EEEA6-E220-4F8E-AEF9-54B4FE4EAFAE}.Debug|x64.Build.0 = Debug|x64 + {EA6EEEA6-E220-4F8E-AEF9-54B4FE4EAFAE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EA6EEEA6-E220-4F8E-AEF9-54B4FE4EAFAE}.Release|Any CPU.Build.0 = Release|Any CPU + {EA6EEEA6-E220-4F8E-AEF9-54B4FE4EAFAE}.Release|x64.ActiveCfg = Release|x64 + {EA6EEEA6-E220-4F8E-AEF9-54B4FE4EAFAE}.Release|x64.Build.0 = Release|x64 + {EAF71B49-AB0C-4298-9280-E508A1D95FC7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EAF71B49-AB0C-4298-9280-E508A1D95FC7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EAF71B49-AB0C-4298-9280-E508A1D95FC7}.Debug|x64.ActiveCfg = Debug|x64 + {EAF71B49-AB0C-4298-9280-E508A1D95FC7}.Debug|x64.Build.0 = Debug|x64 + {EAF71B49-AB0C-4298-9280-E508A1D95FC7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EAF71B49-AB0C-4298-9280-E508A1D95FC7}.Release|x64.ActiveCfg = Release|x64 + {79250F2E-A3C3-4F3E-A05A-9B3F0A3E4DB8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {79250F2E-A3C3-4F3E-A05A-9B3F0A3E4DB8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {79250F2E-A3C3-4F3E-A05A-9B3F0A3E4DB8}.Debug|x64.ActiveCfg = Debug|x64 + {79250F2E-A3C3-4F3E-A05A-9B3F0A3E4DB8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {79250F2E-A3C3-4F3E-A05A-9B3F0A3E4DB8}.Release|Any CPU.Build.0 = Release|Any CPU + {79250F2E-A3C3-4F3E-A05A-9B3F0A3E4DB8}.Release|x64.ActiveCfg = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/GitLink.Tests/packages.config b/src/GitLink.Tests/packages.config index 7efb115..c1094b2 100644 --- a/src/GitLink.Tests/packages.config +++ b/src/GitLink.Tests/packages.config @@ -2,7 +2,7 @@ - + diff --git a/src/GitLink.sln b/src/GitLink.sln index 1fd8d69..5b2c4a1 100644 --- a/src/GitLink.sln +++ b/src/GitLink.sln @@ -1,68 +1,26 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0.30723.0 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GitLink", "GitLink\GitLink.csproj", "{D68ADD77-913F-46D2-9A4F-5CC71C4718D8}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{A6694C2C-1A8A-49F0-B404-1BBB4D081808}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "lib", "lib", "{16B74389-D647-4CF8-90D3-38E5D5256BC5}" - ProjectSection(SolutionItems) = preProject - ..\lib\repositories.config = ..\lib\repositories.config - ..\lib\RestorePackages.bat = ..\lib\RestorePackages.bat - EndProjectSection -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "deployment", "deployment", "{99836492-466A-44E3-A92B-72CE3744F61C}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "doc", "doc", "{88214CBE-4B92-4E22-8854-CC21543EE703}" - ProjectSection(SolutionItems) = preProject - ..\doc\history.txt = ..\doc\history.txt - EndProjectSection -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Core", "Core", "{A5FCE4FA-083A-4814-B38C-2AED9C37647F}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{D435DFD9-F741-4FCA-A65A-28B7D251983D}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GitLink.Tests", "GitLink.Tests\GitLink.Tests.csproj", "{ED2B9579-59D2-40F2-BC5E-F4DC3DAB9A56}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "NuGet", "NuGet", "{2A773B1D-106C-4583-8021-9AC0BB3E5408}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "design", "design", "{0A177E6C-1C04-416D-9473-82EE9A9ACFB4}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "FinalBuilder", "FinalBuilder", "{8EABCB0D-E792-4700-BDF9-E488CF2AB4A2}" - ProjectSection(SolutionItems) = preProject - ..\deployment\FinalBuilder\GitLink.CreatePackages.fbp7 = ..\deployment\FinalBuilder\GitLink.CreatePackages.fbp7 - EndProjectSection -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Chocolatey", "Chocolatey", "{9765817D-03DD-4879-8A43-CB3086B6743F}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Task", "Task", "{EA23F854-946E-4B2A-B3D6-03456D0B8FC5}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "template", "template", "{BEEC31FD-7021-47BA-AB54-A5B4C7C23F7E}" - ProjectSection(SolutionItems) = preProject - ..\deployment\Chocolatey\template\GitLink.nuspec = ..\deployment\Chocolatey\template\GitLink.nuspec - EndProjectSection +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GitLinkTask", "GitLinkTask\GitLinkTask.csproj", "{38BFDD5A-8CC2-43B8-96CE-BC572E3DFEF5}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "template", "template", "{75559B70-907C-4375-A44B-8195B5027B3C}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "misc", "misc", "{FEF533E8-3081-4913-8375-281F8670AF23}" ProjectSection(SolutionItems) = preProject - ..\deployment\NuGet\template\GitLink.nuspec = ..\deployment\NuGet\template\GitLink.nuspec - EndProjectSection -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tools", "tools", "{5BC2D5A6-10B0-425B-BAB3-5AB3DFDC24B2}" - ProjectSection(SolutionItems) = preProject - ..\deployment\Chocolatey\template\tools\chocolateyInstall.ps1 = ..\deployment\Chocolatey\template\tools\chocolateyInstall.ps1 - ..\deployment\Chocolatey\template\tools\chocolateyUninstall.ps1 = ..\deployment\Chocolatey\template\tools\chocolateyUninstall.ps1 - EndProjectSection -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "logo", "logo", "{CADD04D7-0CC0-48BB-B3EC-F82E34895982}" - ProjectSection(SolutionItems) = preProject - ..\design\logo\logo.ico = ..\design\logo\logo.ico - ..\design\logo\logo_1024.png = ..\design\logo\logo_1024.png - ..\design\logo\logo_128.png = ..\design\logo\logo_128.png - ..\design\logo\logo_16.png = ..\design\logo\logo_16.png - ..\design\logo\logo_256.png = ..\design\logo\logo_256.png - ..\design\logo\logo_32.png = ..\design\logo\logo_32.png - ..\design\logo\logo_512.png = ..\design\logo\logo_512.png - ..\design\logo\logo_64.png = ..\design\logo\logo_64.png + ..\doc\history.txt = ..\doc\history.txt + SolutionAssemblyInfo.cs = SolutionAssemblyInfo.cs EndProjectSection EndProject Global @@ -79,6 +37,10 @@ Global {ED2B9579-59D2-40F2-BC5E-F4DC3DAB9A56}.Debug|Any CPU.Build.0 = Debug|Any CPU {ED2B9579-59D2-40F2-BC5E-F4DC3DAB9A56}.Release|Any CPU.ActiveCfg = Release|Any CPU {ED2B9579-59D2-40F2-BC5E-F4DC3DAB9A56}.Release|Any CPU.Build.0 = Release|Any CPU + {38BFDD5A-8CC2-43B8-96CE-BC572E3DFEF5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {38BFDD5A-8CC2-43B8-96CE-BC572E3DFEF5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {38BFDD5A-8CC2-43B8-96CE-BC572E3DFEF5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {38BFDD5A-8CC2-43B8-96CE-BC572E3DFEF5}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -88,12 +50,7 @@ Global {A5FCE4FA-083A-4814-B38C-2AED9C37647F} = {A6694C2C-1A8A-49F0-B404-1BBB4D081808} {D435DFD9-F741-4FCA-A65A-28B7D251983D} = {A6694C2C-1A8A-49F0-B404-1BBB4D081808} {ED2B9579-59D2-40F2-BC5E-F4DC3DAB9A56} = {D435DFD9-F741-4FCA-A65A-28B7D251983D} - {2A773B1D-106C-4583-8021-9AC0BB3E5408} = {99836492-466A-44E3-A92B-72CE3744F61C} - {8EABCB0D-E792-4700-BDF9-E488CF2AB4A2} = {99836492-466A-44E3-A92B-72CE3744F61C} - {9765817D-03DD-4879-8A43-CB3086B6743F} = {99836492-466A-44E3-A92B-72CE3744F61C} - {BEEC31FD-7021-47BA-AB54-A5B4C7C23F7E} = {9765817D-03DD-4879-8A43-CB3086B6743F} - {75559B70-907C-4375-A44B-8195B5027B3C} = {2A773B1D-106C-4583-8021-9AC0BB3E5408} - {5BC2D5A6-10B0-425B-BAB3-5AB3DFDC24B2} = {BEEC31FD-7021-47BA-AB54-A5B4C7C23F7E} - {CADD04D7-0CC0-48BB-B3EC-F82E34895982} = {0A177E6C-1C04-416D-9473-82EE9A9ACFB4} + {EA23F854-946E-4B2A-B3D6-03456D0B8FC5} = {A6694C2C-1A8A-49F0-B404-1BBB4D081808} + {38BFDD5A-8CC2-43B8-96CE-BC572E3DFEF5} = {EA23F854-946E-4B2A-B3D6-03456D0B8FC5} EndGlobalSection EndGlobal diff --git a/src/GitLink/ArgumentParser.cs b/src/GitLink/ArgumentParser.cs index 97bcf44..ffe4d7f 100644 --- a/src/GitLink/ArgumentParser.cs +++ b/src/GitLink/ArgumentParser.cs @@ -1,248 +1,261 @@ -// -------------------------------------------------------------------------------------------------------------------- -// -// Copyright (c) 2014 - 2014 CatenaLogic. All rights reserved. -// -// -------------------------------------------------------------------------------------------------------------------- - - -namespace GitLink -{ - using System; - using System.Collections.Generic; - using System.Linq; - using Catel.Collections; - using Catel.Logging; - using GitLink.Providers; - using GitTools; - using GitTools.Git; - using LibGit2Sharp; - - public static class ArgumentParser - { - private static readonly ILog Log = LogManager.GetCurrentClassLogger(); - - public static Context ParseArguments(string commandLineArguments) - { - return ParseArguments(commandLineArguments.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).ToList(), - new ProviderManager()); - } - - public static Context ParseArguments(params string[] commandLineArguments) - { - return ParseArguments(commandLineArguments.ToList(), new ProviderManager()); - } - - public static Context ParseArguments(List commandLineArguments, IProviderManager providerManager) - { - var context = new Context(providerManager); - - if (commandLineArguments.Count == 0) - { - context.IsHelp = true; - return context; - } - - var firstArgument = commandLineArguments.First(); - if (IsHelp(firstArgument)) - { - context.IsHelp = true; - return context; - } - - if (commandLineArguments.Count < 3 && commandLineArguments.Count != 1) - { - throw Log.ErrorAndCreateException("Invalid number of arguments"); - } - - context.SolutionDirectory = firstArgument; - - var namedArguments = commandLineArguments.Skip(1).ToList(); - for (var index = 0; index < namedArguments.Count; index++) - { - var name = namedArguments[index]; - - // First check everything without values - if (IsSwitch("debug", name)) - { - context.IsDebug = true; - continue; - } - - if (IsSwitch("errorsaswarnings", name)) - { - context.ErrorsAsWarnings = true; - continue; - } - - if (IsSwitch("skipverify", name)) - { - context.SkipVerify = true; - continue; - } - - if (IsSwitch("powershell", name)) - { - context.DownloadWithPowershell = true; - continue; - } - - // After this point, all arguments should have a value - index++; - var valueInfo = GetValue(namedArguments, index); - var value = valueInfo.Key; - index = index + (valueInfo.Value - 1); - - if (IsSwitch("l", name)) - { - context.LogFile = value; - continue; - } - - if (IsSwitch("c", name)) - { - context.ConfigurationName = value; - continue; - } - - if (IsSwitch("p", name)) - { - context.PlatformName = value; - continue; - } - - if (IsSwitch("u", name)) - { - context.TargetUrl = value; - continue; - } - - if (IsSwitch("b", name)) - { - context.TargetBranch = value; - continue; - } - - if (IsSwitch("s", name)) - { - context.ShaHash = value; - continue; - } - - if (IsSwitch("f", name)) - { - context.SolutionFile = value; - continue; - } - - if (IsSwitch("d", name)) - { - context.PdbFilesDirectory = value; - continue; - } - - if (IsSwitch("include", name)) - { - context.IncludedProjects.AddRange(value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Trim())); - continue; - } - - if (IsSwitch("ignore", name)) - { - context.IgnoredProjects.AddRange(value.Split(new []{ ',' }, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Trim())); - continue; - } - - throw Log.ErrorAndCreateException("Could not parse command line parameter '{0}'.", name); - } - - if (string.IsNullOrEmpty(context.TargetUrl)) - { - Log.Info("No target url was specified, trying to determine the target url automatically"); - - var gitDir = GitDirFinder.TreeWalkForGitDir(context.SolutionDirectory); - if (gitDir != null) - { - using (var repo = RepositoryLoader.GetRepo(gitDir)) - { - var currentBranch = repo.Head; - - if (string.IsNullOrEmpty(context.ShaHash)) - { - context.ShaHash = currentBranch.Tip.Sha; - } - - if (currentBranch.Remote == null || currentBranch.IsDetachedHead()) - { - currentBranch = repo.GetBranchesContainingCommit(context.ShaHash).FirstOrDefault(b => b.Remote != null); - } - - if (currentBranch != null && currentBranch.Remote != null) - { - var url = currentBranch.Remote.Url; - if (url.StartsWith("https://")) - { - context.TargetUrl = url.OptimizeUrl(); - - Log.Info("Automatically determine target url '{0}'", context.TargetUrl); - } - } - } - } - } - - if (!string.IsNullOrEmpty(context.TargetUrl)) - { - context.Provider = providerManager.GetProvider(context.TargetUrl); - } - - return context; - } - - private static KeyValuePair GetValue(List arguments, int index) - { - var totalCounter = 1; - - var value = arguments[index]; - - while (value.StartsWith("\"")) - { - if (value.EndsWith("\"")) - { - break; - } - - index++; - value += " " + arguments[index]; - - totalCounter++; - } - - value = value.Trim('\"'); - - return new KeyValuePair(value, totalCounter); - } - - private static bool IsSwitch(string switchName, string value) - { - if (value.StartsWith("-")) - { - value = value.Remove(0, 1); - } - - if (value.StartsWith("/")) - { - value = value.Remove(0, 1); - } - - return (string.Equals(switchName, value)); - } - - private static bool IsHelp(string singleArgument) - { - return (singleArgument == "?") || - IsSwitch("h", singleArgument) || - IsSwitch("help", singleArgument) || - IsSwitch("?", singleArgument); - } - } +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) 2014 - 2014 CatenaLogic. All rights reserved. +// +// -------------------------------------------------------------------------------------------------------------------- + + +namespace GitLink +{ + using System; + using System.Collections.Generic; + using System.Linq; + using Catel.Collections; + using Catel.Logging; + using GitLink.Providers; + using GitTools; + using GitTools.Git; + using LibGit2Sharp; + + public static class ArgumentParser + { + private static readonly ILog Log = LogManager.GetCurrentClassLogger(); + + public static Context ParseArguments(string commandLineArguments) + { + return ParseArguments(commandLineArguments.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).ToList(), + new ProviderManager()); + } + + public static Context ParseArguments(params string[] commandLineArguments) + { + return ParseArguments(commandLineArguments.ToList(), new ProviderManager()); + } + + public static Context ParseArguments(List commandLineArguments, IProviderManager providerManager) + { + var context = new Context(providerManager); + + if (commandLineArguments.Count == 0) + { + context.IsHelp = true; + return context; + } + + var firstArgument = commandLineArguments.First(); + if (IsHelp(firstArgument)) + { + context.IsHelp = true; + return context; + } + + if (commandLineArguments.Count < 3 && commandLineArguments.Count != 1) + { + throw Log.ErrorAndCreateException("Invalid number of arguments"); + } + + context.SolutionDirectory = firstArgument; + + var namedArguments = commandLineArguments.Skip(1).ToList(); + for (var index = 0; index < namedArguments.Count; index++) + { + var name = namedArguments[index]; + + // First check everything without values + if (IsSwitch("debug", name)) + { + context.IsDebug = true; + continue; + } + + if (IsSwitch("errorsaswarnings", name)) + { + context.ErrorsAsWarnings = true; + continue; + } + + if (IsSwitch("skipverify", name)) + { + context.SkipVerify = true; + continue; + } + + if (IsSwitch("powershell", name)) + { + context.DownloadWithPowershell = true; + continue; + } + + // After this point, all arguments should have a value + index++; + var valueInfo = GetValue(namedArguments, index); + var value = valueInfo.Key; + index = index + (valueInfo.Value - 1); + + if (IsSwitch("l", name)) + { + context.LogFile = value; + continue; + } + + if (IsSwitch("c", name)) + { + context.ConfigurationName = value; + continue; + } + + if (IsSwitch("p", name)) + { + context.PlatformName = value; + continue; + } + + if (IsSwitch("u", name)) + { + context.TargetUrl = value; + continue; + } + + if (IsSwitch("b", name)) + { + context.TargetBranch = value; + continue; + } + + if (IsSwitch("s", name)) + { + context.ShaHash = value; + continue; + } + + if (IsSwitch("f", name)) + { + context.SolutionFile = value; + continue; + } + + if (IsSwitch("d", name)) + { + context.PdbFilesDirectory = value; + continue; + } + + if (IsSwitch("include", name)) + { + context.IncludedProjects.AddRange(value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Trim())); + continue; + } + + if (IsSwitch("ignore", name)) + { + context.IgnoredProjects.AddRange(value.Split(new []{ ',' }, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Trim())); + continue; + } + + throw Log.ErrorAndCreateException("Could not parse command line parameter '{0}'.", name); + } + + if (string.IsNullOrEmpty(context.TargetUrl)) + { + Log.Info($"No target url was specified, trying to determine the target url automatically based on directory '{context.SolutionDirectory}'"); + + var gitDir = GitDirFinder.TreeWalkForGitDir(context.SolutionDirectory); + + if (gitDir == null) + { + Log.Warning("Could not find a .git directory by walking up the directory tree"); + } + else + { + Log.Debug($"Found git directory at '{gitDir}', opening repository"); + + using (var repo = RepositoryLoader.GetRepo(gitDir)) + { + var currentBranch = repo.Head; + + Log.Debug($"Current branch is '{currentBranch.CanonicalName}', remote: '{currentBranch.Remote?.Url}', isDetachedHead: '{currentBranch.IsDetachedHead()}'"); + + if (string.IsNullOrEmpty(context.ShaHash)) + { + context.ShaHash = currentBranch.Tip.Sha; + + Log.Debug($"Automatically determined sha '{context.ShaHash}'"); + } + + if (currentBranch.Remote == null || currentBranch.IsDetachedHead()) + { + currentBranch = repo.GetBranchesContainingCommit(context.ShaHash).FirstOrDefault(b => b.Remote != null); + + Log.Debug($"Automatically determined branch '{currentBranch}'"); + } + + if (currentBranch != null && currentBranch.Remote != null) + { + var url = currentBranch.Remote.Url; + if (url.StartsWith("https://")) + { + context.TargetUrl = url.OptimizeUrl(); + + Log.Info("Automatically determine target url '{0}'", context.TargetUrl); + } + } + } + } + } + + if (!string.IsNullOrEmpty(context.TargetUrl)) + { + context.Provider = providerManager.GetProvider(context.TargetUrl); + } + + return context; + } + + private static KeyValuePair GetValue(List arguments, int index) + { + var totalCounter = 1; + + var value = arguments[index]; + + while (value.StartsWith("\"")) + { + if (value.EndsWith("\"")) + { + break; + } + + index++; + value += " " + arguments[index]; + + totalCounter++; + } + + value = value.Trim('\"'); + + return new KeyValuePair(value, totalCounter); + } + + private static bool IsSwitch(string switchName, string value) + { + if (value.StartsWith("-")) + { + value = value.Remove(0, 1); + } + + if (value.StartsWith("/")) + { + value = value.Remove(0, 1); + } + + return (string.Equals(switchName, value)); + } + + private static bool IsHelp(string singleArgument) + { + return (singleArgument == "?") || + IsSwitch("h", singleArgument) || + IsSwitch("help", singleArgument) || + IsSwitch("?", singleArgument); + } + } } \ No newline at end of file diff --git a/src/GitLink/Build/Construction/Interfaces/IProjectConfigurationInSolution.cs b/src/GitLink/Build/Construction/Interfaces/IProjectConfigurationInSolution.cs new file mode 100644 index 0000000..0422e46 --- /dev/null +++ b/src/GitLink/Build/Construction/Interfaces/IProjectConfigurationInSolution.cs @@ -0,0 +1,7 @@ +namespace GitLink.Build.Construction +{ + public interface IProjectConfigurationInSolution + { + bool IncludeInBuild { get; } + } +} \ No newline at end of file diff --git a/src/GitLink/Build/Construction/Interfaces/IProjectInSolution.cs b/src/GitLink/Build/Construction/Interfaces/IProjectInSolution.cs new file mode 100644 index 0000000..6dfb9ee --- /dev/null +++ b/src/GitLink/Build/Construction/Interfaces/IProjectInSolution.cs @@ -0,0 +1,9 @@ +namespace GitLink.Build.Construction +{ + public interface IProjectInSolution + { + object ProjectType { get; } + string RelativePath { get; } + object ProjectConfigurations { get; } + } +} \ No newline at end of file diff --git a/src/GitLink/Build/Construction/Interfaces/ISolutionParser.cs b/src/GitLink/Build/Construction/Interfaces/ISolutionParser.cs new file mode 100644 index 0000000..371cbc4 --- /dev/null +++ b/src/GitLink/Build/Construction/Interfaces/ISolutionParser.cs @@ -0,0 +1,11 @@ +namespace GitLink.Build.Construction +{ + using System.IO; + + public interface ISolutionParser + { + StreamReader SolutionReader { get; set; } + object[] Projects { get; } + void ParseSolution(); + } +} \ No newline at end of file diff --git a/src/GitLink/Context.cs b/src/GitLink/Context.cs index 5d3869e..5679d8a 100644 --- a/src/GitLink/Context.cs +++ b/src/GitLink/Context.cs @@ -1,137 +1,137 @@ -// -------------------------------------------------------------------------------------------------------------------- -// -// Copyright (c) 2014 - 2014 CatenaLogic. All rights reserved. -// -// -------------------------------------------------------------------------------------------------------------------- - - -namespace GitLink -{ - using System; - using System.Collections.Generic; - using Catel; - using Catel.IO; - using Catel.Logging; - using GitTools; - using Providers; - - public class Context : RepositoryContext - { - private static readonly ILog Log = LogManager.GetCurrentClassLogger(); - - private readonly IProviderManager _providerManager; - private IProvider _provider; - - public Context(IProviderManager providerManager) - { - Argument.IsNotNull(() => providerManager); - - _providerManager = providerManager; - - Authentication = new Authentication(); - ConfigurationName = "Release"; - PlatformName = "AnyCPU"; - IncludedProjects = new List(); - IgnoredProjects = new List(); - } - - public bool DownloadWithPowershell { get; set; } - - public bool IsHelp { get; set; } - - public bool IsDebug { get; set; } - - public bool ErrorsAsWarnings { get; set; } - - public bool SkipVerify { get; set; } - - public string LogFile { get; set; } - - //[Obsolete("Use 'Directory' instead")] - public string SolutionDirectory - { - get { return Directory; } - set { Directory = value; } - } - - public string ConfigurationName { get; set; } - - public string PlatformName { get; set; } - - public Authentication Authentication { get; private set; } - - public IProvider Provider - { - get - { - if (_provider == null) - { - _provider = _providerManager.GetProvider(TargetUrl); - } - - return _provider; - } - set - { - _provider = value; - } - } - - //[Obsolete("Use 'Url' instead")] - public string TargetUrl - { - get { return Url; } - set { Url = value; } - } - - //[Obsolete("Use 'Branch' instead")] - public string TargetBranch - { - get { return Branch; } - set { Branch = value; } - } - - public string ShaHash { get; set; } - - public string SolutionFile { get; set; } - - public List IncludedProjects { get; private set; } - - public List IgnoredProjects { get; private set; } - - public string PdbFilesDirectory { get; set; } - - public void ValidateContext() - { - if (!string.IsNullOrWhiteSpace(SolutionDirectory)) - { - SolutionDirectory = Path.GetFullPath(SolutionDirectory, Environment.CurrentDirectory); - } - - if (string.IsNullOrEmpty(SolutionDirectory)) - { - throw Log.ErrorAndCreateException("Solution directory is missing"); - } - - if (string.IsNullOrEmpty(ConfigurationName)) - { - throw Log.ErrorAndCreateException("Configuration name is missing"); - } - - if (string.IsNullOrEmpty(PlatformName)) - { - throw Log.ErrorAndCreateException("Platform name is missing"); - } - - if (string.IsNullOrEmpty(TargetUrl)) - { - throw Log.ErrorAndCreateException("Target url is missing"); - } - - if (Provider == null) - { - throw Log.ErrorAndCreateException("Cannot determine git provider"); - } - } - } +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) 2014 - 2014 CatenaLogic. All rights reserved. +// +// -------------------------------------------------------------------------------------------------------------------- + + +namespace GitLink +{ + using System; + using System.Collections.Generic; + using Catel; + using Catel.IO; + using Catel.Logging; + using GitTools; + using Providers; + + public class Context : RepositoryContext + { + private static readonly ILog Log = LogManager.GetCurrentClassLogger(); + + private readonly IProviderManager _providerManager; + private IProvider _provider; + + public Context(IProviderManager providerManager) + { + Argument.IsNotNull(() => providerManager); + + _providerManager = providerManager; + + Authentication = new Authentication(); + ConfigurationName = "Release"; + PlatformName = "AnyCPU"; + IncludedProjects = new List(); + IgnoredProjects = new List(); + } + + public bool DownloadWithPowershell { get; set; } + + public bool IsHelp { get; set; } + + public bool IsDebug { get; set; } + + public bool ErrorsAsWarnings { get; set; } + + public bool SkipVerify { get; set; } + + public string LogFile { get; set; } + + //[Obsolete("Use 'Directory' instead")] + public string SolutionDirectory + { + get { return Directory; } + set { Directory = value; } + } + + public string ConfigurationName { get; set; } + + public string PlatformName { get; set; } + + public Authentication Authentication { get; private set; } + + public IProvider Provider + { + get + { + if (_provider == null) + { + _provider = _providerManager.GetProvider(TargetUrl); + } + + return _provider; + } + set + { + _provider = value; + } + } + + //[Obsolete("Use 'Url' instead")] + public string TargetUrl + { + get { return Url; } + set { Url = value; } + } + + //[Obsolete("Use 'Branch' instead")] + public string TargetBranch + { + get { return Branch; } + set { Branch = value; } + } + + public string ShaHash { get; set; } + + public string SolutionFile { get; set; } + + public List IncludedProjects { get; private set; } + + public List IgnoredProjects { get; private set; } + + public string PdbFilesDirectory { get; set; } + + public void ValidateContext() + { + if (!string.IsNullOrWhiteSpace(SolutionDirectory)) + { + SolutionDirectory = Path.GetFullPath(SolutionDirectory, Environment.CurrentDirectory); + } + + if (string.IsNullOrEmpty(SolutionDirectory)) + { + throw Log.ErrorAndCreateException("Solution directory is missing"); + } + + if (string.IsNullOrEmpty(ConfigurationName)) + { + throw Log.ErrorAndCreateException("Configuration name is missing"); + } + + if (string.IsNullOrEmpty(PlatformName)) + { + throw Log.ErrorAndCreateException("Platform name is missing"); + } + + if (string.IsNullOrEmpty(TargetUrl)) + { + throw Log.ErrorAndCreateException("Target url is missing"); + } + + if (Provider == null) + { + throw Log.ErrorAndCreateException("Cannot determine git provider"); + } + } + } } \ No newline at end of file diff --git a/src/GitLink/Extensions/ProjectExtensions.cs b/src/GitLink/Extensions/ProjectExtensions.cs index af0c1e9..7599cfa 100644 --- a/src/GitLink/Extensions/ProjectExtensions.cs +++ b/src/GitLink/Extensions/ProjectExtensions.cs @@ -28,25 +28,35 @@ public static string GetProjectName(this Project project) return projectName ?? Path.GetFileName(project.FullPath); } - public static void CreateSrcSrv(this Project project, string rawUrl, string revision, Dictionary paths, bool downloadWithPowershell) + public static void CreateSrcSrv(this Project project, SrcSrvContext srcSrvContext) { Argument.IsNotNull(() => project); - Argument.IsNotNullOrWhitespace(() => rawUrl); - Argument.IsNotNullOrWhitespace(() => revision); + Argument.IsNotNull(() => srcSrvContext); + + Argument.IsNotNullOrWhitespace("rawUrl", srcSrvContext.RawUrl); + Argument.IsNotNullOrWhitespace("revision", srcSrvContext.Revision); var srcsrvFile = GetOutputSrcSrvFile(project); - CreateSrcSrv(project, rawUrl, revision, paths, srcsrvFile, downloadWithPowershell); + CreateSrcSrv(project, srcsrvFile, srcSrvContext); } - public static void CreateSrcSrv(this Project project, string rawUrl, string revision, Dictionary paths, string srcsrvFile, bool downloadWithPowershell) + public static void CreateSrcSrv(this Project project, string srcsrvFile, SrcSrvContext srcSrvContext) { Argument.IsNotNull(() => project); - Argument.IsNotNullOrWhitespace(() => rawUrl); - Argument.IsNotNullOrWhitespace(() => revision); + Argument.IsNotNull(() => srcSrvContext); + Argument.IsNotNullOrWhitespace("rawUrl", srcSrvContext.RawUrl); + Argument.IsNotNullOrWhitespace("revision", srcSrvContext.Revision); Argument.IsNotNullOrWhitespace(() => srcsrvFile); - File.WriteAllBytes(srcsrvFile, SrcSrv.Create(rawUrl, revision, paths.Select(x => new Tuple(x.Key, x.Value)), downloadWithPowershell)); + if (srcSrvContext.VstsData.Count != 0) + { + File.WriteAllBytes(srcsrvFile, SrcSrv.CreateVsts(srcSrvContext.Revision, srcSrvContext.Paths, srcSrvContext.VstsData)); + } + else + { + File.WriteAllBytes(srcsrvFile, SrcSrv.Create(srcSrvContext.RawUrl, srcSrvContext.Revision, srcSrvContext.Paths, srcSrvContext.DownloadWithPowershell)); + } } public static IEnumerable GetCompilableItems(this Project project) diff --git a/src/GitLink/FodyWeavers.xml b/src/GitLink/FodyWeavers.xml index 1ae0446..f50b34a 100644 --- a/src/GitLink/FodyWeavers.xml +++ b/src/GitLink/FodyWeavers.xml @@ -1,10 +1,16 @@  - + Catel.Core GitTools.Core + ImpromptuInterface + + + Microsoft.Build + + \ No newline at end of file diff --git a/src/GitLink/GitLink.csproj b/src/GitLink/GitLink.csproj index f02cf08..5ec6fe6 100644 --- a/src/GitLink/GitLink.csproj +++ b/src/GitLink/GitLink.csproj @@ -48,14 +48,12 @@ Resources\Icons\Logo.ico - - False - ..\..\lib\Catel.Core.4.3.0\lib\net45\Catel.Core.dll + + ..\..\lib\Catel.Core.4.5.3\lib\net45\Catel.Core.dll True - - False - ..\..\lib\Catel.Fody.2.11.0\lib\portable-net4+sl4+wp7+win8+wpa81+MonoAndroid14+MonoTouch40\Catel.Fody.Attributes.dll + + ..\..\lib\Catel.Fody.2.14.0\lib\portable-net4+sl4+wp7+win8+wpa81+MonoAndroid14+MonoTouch40\Catel.Fody.Attributes.dll True @@ -63,6 +61,10 @@ ..\..\lib\GitTools.Core.1.0.0-unstable0021\lib\net45\GitTools.Core.dll True + + ..\..\lib\ImpromptuInterface.6.2.2\lib\net40\ImpromptuInterface.dll + True + False ..\..\lib\LibGit2Sharp.0.21.0.176\lib\net40\LibGit2Sharp.dll @@ -93,6 +95,9 @@ + + + @@ -107,6 +112,7 @@ + @@ -114,10 +120,13 @@ + + + @@ -139,11 +148,9 @@ This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - + - - + + \ No newline at end of file diff --git a/src/GitLinkTask/LinkProject.cs b/src/GitLinkTask/LinkProject.cs new file mode 100644 index 0000000..79a6bdb --- /dev/null +++ b/src/GitLinkTask/LinkProject.cs @@ -0,0 +1,28 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) 2014 - 2016 CatenaLogic. All rights reserved. +// +// -------------------------------------------------------------------------------------------------------------------- + + +namespace GitLinkTask +{ + using System.IO; + using Microsoft.Build.Framework; + using Microsoft.Build.Utilities; + + public class LinkProject : ToolTask + { + [Required] + public ITaskItem SolutionDirectory { get; set; } + + [Required] + public string ProjectName { get; set; } + + protected override string ToolName => "GitLink.exe"; + + protected override string GenerateFullPathToTool() => Path.Combine(Path.GetDirectoryName(GetType().Assembly.Location), "GitLink.exe"); + + protected override string GenerateCommandLineCommands() => $"{SolutionDirectory.FullPath()} -include {ProjectName}"; + } +} \ No newline at end of file diff --git a/src/GitLinkTask/Properties/AssemblyInfo.cs b/src/GitLinkTask/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..e67bdcc --- /dev/null +++ b/src/GitLinkTask/Properties/AssemblyInfo.cs @@ -0,0 +1,24 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) 2014 - 2016 CatenaLogic. All rights reserved. +// +// -------------------------------------------------------------------------------------------------------------------- + + +using System.Reflection; +using System.Runtime.InteropServices; + +// All other assembly info is defined in SharedAssembly.cs + +[assembly: AssemblyTitle("GitLinkTask")] +[assembly: AssemblyProduct("GitLinkTask")] +[assembly: AssemblyDescription("GitLinkTask library")] + +// 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. + +#if !PCL + +[assembly: ComVisible(false)] +#endif \ No newline at end of file diff --git a/src/GitLinkTask/TaskItemExtensions.cs b/src/GitLinkTask/TaskItemExtensions.cs new file mode 100644 index 0000000..d9e965f --- /dev/null +++ b/src/GitLinkTask/TaskItemExtensions.cs @@ -0,0 +1,30 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) 2014 - 2016 CatenaLogic. All rights reserved. +// +// -------------------------------------------------------------------------------------------------------------------- + + +namespace GitLinkTask +{ + using System.Diagnostics; + using Microsoft.Build.Framework; + + public static class TaskItemExtensions + { + [DebuggerStepThrough] + public static string FullPath(this ITaskItem item) => item.GetMetadata("FullPath"); + + [DebuggerStepThrough] + public static string RootDir(this ITaskItem item) => item.GetMetadata("RootDir"); + + [DebuggerStepThrough] + public static string Filename(this ITaskItem item) => item.GetMetadata("Filename"); + + [DebuggerStepThrough] + public static string Extension(this ITaskItem item) => item.GetMetadata("Extension"); + + [DebuggerStepThrough] + public static string Directory(this ITaskItem item) => item.GetMetadata("Directory"); + } +} \ No newline at end of file diff --git a/tools/NuGet/NuGet.exe b/tools/NuGet/NuGet.exe index 3ffdd33..9552e30 100644 Binary files a/tools/NuGet/NuGet.exe and b/tools/NuGet/NuGet.exe differ