diff --git a/.gitignore b/.gitignore index c2c5710..8e6778c 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,9 @@ *.sln.docstates .nuget/ +project.lock.json +*.nuget.targets +*.nuget.props tools/FAKE/ build-log.xml Nuget.key @@ -42,6 +45,7 @@ obj *.vspscc *.xap .builds +*.log # Visual C++ cache files ipch/ @@ -103,7 +107,6 @@ sql TestResults *.Cache ClientBin -stylecop.* ~$* *.dbmdl Generated_Code #added for RIA/Silverlight projects @@ -122,4 +125,4 @@ Desktop.ini # mstest test results TestResults -/.vs +.vs/ diff --git a/AUTHORS b/AUTHORS index 9f4ce2d..9d39982 100644 --- a/AUTHORS +++ b/AUTHORS @@ -9,4 +9,5 @@ # Please keep the list sorted. # Please notify the first person on the list to be added here. +Andrew Arnott CatenaLogic diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f8c392a..9babfd8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,6 +1,22 @@ Contributors ============ +## Prerequisites + +### Required + +* [Microsoft Build Tools 2015](https://www.microsoft.com/en-us/download/details.aspx?id=48159) (automatically installed with Visual Studio 2015) + +### Better with + +* [Visual Studio 2015](https://www.visualstudio.com/en-us) +* [NuProj](http://nuproj.net) extension for Visual Studio + +### How to Build + +To build this project, first run the init script in the root of the repo, +then simply run "msbuild" from the src directory. + ## Contributing Process ### Get Buyoff Or Find Open Community Issues/Features diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 694781d..4de36da 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -10,6 +10,7 @@ # Please keep the list sorted. +Andrew Arnott Geert van Horrik Wesley Eledui -Marek Fišera \ No newline at end of file +Marek Fišera diff --git a/GitVersionConfig.yaml b/GitVersionConfig.yaml index 35575d5..af70400 100644 --- a/GitVersionConfig.yaml +++ b/GitVersionConfig.yaml @@ -1,3 +1,3 @@ mode: ContinuousDeployment assembly-versioning-scheme: MajorMinorPatch -#next-version: 1.0.0 \ No newline at end of file +next-version: 3.0.0 \ No newline at end of file diff --git a/README.md b/README.md index de69bff..28d2b3d 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,12 @@ GitLink ========== +[![Build status](https://ci.appveyor.com/api/projects/status/y3yvwpvk4kmw0hsg/branch/develop?svg=true)](https://ci.appveyor.com/project/gittools/gitlink/branch/develop) + [![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) -![Version](https://img.shields.io/nuget/v/gitlink.svg) -![Pre-release version](https://img.shields.io/nuget/vpre/gitlink.svg) +[![Version](https://img.shields.io/nuget/v/gitlink.svg)][NuGetDownload] +[![Pre-release version](https://img.shields.io/nuget/vpre/gitlink.svg)][NuGetDownload] ![Chocolatey count](https://img.shields.io/chocolatey/dt/gitlink.svg) ![Chocolatey version](https://img.shields.io/chocolatey/v/gitlink.svg) @@ -36,6 +38,61 @@ When using GitLink, the user no longer has to specify symbol servers. The only r ![Enabling source server support](doc/images/visualstudio_enablesourceserversupport.png) +# How to use GitLink to enable source stepping on your own projects + +## NuGet/MSBuild integration + +The simplest way to use GitLink is to [install its NuGet package][NuGetDownload] into your project. + + Install-Package GitLink + +Once installed, it automatically integrates with MSBuild to add source download instructions to your PDB. + +## Command line tool + +If you want to install the tool on your (build) computer, the package is available via Chocolatey. To install, use the following command: + + choco install gitlink + +Using GitLink via the command line is very simple: + + gitlink.exe + +### Running for a custom raw content URL + +When working with a content proxy or an alternative git VCS system that supports direct HTTP access to specific file revisions use the `-u` parameter with the custom raw content root URL + + GitLink.exe -u https://raw.githubusercontent.com/catel/catel + +The custom url will be used to fill in the following pattern `{customUrl}/{revision}/{relativeFilePath}` when generating the source mapping. + +When working with a repository using uncommon URL you can use placeholders to specify where the filename and revision hash should be, use `-u` parameter with the custom URL + + GitLink.exe -u "https://host/projects/catel/repos/catel/browse/{filename}?at={revision}&raw" + +The custom url will be used to fill the placeholders with the relative file path and the revision hash. + +### More options + +There are many more parameters you can use. Display the usage doc with the following command line: + + GitLink.exe -h + +# How does it work + +The SrcSrv tool (Srcsrv.dll) enables a client to retrieve the exact version of the source files that were used to build an application. Because the source code for a module can change between versions and over the course of years, it is important to look at the source code as it existed when the version of the module in question was built. + +For more information, see the official documentation of SrcSrv. + +GitLink creates a source index file and updates the PDB file so it will retrieve the files from the Git host file handler. +To do this, GitLink must be aware of the public URL from which the source files you compiled with can be retrieved. +GitLink.exe reads your compiler-generated PDB, which already contains full paths to your local source files. +It then searches for a git repo that contains those source files and looks up the commit that HEAD points to. +It also searches your remotes for a URL pattern that it recognizes (e.g. https://github.com/name/repo). +It combines the URL and the commit ID to create a unique URL for each source file of this exact version, and adds this information to your PDB. + +When you share your PDB alongside your assembly, your users who debug with Source Server support enabled will automatically be able to step into your source code. + # Troubleshooting ## Source Stepping isn't working @@ -46,8 +103,6 @@ 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. @@ -71,7 +126,7 @@ GitLink supports the following providers out of the box (will auto-detect based * GitHub * Custom Provider (custom urls) -Providers currently being worked on: +Providers that could be supported with the help of the community: * Assembla * Beanstalk @@ -85,143 +140,6 @@ Providers currently being worked on: It is also possible to specify a custom url provider. -# Using GitLink as command line tool - -Using GitLink via the command line is very simple: - -1. Build the solution - in release mode with pdb files enabled -2. Run the console application with the right command line parameters -3. Include the PDB in your nuget package - -See [Oren Novotony's blog post](https://oren.codes/2015/09/23/enabling-source-code-debugging-for-your-nuget-packages-with-gitlink/) for even more detail and examples on build integration. - -## Most simple usage - -This is the most simple usage available **starting from 2.2.0**. It will automatically determine the url and commit based on a local *.git* directory. - - GitLink.exe c:\source\catel - -## Running for the default branch - - GitLink.exe c:\source\catel -u https://github.com/catel/catel - -This will use the default branch (which is in most cases **master**). You can find out the default branch by checking what branch is loaded by default on the GitHub page. - -## Running for a specific branch - - GitLink.exe c:\source\catel -u https://github.com/catel/catel -b develop - -This will use the develop branch. - -## Running for a specific branch and configuration - - GitLink.exe c:\source\catel -u https://github.com/catel/catel -b develop -c debug - -This will use the develop branch and the debug configuration. - -## Running for a specific solution only - -Sometimes a repository contains more than 1 solution file. By default, all solutions will be processed. To only process a single solution file, use the *-f* option: - - GitLink.exe c:\source\catel -u https://github.com/catel/catel -f Catel.sln - -## Ignoring projects and explicitly including them - -When specific projects should be ignored, use the *-ignore* option. This option accepts a comma separated list of patterns to ignore. Each pattern is either a literal project name (case-insensitive) or a regex enclosed in slashes. For example: - - GitLink.exe c:\source\catel -u https://github.com/catel/catel -f Catel.sln -ignore Catel.Core.WP80,Catel.MVVM.WP80 - GitLink.exe c:\source\catel -u https://github.com/catel/catel -f Catel.sln -ignore /^.+\.WP80$/,Catel.Core - -In case you want to ignore most of your projects, you can explicitly *-include* only the projects you need - others will be ignored automatically. Same as *-ignore* it accepts list of patterns. For example: - - GitLink.exe c:\source\catel -u https://github.com/catel/catel -f Catel.sln -include Catel.Core - GitLink.exe c:\source\catel -u https://github.com/catel/catel -f Catel.sln -include /Catel\..*$/,SomeOtherProject - -Finally, you can set both *-ignore* and *-include* options. In this case only projects matching one of *-include* patterns will be taken, but if and only if they don't match one of *-ignore*s. For example, the following command line will include only Catel.* projects, except "Catel.Core": - - GitLink.exe c:\source\catel -u https://github.com/catel/catel -f Catel.sln -include /Catel\..*$/ -ignore Catel.Core - -## Running for an uncommon / customized URL - -When working with a repository using uncommon URL you can use placeholders to specifiy where the filename and revision hash should be, use `-u` parameter with the custom URL - - GitLink.exe c:\source\catel -u "https://host/projects/catel/repos/catel/browse/{filename}?at={revision}&raw" - -The custom url will be used to fill the placeholders with the relative file path and the revision hash. - -## Running for a custom raw content URL - -When working with a content proxy or an alternative git VCS system that supports direct HTTP access to specific file revisions use the `-u` parameter with the custom raw content root URL - - GitLink.exe c:\source\catel -u https://raw.githubusercontent.com/catel/catel - -The custom url will be used to fill in the following pattern `{customUrl}/{revision}/{relativeFilePath}` when generating the source mapping. - -## Getting help - -When you need help about GitLink, use the following command line: - - GitLink.exe -help - -## Logging to a file - -When you need to log the information to a file, use the following command line: - - GitLink.exe c:\source\catel -u https://github.com/catel/catel -b develop -l GitLinkLog.log - -# Using GitLink in code - -GitLink is built with 2 usages in mind: command line and code reference. Though most people will use the command line version, it is possible to reference the executable and use the logic in code. - -The command line implementation uses the same available API. - -## Creating a context - -To link files to a Git project, a context must be created. The command line version does this by using the *ArgumentParser* class. It is also possible to create a context from scratch as shown in the example below: - - var context = new GitLink.Context(new ProviderManager()); - context.SolutionDirectory = @"c:\source\catel"; - context.TargetUrl = "https://github.com/catel/catel"; - context.TargetBranch = "develop"; - -It is possible to create a context based on command line arguments: - - var context = ArgumentParser.Parse(@"c:\source\catel -u https://github.com/catel/catel -b develop"); - -## Linking a context - -Once a context is created, the *Linker* class can be used to actually link the files: - - Linker.Link(context); - -# How to get - -There are three general ways to get GitLink: - -## Get it from GitHub - -The releases will be available as separate executable download on the [releases tab](https://github.com/GitTools/GitLink/releases) of the project. - -## Get it via Chocolatey - -If you want to install the tool on your (build) computer, the package is available via Chocolatey. To install, use the following command: - - choco install gitlink - -## Get it via NuGet - -If you want to reference the assembly to use it in code, the recommended way to get it is via NuGet. - -**Note that getting GitLink via NuGet will add it as a reference to the project** - -# How does it work - -The SrcSrv tool (Srcsrv.dll) enables a client to retrieve the exact version of the source files that were used to build an application. Because the source code for a module can change between versions and over the course of years, it is important to look at the source code as it existed when the version of the module in question was built. - -For more information, see the official documentation of SrcSrv. - -GitLink creates a source index file and updates the PDB file so it will retrieve the files from the Git host file handler. - # Projects using GitLink @@ -271,7 +189,8 @@ Are you using GitLink in your projects? Let us know and we will add your project *Note that you can also create a pull request on this document and add it yourself.* - # Icon Link by Dominic Whittle from The Noun Project + +[NuGetDownload]: https://www.nuget.org/packages/gitlink diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 0000000..6f8b018 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,31 @@ +install: + - choco install gitversion.portable -pre -y + +assembly_info: + patch: false + +skip_tags: true + +image: Visual Studio 2015 + +configuration: Release + +environment: + VisualStudioVersion: 14.0 + +cache: +- '%USERPROFILE%\.nuget\packages -> **\project.json' +- 'obj\tools -> tools\**' + +before_build: + - ps: .\init.ps1 + - ps: gitversion /l console /output buildserver /updateAssemblyInfo + +build: + project: src\GitLink.sln + parallel: true + verbosity: minimal + +artifacts: +- path: '**\bin\**\*.nupkg' + name: NuGet Package diff --git a/deployment/Chocolatey/template/GitHubLink/GitHubLink.nuspec b/deployment/Chocolatey/template/GitHubLink/GitHubLink.nuspec deleted file mode 100644 index 07d91ae..0000000 --- a/deployment/Chocolatey/template/GitHubLink/GitHubLink.nuspec +++ /dev/null @@ -1,27 +0,0 @@ - - - - githublink - [VERSION] - GitHubLink - GeertvanHorrik - - - ** Note: this is a maintenance package, GitHubLink is replaced by GitLink ** - - - - - - 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/deployment/Chocolatey/template/GitLink/GitLink.nuspec b/deployment/Chocolatey/template/GitLink/GitLink.nuspec deleted file mode 100644 index 2b6ec9f..0000000 --- a/deployment/Chocolatey/template/GitLink/GitLink.nuspec +++ /dev/null @@ -1,24 +0,0 @@ - - - - gitlink - [VERSION] - GitLink - GeertvanHorrik - - - 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 githublinksource 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_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 deleted file mode 100644 index a46c961..0000000 --- a/deployment/Chocolatey/template/GitLink/tools/LICENSE.txt +++ /dev/null @@ -1,21 +0,0 @@ -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 deleted file mode 100644 index 2fe26a3..0000000 Binary files a/deployment/FinalBuilder/GitLink.CreatePackages.fbp7 and /dev/null differ diff --git a/deployment/NuGet/template/GitHubLink/GitHubLink.nuspec b/deployment/NuGet/template/GitHubLink/GitHubLink.nuspec deleted file mode 100644 index d261a25..0000000 --- a/deployment/NuGet/template/GitHubLink/GitHubLink.nuspec +++ /dev/null @@ -1,28 +0,0 @@ - - - - githublink - [VERSION] - GitHubLink - GeertvanHorrik - true - - - ** Note: this is a maintenance package, GitHubLink is replaced by GitLink ** - - - - - - 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/deployment/NuGet/template/GitLink/GitLink.nuspec b/deployment/NuGet/template/GitLink/GitLink.nuspec deleted file mode 100644 index 2aef4b3..0000000 --- a/deployment/NuGet/template/GitLink/GitLink.nuspec +++ /dev/null @@ -1,25 +0,0 @@ - - - - gitlink - [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 - 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/deployment/NuGet/template/GitLinkTask/Build/dotnet/GitLink.targets b/deployment/NuGet/template/GitLinkTask/Build/dotnet/GitLink.targets deleted file mode 100644 index c4e1f49..0000000 --- a/deployment/NuGet/template/GitLinkTask/Build/dotnet/GitLink.targets +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/deployment/NuGet/template/GitLinkTask/GitLinkTask.nuspec b/deployment/NuGet/template/GitLinkTask/GitLinkTask.nuspec deleted file mode 100644 index e00e962..0000000 --- a/deployment/NuGet/template/GitLinkTask/GitLinkTask.nuspec +++ /dev/null @@ -1,25 +0,0 @@ - - - - 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/init.cmd b/init.cmd new file mode 100644 index 0000000..7cb727e --- /dev/null +++ b/init.cmd @@ -0,0 +1 @@ +powershell.exe -ExecutionPolicy bypass -Command "& '%~dpn0.ps1'" %* diff --git a/init.ps1 b/init.ps1 new file mode 100644 index 0000000..c1398c5 --- /dev/null +++ b/init.ps1 @@ -0,0 +1,33 @@ +<# +.SYNOPSIS + Restores NuGet packages. +#> +Param( +) + +Push-Location $PSScriptRoot +try { + $HeaderColor = 'Green' + $toolsPath = "$PSScriptRoot\tools" + $nugetVerbosity = 'quiet' + if ($Verbose) { $nugetVerbosity = 'normal' } + + # First restore NuProj packages since the solution restore depends on NuProj evaluation succeeding. + gci "$PSScriptRoot\src\project.json" -rec |? { $_.FullName -imatch 'nuget' } |% { + & "$toolsPath\Restore-NuGetPackages.ps1" -Path $_ -Verbosity $nugetVerbosity + } + + # Restore VS solution dependencies + gci "$PSScriptRoot\src" -rec |? { $_.FullName.EndsWith('.sln') } |% { + & "$toolsPath\Restore-NuGetPackages.ps1" -Path $_.FullName -Verbosity $nugetVerbosity + } + + Write-Host "Successfully restored all dependencies" -ForegroundColor Yellow +} +catch { + Write-Error "Aborting script due to error" + exit $lastexitcode +} +finally { + Pop-Location +} diff --git a/lib/repositories.config b/lib/repositories.config deleted file mode 100644 index 8114fe5..0000000 --- a/lib/repositories.config +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/scripts - Build - Debug.bat b/scripts - Build - Debug.bat index b1ae2b9..e0e893d 100644 --- a/scripts - Build - Debug.bat +++ b/scripts - Build - Debug.bat @@ -1,10 +1,7 @@ @echo off +@setlocal -IF NOT "%VS110COMNTOOLS%" == "" (call "%VS110COMNTOOLS%vsvars32.bat") -IF NOT "%VS120COMNTOOLS%" == "" (call "%VS120COMNTOOLS%vsvars32.bat") -IF NOT "%VS130COMNTOOLS%" == "" (call "%VS130COMNTOOLS%vsvars32.bat") IF NOT "%VS140COMNTOOLS%" == "" (call "%VS140COMNTOOLS%vsvars32.bat") - -for /F %%A in ('dir /b src\*.sln') do call devenv src\%%A /build "Debug" +for /F %%A in ('dir /b src\*.sln') do call devenv "src\%%A" /build "Debug" pause \ No newline at end of file diff --git a/scripts - Build - Release.bat b/scripts - Build - Release.bat index d5d0265..8cc9874 100644 --- a/scripts - Build - Release.bat +++ b/scripts - Build - Release.bat @@ -1,10 +1,7 @@ @echo off +@setlocal -IF NOT "%VS110COMNTOOLS%" == "" (call "%VS110COMNTOOLS%vsvars32.bat") -IF NOT "%VS120COMNTOOLS%" == "" (call "%VS120COMNTOOLS%vsvars32.bat") -IF NOT "%VS130COMNTOOLS%" == "" (call "%VS130COMNTOOLS%vsvars32.bat") IF NOT "%VS140COMNTOOLS%" == "" (call "%VS140COMNTOOLS%vsvars32.bat") - -for /F %%A in ('dir /b src\*.sln') do call devenv src\%%A /build "Release" +for /F %%A in ('dir /b src\*.sln') do call devenv "src\%%A" /build "Release" pause \ No newline at end of file diff --git a/scripts - Clean all.bat b/scripts - Clean all.bat index effd5ea..11df517 100644 --- a/scripts - Clean all.bat +++ b/scripts - Clean all.bat @@ -1,7 +1,4 @@ -REM Deleting packages -for /d %%p in (".\lib\*.*") do rmdir "%%p" /s /q - REM Deleting output -rmdir .\output /s /q +FOR %%A in (bin obj\debug obj\release) do IF EXIST "%~dp0%%A" rd /s /q "%~dp0%%A" -pause \ No newline at end of file +@pause diff --git a/scripts - Restore packages.bat b/scripts - Restore packages.bat index 529df1f..4500c48 100644 --- a/scripts - Restore packages.bat +++ b/scripts - Restore packages.bat @@ -1,4 +1,3 @@ -for /f %%a in ('dir /b src\*.sln') do call tools\nuget\nuget.exe restore src\%%a -PackagesDirectory .\lib +call "%~dp0init.cmd" - -pause \ No newline at end of file +@pause diff --git a/src/EnlistmentInfo.targets b/src/EnlistmentInfo.targets new file mode 100644 index 0000000..731d7a7 --- /dev/null +++ b/src/EnlistmentInfo.targets @@ -0,0 +1,30 @@ + + + + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) + + + + + + $(MSBuildProjectFullPath) + GetDeployableOutputs + + + $(MSBuildProjectFullPath) + GetDeployableOutputs + + + + diff --git a/src/GitLink.NuGet/GitLink.NuGet.nuproj b/src/GitLink.NuGet/GitLink.NuGet.nuproj new file mode 100644 index 0000000..338674f --- /dev/null +++ b/src/GitLink.NuGet/GitLink.NuGet.nuproj @@ -0,0 +1,52 @@ + + + + + Debug + AnyCPU + + + Release + AnyCPU + + + + 29e78909-b7fb-472c-a9a0-1749a8be9a9a + + + <_NuGetRoot>$(UserProfile)\.nuget\packages + <_NuGetRoot Condition="'$(NUGET_PACKAGES)' != ''">$(NUGET_PACKAGES) + $(_NuGetRoot)\NuProj\0.11.14-beta\tools + + + + GitLink + $(GitVersion_NuGetVersion) + GitLink + GeertvanHorrik,AArnott + GeertvanHorrik,AArnott + GitLink let's users step through your code hosted on any Git hosting service! This makes symbol servers obsolete which saves you both time + + + https://github.com/GitTools/GitLink + https://github.com/GitTools/GitLink/blob/$(APPVEYOR_REPO_COMMIT)/LICENSE + git pdb + true + https://raw.githubusercontent.com/GitTools/GitLink/$(APPVEYOR_REPO_COMMIT)/design/logo/logo_64.png + GetDeployableOutputs + + true + + + + + + + Build + + + + + + + diff --git a/src/GitLink.NuGet/project.json b/src/GitLink.NuGet/project.json new file mode 100644 index 0000000..584dba0 --- /dev/null +++ b/src/GitLink.NuGet/project.json @@ -0,0 +1,11 @@ +{ + "dependencies": { + "NuProj": "0.11.14-beta" + }, + "frameworks": { + "net451": {} + }, + "runtimes": { + "win": {} + } +} \ No newline at end of file diff --git a/deployment/Chocolatey/template/GitHubLink/tools/LICENSE.txt b/src/GitLink.NuGet/tools/LICENSE.txt similarity index 90% rename from deployment/Chocolatey/template/GitHubLink/tools/LICENSE.txt rename to src/GitLink.NuGet/tools/LICENSE.txt index a46c961..2e12320 100644 --- a/deployment/Chocolatey/template/GitHubLink/tools/LICENSE.txt +++ b/src/GitLink.NuGet/tools/LICENSE.txt @@ -1,6 +1,10 @@ +From: https://github.com/GitTools/GitLink/blob/develop/LICENSE + +LICENSE + The MIT License (MIT) -Copyright (c) 2014 - 2016 CatenaLogic +Copyright (c) 2014 - 2017 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/src/GitLink.Tests/ApprovalTestsConfig.cs b/src/GitLink.Tests/ApprovalTestsConfig.cs index 7967abb..f5d3ac4 100644 --- a/src/GitLink.Tests/ApprovalTestsConfig.cs +++ b/src/GitLink.Tests/ApprovalTestsConfig.cs @@ -1,10 +1,9 @@ // -------------------------------------------------------------------------------------------------------------------- // -// Copyright (c) 2014 - 2014 CatenaLogic. All rights reserved. +// Copyright (c) 2014 - 2016 CatenaLogic. All rights reserved. // // -------------------------------------------------------------------------------------------------------------------- - using ApprovalTests.Reporters; [assembly: UseReporter(typeof(DiffReporter))] \ No newline at end of file diff --git a/src/GitLink.Tests/ArgumentParserFacts.cs b/src/GitLink.Tests/ArgumentParserFacts.cs deleted file mode 100644 index f93bd13..0000000 --- a/src/GitLink.Tests/ArgumentParserFacts.cs +++ /dev/null @@ -1,166 +0,0 @@ -// -------------------------------------------------------------------------------------------------------------------- -// -// Copyright (c) 2014 - 2014 CatenaLogic. All rights reserved. -// -// -------------------------------------------------------------------------------------------------------------------- - - -namespace GitLink.Tests -{ - using Catel.Test; - using NUnit.Framework; - - [TestFixture] - public class ArgumentParserFacts - { - [TestCase] - public void ReturnsHelpForEmptyParameters() - { - var context = ArgumentParser.ParseArguments(string.Empty); - Assert.IsTrue(context.IsHelp); - } - - [TestCase] - public void CorrectlyParsesSolutionDirectory() - { - var context = ArgumentParser.ParseArguments("solutionDirectory -u http://github.com/CatenaLogic/GitLink"); - - Assert.AreEqual("solutionDirectory", context.SolutionDirectory); - } - - [TestCase] - public void CorrectlyParsesLogFilePath() - { - var context = ArgumentParser.ParseArguments("solutionDirectory -l logFilePath"); - - Assert.AreEqual("solutionDirectory", context.SolutionDirectory); - Assert.AreEqual("logFilePath", context.LogFile); - } - - [TestCase] - public void CorrectlyParsesPdbFilesDirectory() - { - var context = ArgumentParser.ParseArguments("solutionDirectory -d pdbFilesDirectory"); - - Assert.AreEqual("solutionDirectory", context.SolutionDirectory); - Assert.AreEqual("pdbFilesDirectory", context.PdbFilesDirectory); - } - - [TestCase] - public void CorrectlyParsesHelp() - { - var context = ArgumentParser.ParseArguments("-h"); - - Assert.IsTrue(context.IsHelp); - } - - [TestCase] - public void CorrectlyParsesSolutionFile() - { - var context = ArgumentParser.ParseArguments("solutionDirectory -u http://github.com/CatenaLogic/GitLink -f someSolution"); - - Assert.AreEqual("someSolution", context.SolutionFile); - } - - [TestCase] - public void CorrectlyParsesUrlAndBranchName() - { - var context = ArgumentParser.ParseArguments("solutionDirectory -u http://github.com/CatenaLogic/GitLink -b somebranch"); - - Assert.AreEqual("solutionDirectory", context.SolutionDirectory); - Assert.AreEqual("http://github.com/CatenaLogic/GitLink", context.TargetUrl); - Assert.AreEqual("somebranch", context.TargetBranch); - } - - [TestCase] - public void CorrectlyParsesUrlAndConfiguration() - { - var context = ArgumentParser.ParseArguments("solutionDirectory -u http://github.com/CatenaLogic/GitLink -c someConfiguration"); - - Assert.AreEqual("solutionDirectory", context.SolutionDirectory); - Assert.AreEqual("http://github.com/CatenaLogic/GitLink", context.TargetUrl); - Assert.AreEqual("someConfiguration", context.ConfigurationName); - } - - [TestCase] - public void CorrectlyParsesUrlAndConfigurationAndPlatform() - { - var context = ArgumentParser.ParseArguments("solutionDirectory -u http://github.com/CatenaLogic/GitLink -c someConfiguration -p \"Any CPU\""); - - Assert.AreEqual("solutionDirectory", context.SolutionDirectory); - Assert.AreEqual("http://github.com/CatenaLogic/GitLink", context.TargetUrl); - Assert.AreEqual("someConfiguration", context.ConfigurationName); - Assert.AreEqual("Any CPU", context.PlatformName); - } - - [TestCase] - public void CorrectlyParsesUrlAndConfigurationWithDebug() - { - var context = ArgumentParser.ParseArguments("solutionDirectory -u http://github.com/CatenaLogic/GitLink -debug -c someConfiguration"); - - Assert.AreEqual("solutionDirectory", context.SolutionDirectory); - Assert.AreEqual("http://github.com/CatenaLogic/GitLink", context.TargetUrl); - Assert.AreEqual("someConfiguration", context.ConfigurationName); - Assert.IsTrue(context.IsDebug); - } - - [TestCase] - public void CorrectlyParsesIgnoredProjects() - { - var context = ArgumentParser.ParseArguments("solutionDirectory -u http://github.com/CatenaLogic/GitLink -debug -c someConfiguration -ignore test1,test2"); - - Assert.AreEqual("solutionDirectory", context.SolutionDirectory); - Assert.AreEqual("http://github.com/CatenaLogic/GitLink", context.TargetUrl); - Assert.AreEqual("someConfiguration", context.ConfigurationName); - Assert.IsTrue(context.IsDebug); - - Assert.AreEqual(2, context.IgnoredProjects.Count); - Assert.AreEqual("test1", context.IgnoredProjects[0]); - Assert.AreEqual("test2", context.IgnoredProjects[1]); - } - - [TestCase] - public void CorrectlyParsesIncludedProjects() - { - var context = ArgumentParser.ParseArguments("solutionDirectory -u http://github.com/CatenaLogic/GitLink -debug -c someConfiguration -include test1,test2"); - - Assert.AreEqual("solutionDirectory", context.SolutionDirectory); - Assert.AreEqual("http://github.com/CatenaLogic/GitLink", context.TargetUrl); - Assert.AreEqual("someConfiguration", context.ConfigurationName); - Assert.IsTrue(context.IsDebug); - - Assert.AreEqual(2, context.IncludedProjects.Count); - Assert.AreEqual("test1", context.IncludedProjects[0]); - Assert.AreEqual("test2", context.IncludedProjects[1]); - } - - [TestCase] - public void CorrectlyParsesIncludedProjectsWithRegex() - { - var context = ArgumentParser.ParseArguments("solutionDirectory -u http://github.com/CatenaLogic/GitLink -debug -c someConfiguration -include test1,/*.test*2/"); - - Assert.AreEqual("solutionDirectory", context.SolutionDirectory); - Assert.AreEqual("http://github.com/CatenaLogic/GitLink", context.TargetUrl); - Assert.AreEqual("someConfiguration", context.ConfigurationName); - Assert.IsTrue(context.IsDebug); - - Assert.AreEqual(2, context.IncludedProjects.Count); - Assert.AreEqual("test1", context.IncludedProjects[0]); - Assert.AreEqual("/*.test*2/", context.IncludedProjects[1]); - } - - [TestCase] - public void ThrowsExceptionForUnknownArgument() - { - ExceptionTester.CallMethodAndExpectException(() => ArgumentParser.ParseArguments("solutionDirectory -x logFilePath")); - } - - [TestCase] - public void PowershellDownloadSetToTrue() - { - var context = ArgumentParser.ParseArguments("solutionDirectory -u http://github.com/CatenaLogic/GitLink -powershell"); - - Assert.IsTrue(context.DownloadWithPowershell); - } - } -} \ No newline at end of file diff --git a/src/GitLink.Tests/ContextFacts.cs b/src/GitLink.Tests/ContextFacts.cs deleted file mode 100644 index e5a771e..0000000 --- a/src/GitLink.Tests/ContextFacts.cs +++ /dev/null @@ -1,95 +0,0 @@ -// -------------------------------------------------------------------------------------------------------------------- -// -// Copyright (c) 2014 - 2014 CatenaLogic. All rights reserved. -// -// -------------------------------------------------------------------------------------------------------------------- - - -namespace GitLink.Tests -{ - using System; - using Catel.Test; - using GitLink.Providers; - using NUnit.Framework; - - public class ContextFacts - { - [TestFixture] - public class TheDefaultValues - { - [TestCase] - public void SetsRightDefaultValues() - { - var context = new Context(new ProviderManager()); - - Assert.AreEqual("Release", context.ConfigurationName); - Assert.IsFalse(context.IsHelp); - } - } - - [TestFixture] - public class TheValidateContextMethod - { - [TestCase] - public void ThrowsExceptionForMissingSolutionDirectory() - { - var context = new Context(new ProviderManager()); - - ExceptionTester.CallMethodAndExpectException(() => context.ValidateContext()); - } - - [TestCase] - public void ThrowsExceptionForMissingConfigurationName() - { - var context = new Context(new ProviderManager()) - { - SolutionDirectory = @"c:\source\GitLink", - ConfigurationName = string.Empty - }; - - ExceptionTester.CallMethodAndExpectException(() => context.ValidateContext()); - } - - [TestCase] - public void ThrowsExceptionForMissingTargetUrl() - { - var context = new Context(new ProviderManager()) - { - SolutionDirectory = @"c:\source\GitLink", - }; - - ExceptionTester.CallMethodAndExpectException(() => context.ValidateContext()); - } - - [TestCase] - public void SucceedsForValidContext() - { - var context = new Context(new ProviderManager()) - { - SolutionDirectory = @"c:\source\GitLink", - TargetUrl = "https://github.com/CatenaLogic/GitLink", - }; - - // should not throw - context.ValidateContext(); - } - - [TestCase(@".", @"c:\")] - [TestCase(@"C:\MyDirectory\", @"C:\MyDirectory\")] - [TestCase(@"C:\MyDirectory\..", @"C:\")] - [TestCase(@"C:\MyDirectory\..\TestDirectory\", @"C:\TestDirectory\")] - public void ExpandsDirectoryIfRequired(string solutionDirectory, string expectedValue) - { - Environment.CurrentDirectory = @"c:\"; - - var context = new Context(new ProviderManager()); - context.TargetUrl = "https://github.com/CatenaLogic/GitLink.git"; - context.SolutionDirectory = solutionDirectory; - - context.ValidateContext(); - - Assert.AreEqual(expectedValue, context.SolutionDirectory); - } - } - } -} \ No newline at end of file diff --git a/src/GitLink.Tests/Extensions/ContextExtensionsFacts.cs b/src/GitLink.Tests/Extensions/ContextExtensionsFacts.cs deleted file mode 100644 index 2e6222c..0000000 --- a/src/GitLink.Tests/Extensions/ContextExtensionsFacts.cs +++ /dev/null @@ -1,45 +0,0 @@ -// -------------------------------------------------------------------------------------------------------------------- -// -// Copyright (c) 2014 - 2014 CatenaLogic. All rights reserved. -// -// -------------------------------------------------------------------------------------------------------------------- - - -namespace GitLink.Tests.Extensions -{ - using GitLink.Providers; - using NUnit.Framework; - - public class ContextExtensionsFacts - { - [TestFixture] - public class TheGetRelativePathMethod - { - [TestCase] - public void ReturnsRelativePathWithDirectoryDownwards() - { - var context = new Context(new ProviderManager()) - { - SolutionDirectory = @"c:\source\GitLink" - }; - - var relativePath = context.GetRelativePath(@"c:\source\GitLink\src\subdir1\somefile.cs"); - - Assert.AreEqual(@"src\subdir1\somefile.cs", relativePath); - } - - [TestCase] - public void ReturnsRelativePathWithDirectoryUpwards() - { - var context = new Context(new ProviderManager()) - { - SolutionDirectory = @"c:\source\GitLink" - }; - - var relativePath = context.GetRelativePath(@"c:\source\catel\src\subdir1\somefile.cs"); - - Assert.AreEqual(@"..\catel\src\subdir1\somefile.cs", relativePath); - } - } - } -} \ No newline at end of file diff --git a/src/GitLink.Tests/Extensions/RepositoryExtensionFacts.cs b/src/GitLink.Tests/Extensions/RepositoryExtensionFacts.cs new file mode 100644 index 0000000..6f23ff1 --- /dev/null +++ b/src/GitLink.Tests/Extensions/RepositoryExtensionFacts.cs @@ -0,0 +1,96 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) 2016 Andrew Arnott. All rights reserved. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace GitLink.Tests.Extensions +{ + using System.IO; + using GitTools.Git; + using LibGit2Sharp; + using NUnit.Framework; + + [TestFixture] + public class RepositoryExtensionFacts + { + private static readonly char[] PathSeparators = new char[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar }; + private Repository repo; + + [SetUp] + public void SetUp() + { + var assemblyLocation = System.Reflection.Assembly.GetExecutingAssembly().Location; + var assemblyDirectory = Path.GetDirectoryName(assemblyLocation); + + string repositoryDirectory = GitDirFinder.TreeWalkForGitDir(assemblyDirectory); + repo = new Repository(repositoryDirectory); + } + + [Theory, Pairwise] + public void NormalizeFileAtRoot(bool scrambleCase, bool absolutePath, bool emptySegments, bool forwardSlashes) + { + string expected = "LICENSE"; + string input = GetPathToTest(expected, scrambleCase, absolutePath, emptySegments, forwardSlashes); + string actual = repo.GetNormalizedPath(input); + Assert.AreEqual(expected, actual); + } + + [Theory, Pairwise] + public void NormalizeFileOneDirDeep(bool scrambleCase, bool absolutePath, bool emptySegments, bool forwardSlashes) + { + string expected = "src/EnlistmentInfo.targets"; + string input = GetPathToTest(expected, scrambleCase, absolutePath, emptySegments, forwardSlashes); + string actual = repo.GetNormalizedPath(input); + Assert.AreEqual(expected, actual); + } + + [Theory, Pairwise] + public void NormalizeFileTwoDirsDeep(bool scrambleCase, bool absolutePath, bool emptySegments, bool forwardSlashes) + { + string expected = "src/GitLink/Linker.cs"; + string input = GetPathToTest(expected, scrambleCase, absolutePath, emptySegments, forwardSlashes); + string actual = repo.GetNormalizedPath(input); + Assert.AreEqual(expected, actual); + } + + [Theory] + public void NormalizeMissingFile([Values("T/N", "T\\N", "T", "T/n/C")]string path) + { + Assert.AreEqual(path, repo.GetNormalizedPath(path)); + } + + private string GetPathToTest(string expected, bool scrambleCase, bool absolutePath, bool emptySegments, bool forwardSlashes) + { + string actual = expected; + if (scrambleCase) + { + actual = actual.ToUpperInvariant(); + if (actual == expected) + { + actual = actual.ToLowerInvariant(); + } + } + + if (absolutePath) + { + actual = Path.Combine(repo.Info.WorkingDirectory, actual); + } + + if (emptySegments) + { + if (actual.IndexOfAny(PathSeparators) >= 0) + { + actual = actual.Replace(Path.DirectorySeparatorChar.ToString(), Path.DirectorySeparatorChar.ToString() + Path.DirectorySeparatorChar.ToString()) + .Replace(Path.AltDirectorySeparatorChar.ToString(), Path.AltDirectorySeparatorChar.ToString() + Path.AltDirectorySeparatorChar.ToString()); + } + } + + actual = forwardSlashes + ? actual.Replace('\\', '/') + : actual.Replace('/', '\\'); + + return actual; + } + } +} diff --git a/src/GitLink.Tests/GitLink.Tests.csproj b/src/GitLink.Tests/GitLink.Tests.csproj index 5f8601f..d008f77 100644 --- a/src/GitLink.Tests/GitLink.Tests.csproj +++ b/src/GitLink.Tests/GitLink.Tests.csproj @@ -1,6 +1,5 @@  - Debug AnyCPU @@ -28,6 +27,9 @@ DEBUG;TRACE prompt 4 + ..\..\bin\Debug\GitLink.Tests\GitLink.Tests.XML + CS1591 + GitLink.Tests.ruleset pdbonly @@ -36,40 +38,12 @@ TRACE prompt 4 + ..\..\bin\Release\GitLink.Tests\GitLink.Tests.XML + CS1591 + GitLink.Tests.ruleset - - False - ..\..\lib\ApprovalTests.3.0.8\lib\net40\ApprovalTests.dll - True - - - False - ..\..\lib\ApprovalUtilities.3.0.8\lib\net45\ApprovalUtilities.dll - True - - - ..\..\lib\ApprovalUtilities.3.0.8\lib\net45\ApprovalUtilities.Net45.dll - True - - - ..\..\lib\Catel.Core.4.5.3\lib\net45\Catel.Core.dll - True - - - False - ..\..\lib\GitTools.Core.1.0.0-unstable0021\lib\net45\GitTools.Core.dll - True - - - False - ..\..\lib\LibGit2Sharp.0.21.0.176\lib\net40\LibGit2Sharp.dll - True - - - ..\..\lib\NUnit.2.6.4\lib\nunit.framework.dll - @@ -82,15 +56,14 @@ + + Extensions\RepositoryExtensions.cs + - - - + - - @@ -107,9 +80,6 @@ GitLink - - - @@ -126,7 +96,13 @@ Always - + + + stylecop.json + + + + @@ -147,12 +123,6 @@ - - - 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}. - - - \ No newline at end of file diff --git a/src/GitLink/GitLink.ruleset b/src/GitLink/GitLink.ruleset new file mode 100644 index 0000000..7bbe483 --- /dev/null +++ b/src/GitLink/GitLink.ruleset @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/GitLink/HelpWriter.cs b/src/GitLink/HelpWriter.cs deleted file mode 100644 index f16a2f8..0000000 --- a/src/GitLink/HelpWriter.cs +++ /dev/null @@ -1,51 +0,0 @@ -// -------------------------------------------------------------------------------------------------------------------- -// -// Copyright (c) 2014 - 2014 CatenaLogic. All rights reserved. -// -// -------------------------------------------------------------------------------------------------------------------- - - -namespace GitLink -{ - using System; - using Catel.Reflection; - - public static class HelpWriter - { - public static void WriteAppHeader(Action writer) - { - var assembly = typeof (HelpWriter).Assembly; - - writer(string.Format("{0} v{1}", assembly.Title(), assembly.Version())); - writer("================"); - writer(string.Empty); - } - - public static void WriteHelp(Action writer) - { - const string message = @"Update pdb files to link all sources. This will allow anyone to step through the source code while debugging without a symbol source server. - -Note that the solution must be built because this application will update existing pdb files. - -GitLink [solutionPath] -u [urlToRepository] - - solutionPath The directory containing the solution with the pdb files. - -u [url] Url to remote git repository. - -f [file] Solution file name. - -c [config] Name of the configuration, default value is 'Release'. - -p [platform] Name of the platform, default value is 'AnyCPU'. - -b [branch] Name of the branch to use on the remote repository. - -l [file] The log file to write to. - -s [shaHash] The SHA-1 hash of the commit. - -d [pdbDirectory] The directory where pdb files exists, default value - is the normal project output directory. - -powershell Use an indexing strategy that won't rely on SRCSRV http support, - but use a powershell command for URL download instead. - -errorsaswarnings Don't fail on errors, but treat them as warnings instead. - -skipverify Skip pdb verification in case it causes issues (it's a formality anyway) - -debug Enables debug mode with special dumps of msbuild. -"; - writer(message); - } - } -} \ No newline at end of file diff --git a/src/GitLink/Helpers/PdbStrHelper.cs b/src/GitLink/Helpers/PdbStrHelper.cs index 323b31b..f1fe32d 100644 --- a/src/GitLink/Helpers/PdbStrHelper.cs +++ b/src/GitLink/Helpers/PdbStrHelper.cs @@ -1,21 +1,20 @@ // -------------------------------------------------------------------------------------------------------------------- // -// Copyright (c) 2014 - 2014 CatenaLogic. All rights reserved. +// Copyright (c) 2014 - 2016 CatenaLogic. All rights reserved. // // -------------------------------------------------------------------------------------------------------------------- - namespace GitLink { using System.Diagnostics; using Catel; using Catel.Logging; - public static class PdbStrHelper + internal static class PdbStrHelper { private static readonly ILog Log = LogManager.GetCurrentClassLogger(); - public static void Execute(string pdbStrFileName, string projectPdbFile, string pdbStrFile) + internal static void Execute(string pdbStrFileName, string projectPdbFile, string pdbStrFile) { Argument.IsNotNullOrWhitespace(() => projectPdbFile); Argument.IsNotNullOrWhitespace(() => pdbStrFile); @@ -24,12 +23,33 @@ public static void Execute(string pdbStrFileName, string projectPdbFile, string { Arguments = string.Format("-w -s:srcsrv -p:\"{0}\" -i:\"{1}\"", projectPdbFile, pdbStrFile), CreateNoWindow = true, - UseShellExecute = false + UseShellExecute = false, + RedirectStandardOutput = true, + RedirectStandardError = true, }; var process = new Process(); + bool errorsPrinted = false; + process.OutputDataReceived += (s, e) => + { + if (e.Data != null) + { + Log.Info(e.Data); + } + }; + process.ErrorDataReceived += (s, e) => + { + if (e.Data != null) + { + Log.Error(e.Data); + errorsPrinted = true; + } + }; + process.EnableRaisingEvents = true; process.StartInfo = processStartInfo; process.Start(); + process.BeginErrorReadLine(); + process.BeginOutputReadLine(); process.WaitForExit(); var processExitCode = process.ExitCode; @@ -37,6 +57,12 @@ public static void Execute(string pdbStrFileName, string projectPdbFile, string { throw Log.ErrorAndCreateException("PdbStr exited with unexpected error code '{0}'", processExitCode); } + + // PdbStr can print errors and still return 0 for its exit code. + if (errorsPrinted) + { + throw Log.ErrorAndCreateException("PdbStr printed errors."); + } } } } \ No newline at end of file diff --git a/src/GitLink/Helpers/ProjectHelper.cs b/src/GitLink/Helpers/ProjectHelper.cs deleted file mode 100644 index 866078f..0000000 --- a/src/GitLink/Helpers/ProjectHelper.cs +++ /dev/null @@ -1,158 +0,0 @@ -// -------------------------------------------------------------------------------------------------------------------- -// -// Copyright (c) 2014 - 2014 CatenaLogic. All rights reserved. -// -// -------------------------------------------------------------------------------------------------------------------- - - -namespace GitLink -{ - using System; - using System.Collections; - using System.Collections.Generic; - using System.Linq; - using Catel; - using Catel.Logging; - using Catel.Reflection; - using Microsoft.Build.Evaluation; - using System.IO; - using System.Text.RegularExpressions; - using Build.Construction; - using ImpromptuInterface; - - public static class ProjectHelper - { - private static readonly ILog Log = LogManager.GetCurrentClassLogger(); - - private static readonly Type SolutionParserType; - private static readonly object KnownToBeMsBuildFormat; - - static ProjectHelper() - { - SolutionParserType = TypeCache.GetType("Microsoft.Build.Construction.SolutionParser, Microsoft.Build"); - - var solutionProjectTypeType = TypeCache.GetType("Microsoft.Build.Construction.SolutionProjectType"); - if (solutionProjectTypeType != null) - { - KnownToBeMsBuildFormat = Enum.Parse(solutionProjectTypeType, "KnownToBeMSBuildFormat"); - } - } - - public static IEnumerable GetProjects(string solutionFile, string configurationName, string platformName) - { - var projects = new List(); - var solutionParser = ((object)Impromptu.InvokeConstructor(SolutionParserType)).ActLike(); - - using (var streamReader = new StreamReader(solutionFile)) - { - solutionParser.SolutionReader = streamReader; - solutionParser.ParseSolution(); - var solutionDirectory = Path.GetDirectoryName(solutionFile); - var projectsInSolution = solutionParser.Projects.AllActLike(); - foreach (var projectInSolution in projectsInSolution) - { - var isKnownToBeMsBuildFormat = ObjectHelper.AreEqual(projectInSolution.ProjectType, KnownToBeMsBuildFormat); - var isSelectedForBuild = ProjectIsSelectedForBuild(projectInSolution, configurationName, platformName); - if (!isKnownToBeMsBuildFormat || !isSelectedForBuild) - { - continue; - } - - var relativePath = projectInSolution.RelativePath; - var projectFile = Path.Combine(solutionDirectory, relativePath); - - var project = LoadProject(projectFile, configurationName, platformName, solutionDirectory); - if (project != null) - { - projects.Add(project); - } - } - } - - return projects; - } - - public static Project LoadProject(string projectFile, string configurationName, string platformName, string solutionDirectory) - { - Argument.IsNotNullOrWhitespace(() => projectFile); - Argument.IsNotNullOrWhitespace(() => configurationName); - Argument.IsNotNullOrWhitespace(() => platformName); - Argument.IsNotNullOrWhitespace(() => solutionDirectory); - - if (!solutionDirectory.EndsWith(@"\")) - { - solutionDirectory += @"\"; - } - - try - { - var collections = new Dictionary(); - collections["Configuration"] = configurationName; - collections["Platform"] = platformName; - collections["SolutionDir"] = solutionDirectory; - - var project = new Project(projectFile, collections, null); - return project; - } - catch (Exception ex) - { - Log.Warning("Failed to load project '{0}': {1}", projectFile, ex.Message); - return null; - } - } - - public static bool ShouldBeIgnored(string projectName, ICollection projectsToInclude, ICollection projectsToIgnore) - { - Argument.IsNotNull(() => projectName); - - if (projectsToIgnore.Any(projectToIgnore => ProjectNameMatchesPattern(projectName, projectToIgnore))) - { - return true; - } - - if (projectsToInclude.Count == 0) - { - return false; - } - - if (projectsToInclude.All(projectToInclude => !ProjectNameMatchesPattern(projectName, projectToInclude))) - { - return true; - } - - return false; - } - - // pattern may be either a literal string, and then we'll be comparing literally ignoring case - // or it can be a regex enclosed in slashes like /this-is-my-regex/ - private static bool ProjectNameMatchesPattern(string projectName, string pattern) - { - Argument.IsNotNull(() => pattern); - - if (pattern.Length > 2 && pattern.StartsWith("/") && pattern.EndsWith("/")) - { - var ignoreRegex = new Regex(pattern.Substring(1, pattern.Length - 2), RegexOptions.IgnoreCase); - if (ignoreRegex.IsMatch(projectName)) - { - return true; - } - } - return string.Equals(projectName, pattern, StringComparison.InvariantCultureIgnoreCase); - } - - private static bool ProjectIsSelectedForBuild(IProjectInSolution project, string configurationName, string platformName) - { - var configurationPlatformKey = configurationName + "|" + platformName; - - var configurationsDictionary = (IDictionary)project.ProjectConfigurations; - if (configurationsDictionary.Contains(configurationPlatformKey)) - { - var cis = configurationsDictionary[configurationPlatformKey].ActLike(); - - return cis.IncludeInBuild; - } - - return true; - } - } -} \ No newline at end of file diff --git a/src/GitLink/Helpers/ResourceHelper.cs b/src/GitLink/Helpers/ResourceHelper.cs deleted file mode 100644 index e19cbe7..0000000 --- a/src/GitLink/Helpers/ResourceHelper.cs +++ /dev/null @@ -1,28 +0,0 @@ -// -------------------------------------------------------------------------------------------------------------------- -// -// Copyright (c) 2014 - 2015 CatenaLogic. All rights reserved. -// -// -------------------------------------------------------------------------------------------------------------------- - - -namespace GitLink -{ - using System.IO; - using Catel.Reflection; - - public static class ResourceHelper - { - public static void ExtractEmbeddedResource(string resourceName, string destinationFileName) - { - var assembly = typeof(ResourceHelper).Assembly; - - using (var resource = assembly.GetManifestResourceStream(resourceName)) - { - using (var file = new FileStream(destinationFileName, FileMode.Create, FileAccess.Write)) - { - resource.CopyTo(file); - } - } - } - } -} \ No newline at end of file diff --git a/src/GitLink/LinkMethod.cs b/src/GitLink/LinkMethod.cs new file mode 100644 index 0000000..d1c2e43 --- /dev/null +++ b/src/GitLink/LinkMethod.cs @@ -0,0 +1,24 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) 2014 - 2016 CatenaLogic. All rights reserved. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace GitLink +{ + /// + /// The styles of operations a SRCSRV can perform to retrieve the source code. + /// + public enum LinkMethod + { + /// + /// SRCSRV downloads from a web URL directly. + /// + Http, + + /// + /// Use an indexing strategy that won't rely on SRCSRV http support, but use a powershell command for URL download instead. + /// + Powershell, + } +} diff --git a/src/GitLink/LinkOptions.cs b/src/GitLink/LinkOptions.cs new file mode 100644 index 0000000..145ade8 --- /dev/null +++ b/src/GitLink/LinkOptions.cs @@ -0,0 +1,27 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) 2016 Andrew Arnott. All rights reserved. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace GitLink +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using System.Threading.Tasks; + + public struct LinkOptions + { + public LinkMethod Method { get; set; } + + public bool SkipVerify { get; set; } + + public Uri GitRemoteUrl { get; set; } + + public string CommitId { get; set; } + + public string GitWorkingDirectory { get; set; } + } +} diff --git a/src/GitLink/Linker.cs b/src/GitLink/Linker.cs index fa144bd..28dc0e5 100644 --- a/src/GitLink/Linker.cs +++ b/src/GitLink/Linker.cs @@ -1,10 +1,9 @@ // -------------------------------------------------------------------------------------------------------------------- // -// Copyright (c) 2014 - 2014 CatenaLogic. All rights reserved. +// Copyright (c) 2014 - 2016 CatenaLogic. All rights reserved. // // -------------------------------------------------------------------------------------------------------------------- - namespace GitLink { using System; @@ -12,9 +11,12 @@ namespace GitLink using System.Diagnostics; using System.IO; using System.Linq; + using System.Reflection; using Catel; using Catel.Logging; using GitTools; + using GitTools.Git; + using LibGit2Sharp; using Microsoft.Build.Evaluation; using Pdb; using Providers; @@ -24,234 +26,208 @@ namespace GitLink /// public static class Linker { + private static readonly string FilenamePlaceholder = Uri.EscapeUriString("{filename}"); + private static readonly string RevisionPlaceholder = Uri.EscapeUriString("{revision}"); + private static readonly string PdbStrExePath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "pdbstr.exe"); private static readonly ILog Log = LogManager.GetCurrentClassLogger(); - public static int Link(Context context) + public static bool Link(string pdbPath, LinkOptions options = default(LinkOptions)) { - int? exitCode = null; - - var stopWatch = new Stopwatch(); - stopWatch.Start(); - - context.ValidateContext(); + Argument.IsNotNullOrEmpty(() => pdbPath); - if (!string.IsNullOrEmpty(context.LogFile)) + var projectSrcSrvFile = pdbPath + ".srcsrv"; + string repositoryDirectory; + IReadOnlyCollection sourceFiles; + IReadOnlyDictionary repoSourceFiles; + using (var pdb = new PdbFile(pdbPath)) { - var fileLogListener = new FileLogListener(context.LogFile, 25 * 1024); - fileLogListener.IsDebugEnabled = context.IsDebug; + sourceFiles = pdb.GetFilesAndChecksums().Keys.ToList(); - fileLogListener.IgnoreCatelLogging = true; - LogManager.AddListener(fileLogListener); - } + if (options.GitWorkingDirectory != null) + { + repositoryDirectory = Path.Combine(options.GitWorkingDirectory, ".git"); + } + else + { + string someSourceFile = sourceFiles.FirstOrDefault(); + if (someSourceFile == null) + { + Log.Error("No source files were found in the PDB."); + return false; + } - using (var temporaryFilesContext = new TemporaryFilesContext()) - { - Log.Info("Extracting embedded pdbstr.exe"); + repositoryDirectory = GitDirFinder.TreeWalkForGitDir(Path.GetDirectoryName(someSourceFile)); + if (repositoryDirectory == null) + { + Log.Error("No source files found that are tracked in a git repo."); + return false; + } + } - var pdbStrFile = temporaryFilesContext.GetFile("pdbstr.exe"); - ResourceHelper.ExtractEmbeddedResource("GitLink.Resources.Files.pdbstr.exe", pdbStrFile); + string workingDirectory = Path.GetDirectoryName(repositoryDirectory); + var repository = new Lazy(() => new Repository(repositoryDirectory)); try { - var projects = new List(); - string[] solutionFiles; - if (string.IsNullOrEmpty(context.SolutionFile)) + string commitId = options.CommitId ?? repository.Value.Head.Commits.FirstOrDefault()?.Sha; + if (commitId == null) { - solutionFiles = Directory.GetFiles(context.SolutionDirectory, "*.sln", SearchOption.AllDirectories); + Log.Error("No commit is checked out to HEAD. Have you committed yet?"); + return false; } - else - { - var pathToSolutionFile = Path.Combine(context.SolutionDirectory, context.SolutionFile); - if (!File.Exists(pathToSolutionFile)) - { - Log.Error("Could not find solution file: {0}", pathToSolutionFile); - return -1; - } - solutionFiles = new[] { pathToSolutionFile }; + var providerManager = new Providers.ProviderManager(); + Providers.IProvider provider; + if (options.GitRemoteUrl == null) + { + var candidateProviders = from remote in repository.Value.Network.Remotes + let p = providerManager.GetProvider(remote.Url) + where p != null + select p; + provider = candidateProviders.FirstOrDefault(); } - - foreach (var solutionFile in solutionFiles) + else { - var solutionProjects = ProjectHelper.GetProjects(solutionFile, context.ConfigurationName, context.PlatformName); - projects.AddRange(solutionProjects); + provider = providerManager.GetProvider(options.GitRemoteUrl.AbsoluteUri); } - var provider = context.Provider; if (provider == null) { - throw Log.ErrorAndCreateException("Cannot find a matching provider for '{0}'", context.TargetUrl); + Log.Error("Unable to detect the remote git service."); + return false; } - Log.Info("Using provider '{0}'", provider.GetType().Name); - - var shaHash = context.Provider.GetShaHashOfCurrentBranch(context, temporaryFilesContext); - - Log.Info("Using commit sha '{0}' as version stamp", shaHash); - - var projectCount = projects.Count(); - var failedProjects = new List(); - Log.Info("Found '{0}' project(s)", projectCount); - Log.Info(string.Empty); - - foreach (var project in projects) + try { - try - { - var projectName = project.GetProjectName(); - if (ProjectHelper.ShouldBeIgnored(projectName, context.IncludedProjects, context.IgnoredProjects)) - { - Log.Info("Ignoring '{0}'", project.GetProjectName()); - Log.Info(string.Empty); - continue; - } + Repository repo = repository.Value; + repoSourceFiles = sourceFiles.ToDictionary(e => e, e => repo.GetNormalizedPath(e)); + } + catch (RepositoryNotFoundException) + { + // Normalize using file system since we can't find the git repo. + Log.Warning($"Unable to find git repo at \"{options.GitWorkingDirectory}\". Using file system to find canonical capitalization of file paths."); + repoSourceFiles = sourceFiles.ToDictionary(e => e, e => GetNormalizedPath(e, workingDirectory)); + } - if (context.IsDebug) - { - project.DumpProperties(); - } + if (!options.SkipVerify) + { + Log.Debug("Verifying pdb file"); - if (!LinkProject(context, project, pdbStrFile, shaHash, context.PdbFilesDirectory)) - { - failedProjects.Add(project); - } - } - catch (Exception) + var missingFiles = pdb.FindMissingOrChangedSourceFiles(); + foreach (var missingFile in missingFiles) { - failedProjects.Add(project); + Log.Warning($"File \"{missingFile}\" missing or changed since the PDB was compiled."); } } - Log.Info("All projects are done. {0} of {1} succeeded", projectCount - failedProjects.Count, projectCount); + string rawUrl = provider.RawGitUrl; + if (rawUrl.Contains(RevisionPlaceholder) || rawUrl.Contains(FilenamePlaceholder)) + { + if (!rawUrl.Contains(RevisionPlaceholder) || !rawUrl.Contains(FilenamePlaceholder)) + { + Log.Error("Supplied custom URL pattern must contain both a revision and a filename placeholder."); + return false; + } - if (failedProjects.Count > 0) + rawUrl = rawUrl + .Replace(RevisionPlaceholder, "{0}") + .Replace(FilenamePlaceholder, "%var2%"); + } + else { - Log.Info(string.Empty); - Log.Info("The following projects have failed:"); - Log.Indent(); + rawUrl = $"{rawUrl}/{{0}}/%var2%"; + } - foreach (var failedProject in failedProjects) + Log.Info($"Using {string.Format(rawUrl, commitId)} for source server URLs."); + var srcSrvContext = new SrcSrvContext + { + RawUrl = rawUrl, + DownloadWithPowershell = options.Method == LinkMethod.Powershell, + Revision = commitId, + }; + foreach (var sourceFile in repoSourceFiles) + { + // Skip files that aren't tracked by source control. + if (sourceFile.Value != null) { - Log.Info("* {0}", context.GetRelativePath(failedProject.GetProjectName())); + string relativePathForUrl = ReplaceSlashes(provider, sourceFile.Value); + srcSrvContext.Paths.Add(Tuple.Create(sourceFile.Key, relativePathForUrl)); } + } - Log.Unindent(); + // When using the VisualStudioTeamServicesProvider, add extra infomration to dictionary with VSTS-specific data + if (provider is Providers.VisualStudioTeamServicesProvider) + { + srcSrvContext.VstsData["TFS_COLLECTION"] = provider.CompanyUrl; + srcSrvContext.VstsData["TFS_TEAM_PROJECT"] = provider.ProjectName; + srcSrvContext.VstsData["TFS_REPO"] = provider.ProjectUrl; } - exitCode = (failedProjects.Count == 0) ? 0 : -1; + CreateSrcSrv(projectSrcSrvFile, srcSrvContext); } - catch (GitLinkException ex) + catch (RepositoryNotFoundException) { - Log.Error(ex, "An error occurred"); + Log.Error($"Unable to find git repo at \"{options.GitWorkingDirectory}\"."); + return false; } - catch (Exception ex) + finally { - Log.Error(ex, "An unexpected error occurred"); + if (repository.IsValueCreated) + { + repository.Value.Dispose(); + } } - - stopWatch.Stop(); } - Log.Info(string.Empty); - Log.Info("Completed in '{0}'", stopWatch.Elapsed); + Log.Debug("Created source server link file, updating pdb file \"{0}\"", Catel.IO.Path.GetRelativePath(pdbPath, repositoryDirectory)); + PdbStrHelper.Execute(PdbStrExePath, pdbPath, projectSrcSrvFile); + var indexedFilesCount = repoSourceFiles.Values.Count(v => v != null); + Log.Info($"Remote git source information for {indexedFilesCount}/{sourceFiles.Count} files written to pdb: \"{pdbPath}\""); + + return true; + } - exitCode = exitCode ?? -1; + private static void CreateSrcSrv(string srcsrvFile, SrcSrvContext srcSrvContext) + { + Argument.IsNotNull(nameof(srcSrvContext), srcSrvContext); + Argument.IsNotNullOrWhitespace(nameof(srcSrvContext) + "." + nameof(srcSrvContext.RawUrl), srcSrvContext.RawUrl); + Argument.IsNotNullOrWhitespace(nameof(srcSrvContext) + "." + nameof(srcSrvContext.Revision), srcSrvContext.Revision); + Argument.IsNotNullOrWhitespace(nameof(srcsrvFile), srcsrvFile); - if (context.ErrorsAsWarnings && exitCode != 0) + if (srcSrvContext.VstsData.Count != 0) { - Log.Info("One or more errors occurred, but treating it as warning instead"); - - exitCode = 0; + Log.Debug("Writing VSTS specific bytes to srcsrv file because VstsData was not empty."); + 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)); } - - return exitCode.Value; } - private static bool LinkProject(Context context, Project project, string pdbStrFile, string shaHash, string pathPdbDirectory = null) + private static string GetNormalizedPath(string path, string gitRepoRootDir) { - Argument.IsNotNull(() => context); - Argument.IsNotNull(() => project); + Argument.IsNotNullOrEmpty(nameof(path), path); + Argument.IsNotNullOrEmpty(nameof(gitRepoRootDir), gitRepoRootDir); - try + string relativePath = Catel.IO.Path.GetRelativePath(path, gitRepoRootDir); + string[] segments = relativePath.Split(new char[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar }); + DirectoryInfo currentDir = new DirectoryInfo(gitRepoRootDir); + for (int i = 0; i < segments.Length; i++) { - var projectName = project.GetProjectName(); - - Log.Info("Handling project '{0}'", projectName); - - Log.Indent(); - - var compilables = project.GetCompilableItems().Select(x => x.GetFullFileName()).ToList(); - - var outputPdbFile = project.GetOutputPdbFile(); - var projectPdbFile = pathPdbDirectory != null ? Path.Combine(pathPdbDirectory, Path.GetFileName(outputPdbFile)) : Path.GetFullPath(outputPdbFile); - var projectSrcSrvFile = projectPdbFile + ".srcsrv"; - - var srcSrvContext = new SrcSrvContext - { - Revision = shaHash, - RawUrl = context.Provider.RawGitUrl, - DownloadWithPowershell = context.DownloadWithPowershell - }; - - if (!File.Exists(projectPdbFile)) + string segment = segments[i]; + var next = currentDir.GetFileSystemInfos(segment).FirstOrDefault(); + if (next == null) { - Log.Warning("No pdb file found for '{0}', is project built in '{1}' mode with pdb files enabled? Expected file is '{2}'", projectName, context.ConfigurationName, projectPdbFile); - return false; + Log.Error($"Unable to find path \"{path}\" on disk."); + return path; } - if (!context.SkipVerify) - { - Log.Info("Verifying pdb file"); - - var missingFiles = project.VerifyPdbFiles(compilables, projectPdbFile); - foreach (var missingFile in missingFiles) - { - Log.Warning("Missing file '{0}' or checksum '{1}' did not match", missingFile.Key, missingFile.Value); - } - } - - if (!srcSrvContext.RawUrl.Contains("%var2%") && !srcSrvContext.RawUrl.Contains("{0}")) - { - srcSrvContext.RawUrl = string.Format("{0}/{{0}}/%var2%", srcSrvContext.RawUrl); - } - - foreach (var compilable in compilables) - { - var relativePathForUrl = ReplaceSlashes(context.Provider, compilable.Replace(context.SolutionDirectory, string.Empty)); - while (relativePathForUrl.StartsWith("/")) - { - relativePathForUrl = relativePathForUrl.Substring(1, relativePathForUrl.Length - 1); - } - - srcSrvContext.Paths.Add(new Tuple(compilable, relativePathForUrl)); - } - - // When using the VisualStudioTeamServicesProvider, add extra infomration to dictionary with VSTS-specific data - if (context.Provider.GetType().Name.EqualsIgnoreCase("VisualStudioTeamServicesProvider")) - { - srcSrvContext.VstsData["TFS_COLLECTION"] = context.Provider.CompanyUrl; - srcSrvContext.VstsData["TFS_TEAM_PROJECT"] = context.Provider.ProjectName; - srcSrvContext.VstsData["TFS_REPO"] = context.Provider.ProjectUrl; - } - - project.CreateSrcSrv(projectSrcSrvFile, srcSrvContext); - - Log.Debug("Created source server link file, updating pdb file '{0}'", context.GetRelativePath(projectPdbFile)); - - PdbStrHelper.Execute(pdbStrFile, projectPdbFile, projectSrcSrvFile); - } - catch (Exception ex) - { - Log.Warning(ex, "An error occurred while processing project '{0}'", project.GetProjectName()); - throw; - } - finally - { - Log.Unindent(); - Log.Info(string.Empty); + segments[i] = next.Name; // get canonical capitalization + currentDir = next as DirectoryInfo; } - return true; + return Path.Combine(segments); } private static string ReplaceSlashes(IProvider provider, string relativePathForUrl) diff --git a/src/GitLink/Logging/OutputLogListener.cs b/src/GitLink/Logging/OutputLogListener.cs index c9a269b..cc58a3d 100644 --- a/src/GitLink/Logging/OutputLogListener.cs +++ b/src/GitLink/Logging/OutputLogListener.cs @@ -1,18 +1,17 @@ // -------------------------------------------------------------------------------------------------------------------- // -// Copyright (c) 2014 - 2014 CatenaLogic. All rights reserved. +// Copyright (c) 2014 - 2016 CatenaLogic. All rights reserved. // // -------------------------------------------------------------------------------------------------------------------- - namespace GitLink.Logging { using System; using Catel.Logging; - public class OutputLogListener : ConsoleLogListener + internal class OutputLogListener : ConsoleLogListener { - public OutputLogListener() + internal OutputLogListener() { IgnoreCatelLogging = true; IsDebugEnabled = true; diff --git a/src/GitLink/Resources/Icons/Logo.ico b/src/GitLink/Logo.ico similarity index 100% rename from src/GitLink/Resources/Icons/Logo.ico rename to src/GitLink/Logo.ico diff --git a/src/GitLink/Pdb/Crypto.cs b/src/GitLink/Pdb/Crypto.cs deleted file mode 100644 index f09fff6..0000000 --- a/src/GitLink/Pdb/Crypto.cs +++ /dev/null @@ -1,45 +0,0 @@ -// -------------------------------------------------------------------------------------------------------------------- -// -// Copyright (c) 2014 - 2014 CatenaLogic. All rights reserved. -// -// -------------------------------------------------------------------------------------------------------------------- - - -namespace GitLink.Pdb -{ - using System; - using System.Collections.Generic; - using System.IO; - using System.Linq; - using System.Security.Cryptography; - using Catel; - - public static class Crypto - { - public static Tuple HashFile(HashAlgorithm ha, string file) - { - using (var fs = File.OpenRead(file)) - { - return new Tuple(ha.ComputeHash(fs), file); - } - } - - public static byte[] GetMd5HashForFile(string file) - { - Argument.IsNotNull(() => file); - - using (var ha = MD5.Create()) - { - return HashFile(ha, file).Item1; - } - } - - public static Tuple[] GetMd5HashForFiles(IEnumerable files) - { - using (var ha = MD5.Create()) - { - return files.Select(file => HashFile(ha, file)).ToArray(); - } - } - } -} \ No newline at end of file diff --git a/src/GitLink/Pdb/Hex.cs b/src/GitLink/Pdb/Hex.cs deleted file mode 100644 index a6e1070..0000000 --- a/src/GitLink/Pdb/Hex.cs +++ /dev/null @@ -1,36 +0,0 @@ -// -------------------------------------------------------------------------------------------------------------------- -// -// Copyright (c) 2014 - 2014 CatenaLogic. All rights reserved. -// -// -------------------------------------------------------------------------------------------------------------------- - - -namespace GitLink.Pdb -{ - using System; - using System.Linq; - using Catel; - - public static class Hex - { - public static string Encode(byte[] buffer) - { - Argument.IsNotNullOrEmptyArray(() => buffer); - - return BitConverter.ToString(buffer).Replace("-", string.Empty); - } - - public static byte[] Decode(string hex) - { - if (string.IsNullOrEmpty(hex)) - { - return new byte[0]; - } - - return Enumerable.Range(0, hex.Length) - .Where(x => x % 2 == 0) - .Select(x => Convert.ToByte(hex.Substring(x, 2), 16)) - .ToArray(); - } - } -} \ No newline at end of file diff --git a/src/GitLink/Pdb/PdbFile.cs b/src/GitLink/Pdb/PdbFile.cs index b3d4b23..4bc16d4 100644 --- a/src/GitLink/Pdb/PdbFile.cs +++ b/src/GitLink/Pdb/PdbFile.cs @@ -1,4 +1,10 @@ -namespace GitLink.Pdb +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) 2014 - 2016 CatenaLogic. All rights reserved. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace GitLink.Pdb { using System; using System.Collections.Generic; @@ -8,7 +14,7 @@ using Catel; using Catel.Logging; - public class PdbFile : IDisposable + internal class PdbFile : IDisposable { private static readonly ILog Log = LogManager.GetCurrentClassLogger(); @@ -26,12 +32,12 @@ public class PdbFile : IDisposable private readonly SortedSet _freePages; private readonly byte[] _zerosPage; - public PdbFile(string path) + internal PdbFile(string path) { Argument.IsNotNullOrWhitespace(() => path); Path = path; - + _fs = File.Open(path, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite); _br = new BinaryReader(_fs, Encoding.UTF8, true); _bw = new BinaryWriter(_fs, Encoding.UTF8, true); @@ -45,35 +51,35 @@ public PdbFile(string path) _zerosPage = new byte[_pageByteCount]; } - public string Path { get; private set; } + internal string Path { get; private set; } - public string PathSrcSrv + internal string PathSrcSrv { get { return Path + ".srcsrv"; } } - public bool HasSrcSrv + internal bool HasSrcSrv { get { return Info.NameToPdbName.ContainsKey(SrcSrvContent); } } - public int SrcSrv + internal int SrcSrv { get { return Info.NameToPdbName[SrcSrvContent].Stream; } } - public int RootPage { get; private set; } + internal int RootPage { get; private set; } - public PdbRoot Root { get; private set; } + internal PdbRoot Root { get; private set; } - public PdbRoot Stream0 + internal PdbRoot Stream0 { get { return ReadRoot(Root.Streams[0]); } } - public int PagesFree { get; private set; } + internal int PagesFree { get; private set; } - public int PageCount { get; private set; } + internal int PageCount { get; private set; } private void CheckPdbHeader() { @@ -88,6 +94,7 @@ private void CheckPdbHeader() private void ReadPdbHeader() { // TODO: Create PdbHeader struct + //// code here _pageByteCount = _br.ReadInt32(); // 0x20 PagesFree = _br.ReadInt32(); // 0x24 TODO not sure meaning @@ -102,14 +109,20 @@ private void CheckPdb() var length = _fs.Length; if (length % _pageByteCount != 0) { - throw Log.ErrorAndCreateException("pdb length {0} bytes per page <> 0, {1}, {2}", length, _pageByteCount, + throw Log.ErrorAndCreateException( + "pdb length {0} bytes per page <> 0, {1}, {2}", + length, + _pageByteCount, PageCount); } if (length / _pageByteCount != PageCount) { - throw Log.ErrorAndCreateException("pdb length does not match page count, length: {0}, bytes per page: {1}, page count: {2}", - length, _pageByteCount, PageCount); + throw Log.ErrorAndCreateException( + "pdb length does not match page count, length: {0}, bytes per page: {1}, page count: {2}", + length, + _pageByteCount, + PageCount); } } @@ -150,7 +163,7 @@ private PdbRoot ReadRoot(PdbStream streamRoot) return root; } - public PdbStream GetRootPdbStream() + internal PdbStream GetRootPdbStream() { var pdbStream = new PdbStream(); pdbStream.ByteCount = _rootByteCount; @@ -215,7 +228,7 @@ private byte[] ReadStreamBytes(PdbStream stream) } var j = pages.Length - 1; - ReadPage(bytes, pages[j], j * _pageByteCount, (stream.ByteCount - j * _pageByteCount)); + ReadPage(bytes, pages[j], j * _pageByteCount, stream.ByteCount - (j * _pageByteCount)); } return bytes; @@ -240,7 +253,8 @@ private PdbInfo InternalInfo() var root = GetRoot(); if (root.Streams.Count <= 1) { - throw Log.ErrorAndCreateException("Expected at least 2 streams inside the pdb root, but only found '{0}', cannot read pdb info", + throw Log.ErrorAndCreateException( + "Expected at least 2 streams inside the pdb root, but only found '{0}', cannot read pdb info", root.Streams.Count); } @@ -295,7 +309,7 @@ private PdbInfo InternalInfo() } var tailByteCount = GetRoot().Streams[1].ByteCount - br.BaseStream.Position; - info.Tail = br.ReadBytes((int) tailByteCount); + info.Tail = br.ReadBytes((int)tailByteCount); foreach (var tuple in positions) { @@ -338,19 +352,19 @@ private List AllocPages(int n) return pages; } - public byte[] ReadPdbStreamBytes(PdbStream pdbStream) + internal byte[] ReadPdbStreamBytes(PdbStream pdbStream) { Argument.IsNotNull(() => pdbStream); return ReadStreamBytes(pdbStream); } - public byte[] ReadStreamBytes(int stream) + internal byte[] ReadStreamBytes(int stream) { return ReadStreamBytes(Root.Streams[stream]); } - public PdbInfo Info + internal PdbInfo Info { get { return _info ?? (_info = InternalInfo()); } } diff --git a/src/GitLink/Pdb/PdbInfo.cs b/src/GitLink/Pdb/PdbInfo.cs index fa3ef13..c83d379 100644 --- a/src/GitLink/Pdb/PdbInfo.cs +++ b/src/GitLink/Pdb/PdbInfo.cs @@ -1,21 +1,20 @@ // -------------------------------------------------------------------------------------------------------------------- // -// Copyright (c) 2014 - 2014 CatenaLogic. All rights reserved. +// Copyright (c) 2014 - 2016 CatenaLogic. All rights reserved. // // -------------------------------------------------------------------------------------------------------------------- - namespace GitLink.Pdb { using System; using System.Collections.Generic; using Catel; - public class PdbInfo + internal class PdbInfo { - public PdbInfo() + internal PdbInfo() { - Guid = new Guid(); + Guid = default(Guid); StreamToPdbName = new SortedDictionary(); NameToPdbName = new SortedDictionary(); FlagIndexToPdbName = new SortedDictionary(); @@ -24,26 +23,37 @@ public PdbInfo() Tail = new byte[0]; } - public int Version { get; set; } - public int Signature { get; set; } - public Guid Guid { get; set; } - public int Age { get; set; } - public int FlagIndexMax { get; set; } - public int FlagCount { get; set; } - public IDictionary StreamToPdbName { get; private set; } - public IDictionary NameToPdbName { get; private set; } - public IDictionary FlagIndexToPdbName { get; private set; } - public SortedSet FlagIndexes { get; private set; } - public string[] SrcSrv { get; set; } - public byte[] Tail { get; set; } - - public void ClearFlags() + internal int Version { get; set; } + + internal int Signature { get; set; } + + internal Guid Guid { get; set; } + + internal int Age { get; set; } + + internal int FlagIndexMax { get; set; } + + internal int FlagCount { get; set; } + + internal IDictionary StreamToPdbName { get; private set; } + + internal IDictionary NameToPdbName { get; private set; } + + internal IDictionary FlagIndexToPdbName { get; private set; } + + internal SortedSet FlagIndexes { get; private set; } + + internal string[] SrcSrv { get; set; } + + internal byte[] Tail { get; set; } + + internal void ClearFlags() { FlagIndexes.Clear(); FlagIndexToPdbName.Clear(); } - public void AddFlag(PdbName name) + internal void AddFlag(PdbName name) { Argument.IsNotNull(() => name); @@ -51,7 +61,7 @@ public void AddFlag(PdbName name) FlagIndexToPdbName.Add(name.FlagIndex, name); } - public void AddName(PdbName name) + internal void AddName(PdbName name) { Argument.IsNotNull(() => name); diff --git a/src/GitLink/Pdb/PdbName.cs b/src/GitLink/Pdb/PdbName.cs index 1980dd0..f74ab66 100644 --- a/src/GitLink/Pdb/PdbName.cs +++ b/src/GitLink/Pdb/PdbName.cs @@ -1,21 +1,22 @@ // -------------------------------------------------------------------------------------------------------------------- // -// Copyright (c) 2014 - 2014 CatenaLogic. All rights reserved. +// Copyright (c) 2014 - 2016 CatenaLogic. All rights reserved. // // -------------------------------------------------------------------------------------------------------------------- - namespace GitLink.Pdb { - public class PdbName + internal class PdbName { - public PdbName(string name = "") + internal PdbName(string name = "") { Name = name; } - public int Stream { get; set; } - public string Name { get; set; } - public int FlagIndex { get; set; } + internal int Stream { get; set; } + + internal string Name { get; set; } + + internal int FlagIndex { get; set; } } } \ No newline at end of file diff --git a/src/GitLink/Pdb/PdbRoot.cs b/src/GitLink/Pdb/PdbRoot.cs index 8050edf..e13ad5e 100644 --- a/src/GitLink/Pdb/PdbRoot.cs +++ b/src/GitLink/Pdb/PdbRoot.cs @@ -1,18 +1,17 @@ // -------------------------------------------------------------------------------------------------------------------- // -// Copyright (c) 2014 - 2014 CatenaLogic. All rights reserved. +// Copyright (c) 2014 - 2016 CatenaLogic. All rights reserved. // // -------------------------------------------------------------------------------------------------------------------- - namespace GitLink.Pdb { using System.Collections.Generic; using Catel; - public class PdbRoot + internal class PdbRoot { - public PdbRoot(PdbStream stream) + internal PdbRoot(PdbStream stream) { Argument.IsNotNull(() => stream); @@ -20,10 +19,11 @@ public PdbRoot(PdbStream stream) Streams = new List(); } - public PdbStream Stream { get; set; } - public List Streams { get; private set; } + internal PdbStream Stream { get; set; } + + internal List Streams { get; private set; } - public int AddStream(PdbStream stream) + internal int AddStream(PdbStream stream) { Streams.Add(stream); diff --git a/src/GitLink/Pdb/PdbStream.cs b/src/GitLink/Pdb/PdbStream.cs index 4468b07..1928258 100644 --- a/src/GitLink/Pdb/PdbStream.cs +++ b/src/GitLink/Pdb/PdbStream.cs @@ -1,15 +1,15 @@ // -------------------------------------------------------------------------------------------------------------------- // -// Copyright (c) 2014 - 2014 CatenaLogic. All rights reserved. +// Copyright (c) 2014 - 2016 CatenaLogic. All rights reserved. // // -------------------------------------------------------------------------------------------------------------------- - namespace GitLink.Pdb { - public class PdbStream + internal class PdbStream { - public int ByteCount { get; set; } - public int[] Pages { get; set; } + internal int ByteCount { get; set; } + + internal int[] Pages { get; set; } } } \ No newline at end of file diff --git a/src/GitLink/Pdb/SrcSrv.cs b/src/GitLink/Pdb/SrcSrv.cs index 6affdda..ad5b66e 100644 --- a/src/GitLink/Pdb/SrcSrv.cs +++ b/src/GitLink/Pdb/SrcSrv.cs @@ -1,10 +1,9 @@ // -------------------------------------------------------------------------------------------------------------------- // -// Copyright (c) 2014 - 2014 CatenaLogic. All rights reserved. +// Copyright (c) 2014 - 2016 CatenaLogic. All rights reserved. // // -------------------------------------------------------------------------------------------------------------------- - namespace GitLink.Pdb { using System; @@ -12,14 +11,14 @@ namespace GitLink.Pdb using System.IO; using Catel; - public static class SrcSrv + internal static class SrcSrv { private static string CreateTarget(string rawUrl, string revision) { return string.Format(rawUrl, revision); } - public static byte[] Create(string rawUrl, string revision, IEnumerable> paths, bool downloadWithPowershell) + internal static byte[] Create(string rawUrl, string revision, IEnumerable> paths, bool downloadWithPowershell) { Argument.IsNotNullOrWhitespace(() => rawUrl); Argument.IsNotNullOrWhitespace(() => revision); @@ -29,22 +28,23 @@ public static byte[] Create(string rawUrl, string revision, IEnumerable> paths, Dictionary vstsData = null) + internal static byte[] CreateVsts(string revision, IEnumerable> paths, Dictionary vstsData = null) { Argument.IsNotNullOrWhitespace(() => revision); diff --git a/src/GitLink/Pdb/SrcSrvContext.cs b/src/GitLink/Pdb/SrcSrvContext.cs index 90f3d1f..5821738 100644 --- a/src/GitLink/Pdb/SrcSrvContext.cs +++ b/src/GitLink/Pdb/SrcSrvContext.cs @@ -4,29 +4,27 @@ // // -------------------------------------------------------------------------------------------------------------------- - namespace GitLink.Pdb { using System; using System.Collections.Generic; - public class SrcSrvContext + internal class SrcSrvContext { - public SrcSrvContext() + internal SrcSrvContext() { Paths = new List>(); VstsData = new Dictionary(); - } - public string RawUrl { get; set; } + internal string RawUrl { get; set; } - public bool DownloadWithPowershell { get; set; } + internal bool DownloadWithPowershell { get; set; } - public string Revision { get; set; } + internal string Revision { get; set; } - public List> Paths { get; private set; } + internal List> Paths { get; private set; } - public Dictionary VstsData { get; private set; } + internal Dictionary VstsData { get; private set; } } } diff --git a/src/GitLink/Program.cs b/src/GitLink/Program.cs index 92d81f2..e8ff243 100644 --- a/src/GitLink/Program.cs +++ b/src/GitLink/Program.cs @@ -1,13 +1,15 @@ // -------------------------------------------------------------------------------------------------------------------- // -// Copyright (c) 2014 - 2014 CatenaLogic. All rights reserved. +// Copyright (c) 2014 - 2016 CatenaLogic. All rights reserved. // // -------------------------------------------------------------------------------------------------------------------- - namespace GitLink { using System; + using System.CommandLine; + using System.Diagnostics; + using System.IO; using Catel.Logging; using Logging; @@ -24,51 +26,67 @@ private static int Main(string[] args) var consoleLogListener = new OutputLogListener(); LogManager.AddListener(consoleLogListener); - try + Uri remoteGitUrl = null; + string commitId = null; + string baseDir = null; + string pdbPath = null; + bool skipVerify = false; + LinkMethod method = LinkMethod.Http; + var arguments = ArgumentSyntax.Parse(args, syntax => { - HelpWriter.WriteAppHeader(s => Log.Write(LogEvent.Info, s)); - - Log.Info("Arguments: {0}", string.Join(" ", args)); - Log.Info(string.Empty); - - var context = ArgumentParser.ParseArguments(args); - if (context.IsHelp) + syntax.DefineOption("m|method", ref method, v => (LinkMethod)Enum.Parse(typeof(LinkMethod), v, true), "The method for SRCSRV to retrieve source code. One of <" + string.Join("|", Enum.GetNames(typeof(LinkMethod))) + ">. Default is " + method + "."); + syntax.DefineOption("u|url", ref remoteGitUrl, s => new Uri(s, UriKind.Absolute), "Url to remote git repository."); + syntax.DefineOption("commit", ref commitId, "The git ref to assume all the source code belongs to."); + syntax.DefineOption("baseDir", ref baseDir, "The path to the root of the git repo."); + syntax.DefineOption("s|skipVerify", ref skipVerify, "Verify all source files are available in source control."); + syntax.DefineParameter("pdb", ref pdbPath, "The PDB to add source indexing to."); + + if (!string.IsNullOrEmpty(pdbPath) && !File.Exists(pdbPath)) { - HelpWriter.WriteHelp(s => Log.Write(LogEvent.Info, s)); - - WaitForKeyPress(); - - return 0; + syntax.ReportError($"File not found: \"{pdbPath}\""); } - consoleLogListener.IsDebugEnabled = context.IsDebug; - - var result = Linker.Link(context); - -#if DEBUG - WaitForKeyPress(); -#endif + if (!string.IsNullOrEmpty(baseDir) && !Directory.Exists(baseDir)) + { + syntax.ReportError($"Directory not found: \"{baseDir}\""); + } + }); - return result; - } - catch (Exception ex) + if (string.IsNullOrEmpty(pdbPath)) { - Log.Error(ex, "An unexpected error occurred"); - -#if DEBUG - WaitForKeyPress(); -#endif + Log.Info(arguments.GetHelpText()); + return 1; + } - return -1; + var options = new LinkOptions + { + GitRemoteUrl = remoteGitUrl, + GitWorkingDirectory = baseDir != null ? Catel.IO.Path.GetFullPath(baseDir, Environment.CurrentDirectory) : null, + CommitId = commitId, + SkipVerify = skipVerify, + Method = method, + }; + + if (!Linker.Link(pdbPath, options)) + { + return 1; } + + WaitForKeyPressWhenDebugging(); + return 0; } - private static void WaitForKeyPress() + [Conditional("DEBUG")] + private static void WaitForKeyPressWhenDebugging() { - Log.Info(string.Empty); - Log.Info("Press any key to continue"); + // VS only closes the window immediately when debugging + if (Debugger.IsAttached) + { + Log.Info(string.Empty); + Log.Info("Press any key to continue"); - Console.ReadKey(); + Console.ReadKey(); + } } } } \ No newline at end of file diff --git a/src/GitLink/Properties/AssemblyInfo.cs b/src/GitLink/Properties/AssemblyInfo.cs index 18211b0..7e0c82d 100644 --- a/src/GitLink/Properties/AssemblyInfo.cs +++ b/src/GitLink/Properties/AssemblyInfo.cs @@ -1,24 +1,12 @@ // -------------------------------------------------------------------------------------------------------------------- // -// Copyright (c) 2014 - 2014 CatenaLogic. All rights reserved. +// Copyright (c) 2014 - 2017 CatenaLogic. All rights reserved. // // -------------------------------------------------------------------------------------------------------------------- using System.Reflection; -using System.Runtime.InteropServices; - -// All other assembly info is defined in SharedAssembly.cs [assembly: AssemblyTitle("GitLink")] [assembly: AssemblyProduct("GitLink")] -[assembly: AssemblyDescription("GitLink 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 +[assembly: AssemblyDescription("GitLink library")] \ No newline at end of file diff --git a/src/GitLink/Providers/BitBucketProvider.cs b/src/GitLink/Providers/BitBucketProvider.cs index 803a392..eb303cd 100644 --- a/src/GitLink/Providers/BitBucketProvider.cs +++ b/src/GitLink/Providers/BitBucketProvider.cs @@ -1,10 +1,9 @@ // -------------------------------------------------------------------------------------------------------------------- // -// Copyright (c) 2014 - 2014 CatenaLogic. All rights reserved. +// Copyright (c) 2014 - 2016 CatenaLogic. All rights reserved. // // -------------------------------------------------------------------------------------------------------------------- - namespace GitLink.Providers { using System; @@ -13,21 +12,18 @@ namespace GitLink.Providers public class BitBucketProvider : ProviderBase { - private readonly Regex _bitBucketRegex = new Regex(@"(?(?(?:https://)?bitbucket\.org/(?[^/]+))/(?[^/]+))"); + private static readonly Regex HostingUrlPattern = new Regex(@"(?(?(?:https://)?bitbucket\.org/(?[^/]+))/(?[^/]+))"); - public BitBucketProvider() + public BitBucketProvider() : base(new GitPreparer()) { } - public override string RawGitUrl - { - get { return String.Format("https://bitbucket.org/{0}/{1}/raw", CompanyName, ProjectName); } - } + public override string RawGitUrl => $"https://bitbucket.org/{CompanyName}/{ProjectName}/raw"; public override bool Initialize(string url) { - var match = _bitBucketRegex.Match(url); + var match = HostingUrlPattern.Match(url); if (!match.Success) { diff --git a/src/GitLink/Providers/CustomRawUrlProvider.cs b/src/GitLink/Providers/CustomRawUrlProvider.cs index dc7b5d6..ff43263 100644 --- a/src/GitLink/Providers/CustomRawUrlProvider.cs +++ b/src/GitLink/Providers/CustomRawUrlProvider.cs @@ -1,4 +1,10 @@ -namespace GitLink.Providers +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) 2014 - 2016 CatenaLogic. All rights reserved. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace GitLink.Providers { using System; using System.Text.RegularExpressions; @@ -6,7 +12,7 @@ public sealed class CustomRawUrlProvider : ProviderBase { - private readonly Regex _regex = new Regex(@"https?://.+"); + private static readonly Regex HostingUrlPattern = new Regex(@"https?://.+"); private string _rawUrl; @@ -15,17 +21,11 @@ public CustomRawUrlProvider() { } - public override string RawGitUrl - { - get - { - return _rawUrl; - } - } + public override string RawGitUrl => _rawUrl; public override bool Initialize(string url) { - if (string.IsNullOrEmpty(url) || !_regex.IsMatch(url)) + if (string.IsNullOrEmpty(url) || !HostingUrlPattern.IsMatch(url)) { return false; } diff --git a/src/GitLink/Providers/CustomUrlProvider.cs b/src/GitLink/Providers/CustomUrlProvider.cs index 8086b42..07b1cbd 100644 --- a/src/GitLink/Providers/CustomUrlProvider.cs +++ b/src/GitLink/Providers/CustomUrlProvider.cs @@ -1,13 +1,19 @@ -namespace GitLink.Providers +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) 2014 - 2016 CatenaLogic. All rights reserved. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace GitLink.Providers { - using GitTools.Git; using System.Text.RegularExpressions; + using GitTools.Git; public sealed class CustomUrlProvider : ProviderBase { private const string FileNamePlaceHolder = "{filename}"; private const string RevisionPlaceHolder = "{revision}"; - private readonly Regex _regexUrl = new Regex(@"https?://.+"); + private static readonly Regex HostingUrlPattern = new Regex(@"https?://.+"); private string _rawUrl; @@ -16,29 +22,23 @@ public CustomUrlProvider() { } - public override string RawGitUrl - { - get - { - return _rawUrl; - } - } + public override string RawGitUrl => _rawUrl; public override bool Initialize(string url) { - if (string.IsNullOrEmpty(url) || !_regexUrl.IsMatch(url) || + if (string.IsNullOrEmpty(url) || !HostingUrlPattern.IsMatch(url) || (!url.Contains(FileNamePlaceHolder) && !url.Contains(RevisionPlaceHolder))) { return false; } - if(url.Contains(FileNamePlaceHolder)) - { + if (url.Contains(FileNamePlaceHolder)) + { _rawUrl = url.Replace(FileNamePlaceHolder, "%var2%"); } if (url.Contains(RevisionPlaceHolder)) - { + { _rawUrl = _rawUrl.Replace(RevisionPlaceHolder, "{0}"); } diff --git a/src/GitLink/Providers/GitHubProvider.cs b/src/GitLink/Providers/GitHubProvider.cs index 927e4d5..318cceb 100644 --- a/src/GitLink/Providers/GitHubProvider.cs +++ b/src/GitLink/Providers/GitHubProvider.cs @@ -1,10 +1,9 @@ // -------------------------------------------------------------------------------------------------------------------- // -// Copyright (c) 2014 - 2014 CatenaLogic. All rights reserved. +// Copyright (c) 2014 - 2016 CatenaLogic. All rights reserved. // // -------------------------------------------------------------------------------------------------------------------- - namespace GitLink.Providers { using System; @@ -13,21 +12,18 @@ namespace GitLink.Providers public class GitHubProvider : ProviderBase { - private readonly Regex _gitHubRegex = new Regex(@"^(?(?(?:https://)?github\.com/(?[^/]+))/(?[^/]+?)(\.git)?)$"); + private static readonly Regex HostingUrlPattern = new Regex(@"^(?(?(?:https://)?github\.com/(?[^/]+))/(?[^/]+?)(\.git)?)$"); - public GitHubProvider() + public GitHubProvider() : base(new GitPreparer()) { } - public override string RawGitUrl - { - get { return String.Format("https://raw.github.com/{0}/{1}", CompanyName, ProjectName); } - } + public override string RawGitUrl => $"https://raw.github.com/{CompanyName}/{ProjectName}"; public override bool Initialize(string url) { - var match = _gitHubRegex.Match(url); + var match = HostingUrlPattern.Match(url); if (!match.Success) { diff --git a/src/GitLink/Providers/Interfaces/IBackSlashSupport.cs b/src/GitLink/Providers/Interfaces/IBackSlashSupport.cs index f29e981..8a43afc 100644 --- a/src/GitLink/Providers/Interfaces/IBackSlashSupport.cs +++ b/src/GitLink/Providers/Interfaces/IBackSlashSupport.cs @@ -8,13 +8,13 @@ namespace GitLink.Providers { /// - /// Implementing this interface path resolver gives provider a change to determine + /// Implementing this interface path resolver gives provider a change to determine /// if back slashes are supported or should be replaced. /// public interface IBackSlashSupport { /// - /// Gets whether back slashes in paths are supported or should be replaced. + /// Gets a value indicating whether back slashes in paths are supported or should be replaced. /// /// /// If value is true, back slashes are not replaced; otherwise back slahes are replaced by forward slashes. diff --git a/src/GitLink/Providers/Interfaces/IProvider.cs b/src/GitLink/Providers/Interfaces/IProvider.cs index 9ec44e2..59f5513 100644 --- a/src/GitLink/Providers/Interfaces/IProvider.cs +++ b/src/GitLink/Providers/Interfaces/IProvider.cs @@ -1,10 +1,9 @@ // -------------------------------------------------------------------------------------------------------------------- // -// Copyright (c) 2014 - 2014 CatenaLogic. All rights reserved. +// Copyright (c) 2014 - 2016 CatenaLogic. All rights reserved. // // -------------------------------------------------------------------------------------------------------------------- - namespace GitLink.Providers { using GitTools; @@ -42,7 +41,5 @@ public interface IProvider string RawGitUrl { get; } bool Initialize(string url); - - string GetShaHashOfCurrentBranch(Context context, TemporaryFilesContext temporaryFilesContext); } } \ No newline at end of file diff --git a/src/GitLink/Providers/Interfaces/IProviderManager.cs b/src/GitLink/Providers/Interfaces/IProviderManager.cs index 30845ef..555259d 100644 --- a/src/GitLink/Providers/Interfaces/IProviderManager.cs +++ b/src/GitLink/Providers/Interfaces/IProviderManager.cs @@ -1,10 +1,9 @@ // -------------------------------------------------------------------------------------------------------------------- // -// Copyright (c) 2014 - 2014 CatenaLogic. All rights reserved. +// Copyright (c) 2014 - 2016 CatenaLogic. All rights reserved. // // -------------------------------------------------------------------------------------------------------------------- - namespace GitLink.Providers { public interface IProviderManager diff --git a/src/GitLink/Providers/ProviderBase.cs b/src/GitLink/Providers/ProviderBase.cs index 32176ab..488ac8b 100644 --- a/src/GitLink/Providers/ProviderBase.cs +++ b/src/GitLink/Providers/ProviderBase.cs @@ -1,10 +1,9 @@ // -------------------------------------------------------------------------------------------------------------------- // -// Copyright (c) 2014 - 2014 CatenaLogic. All rights reserved. +// Copyright (c) 2014 - 2016 CatenaLogic. All rights reserved. // // -------------------------------------------------------------------------------------------------------------------- - namespace GitLink.Providers { using System; @@ -60,50 +59,5 @@ protected ProviderBase(IRepositoryPreparer repositoryPreparer) public abstract string RawGitUrl { get; } public abstract bool Initialize(string url); - - public string GetShaHashOfCurrentBranch(Context context, TemporaryFilesContext temporaryFilesContext) - { - Argument.IsNotNull(() => context); - - string commitSha = null; - var repositoryDirectory = context.SolutionDirectory; - - if (_repositoryPreparer.IsPreparationRequired(context)) - { - Log.Info("No local repository is found in '{0}', creating a temporary one", repositoryDirectory); - - repositoryDirectory = _repositoryPreparer.Prepare(context, temporaryFilesContext); - } - - repositoryDirectory = GitDirFinder.TreeWalkForGitDir(repositoryDirectory); - - using (var repository = new Repository(repositoryDirectory)) - { - if (string.IsNullOrEmpty(context.ShaHash)) - { - Log.Info("No sha hash is available on the context, retrieving latest commit of current branch"); - - var lastCommit = repository.Commits.First(); - commitSha = lastCommit.Sha; - } - else - { - Log.Info("Checking if commit with sha hash '{0}' exists on the repository", context.ShaHash); - - var commit = repository.Commits.FirstOrDefault(c => string.Equals(c.Sha, context.ShaHash, StringComparison.OrdinalIgnoreCase)); - if (commit != null) - { - commitSha = commit.Sha; - } - } - } - - if (commitSha == null) - { - throw Log.ErrorAndCreateException("Cannot find commit '{0}' in repo.", context.ShaHash); - } - - return commitSha; - } } } \ No newline at end of file diff --git a/src/GitLink/Providers/ProviderManager.cs b/src/GitLink/Providers/ProviderManager.cs index 8fc4304..0dfe3e9 100644 --- a/src/GitLink/Providers/ProviderManager.cs +++ b/src/GitLink/Providers/ProviderManager.cs @@ -1,10 +1,9 @@ // -------------------------------------------------------------------------------------------------------------------- // -// Copyright (c) 2014 - 2014 CatenaLogic. All rights reserved. +// Copyright (c) 2014 - 2016 CatenaLogic. All rights reserved. // // -------------------------------------------------------------------------------------------------------------------- - namespace GitLink.Providers { using Catel.IoC; @@ -20,7 +19,7 @@ public ProviderBase GetProvider(string url) foreach (var providerType in providerTypes) { - var provider = (ProviderBase) typeFactory.CreateInstance(providerType); + var provider = (ProviderBase)typeFactory.CreateInstance(providerType); if (provider.Initialize(url)) { return provider; diff --git a/src/GitLink/Providers/UncProvider.cs b/src/GitLink/Providers/UncProvider.cs index 46d60a8..5154a66 100644 --- a/src/GitLink/Providers/UncProvider.cs +++ b/src/GitLink/Providers/UncProvider.cs @@ -7,8 +7,8 @@ namespace GitLink.Providers { - using GitTools.Git; using System.Text.RegularExpressions; + using GitTools.Git; /// /// A git provider for UNC network paths. diff --git a/src/GitLink/Providers/VisualStudioTeamServicesProvider.cs b/src/GitLink/Providers/VisualStudioTeamServicesProvider.cs index 047dd7f..f891079 100644 --- a/src/GitLink/Providers/VisualStudioTeamServicesProvider.cs +++ b/src/GitLink/Providers/VisualStudioTeamServicesProvider.cs @@ -4,7 +4,6 @@ // // -------------------------------------------------------------------------------------------------------------------- - namespace GitLink.Providers { using System; @@ -14,21 +13,18 @@ namespace GitLink.Providers public class VisualStudioTeamServicesProvider : ProviderBase { - private readonly Regex _visualStudioTeamServicesRegex = new Regex(@"(?(?(?:https://)?(?([a-zA-Z0-9\-\.]*)?)\.visualstudio\.com/)(?[a-zA-Z0-9\-\.]*)/?_git/(?[^/]+))"); + private static readonly Regex HostingUrlPattern = new Regex(@"(?(?(?:https://)?(?([a-zA-Z0-9\-\.]*)?)\.visualstudio\.com/)(?[a-zA-Z0-9\-\.]*)/?_git//?(?[^/]+))"); public VisualStudioTeamServicesProvider() : base(new GitPreparer()) { } - public override string RawGitUrl - { - get { return string.Empty; } - } + public override string RawGitUrl => string.Empty; public override bool Initialize(string url) { - var match = _visualStudioTeamServicesRegex.Match(url); + var match = HostingUrlPattern.Match(url); if (!match.Success) { @@ -44,7 +40,7 @@ public override bool Initialize(string url) ProjectName = match.Groups["repo"].Value; } - // In the VSTS provider, the ProjectUrl will represent + // In the VSTS provider, the ProjectUrl will represent // the repository's name. ProjectUrl = match.Groups["repo"].Value; diff --git a/src/GitLink/packages.config b/src/GitLink/packages.config deleted file mode 100644 index d1a2b4f..0000000 --- a/src/GitLink/packages.config +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/src/GitLink/Resources/Files/pdbstr.exe b/src/GitLink/pdbstr.exe similarity index 100% rename from src/GitLink/Resources/Files/pdbstr.exe rename to src/GitLink/pdbstr.exe diff --git a/src/GitLink/project.json b/src/GitLink/project.json new file mode 100644 index 0000000..2c78d6f --- /dev/null +++ b/src/GitLink/project.json @@ -0,0 +1,25 @@ +{ + "dependencies": { + "Catel.Core": "4.5.3", + "EnlistmentInfo": { + "version": "1.0.4", + "suppressParent": "none" + }, + "GitTools.Core": "1.0.0-unstable0021", + "GitVersionTask": "4.0.0-beta0009", + "ImpromptuInterface": "6.2.2", + "LibGit2Sharp": "0.21.0.176", + "NuProj.Common": "0.11.14-beta", + "StyleCop.Analyzers": { + "version": "1.0.0", + "type": "build" + }, + "System.CommandLine": "0.1.0-e161008-1" + }, + "frameworks": { + "net45": {} + }, + "runtimes": { + "win": {} + } +} \ No newline at end of file diff --git a/src/GitLink/stylecop.json b/src/GitLink/stylecop.json new file mode 100644 index 0000000..d600716 --- /dev/null +++ b/src/GitLink/stylecop.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "documentationRules": { + "companyName": "CatenaLogic", + "copyrightText": " Copyright (c) 2014 - 2016 {companyName}. All rights reserved." + } + } +} diff --git a/src/GitLink/Resources/Files/winsdk.redist.txt b/src/GitLink/winsdk.redist.txt similarity index 100% rename from src/GitLink/Resources/Files/winsdk.redist.txt rename to src/GitLink/winsdk.redist.txt diff --git a/src/GitLinkTask/GitLink.props b/src/GitLinkTask/GitLink.props new file mode 100644 index 0000000..f8131b3 --- /dev/null +++ b/src/GitLinkTask/GitLink.props @@ -0,0 +1,7 @@ + + + + true + true + + diff --git a/src/GitLinkTask/GitLink.targets b/src/GitLinkTask/GitLink.targets index c4e1f49..2e25ce8 100644 --- a/src/GitLinkTask/GitLink.targets +++ b/src/GitLinkTask/GitLink.targets @@ -1,11 +1,18 @@  - + - - - + + + \ No newline at end of file diff --git a/src/GitLinkTask/GitLinkTask.csproj b/src/GitLinkTask/GitLinkTask.csproj index f0a98d5..d427497 100644 --- a/src/GitLinkTask/GitLinkTask.csproj +++ b/src/GitLinkTask/GitLinkTask.csproj @@ -23,6 +23,8 @@ 4 true 1591;1998 + ..\..\bin\Debug\GitLinkTask\GitLinkTask.XML + GitLinkTask.ruleset AnyCPU @@ -34,33 +36,47 @@ 4 1591;1998 true + ..\..\bin\Release\GitLinkTask\GitLinkTask.XML + GitLinkTask.ruleset - - Properties\SolutionAssemblyInfo.cs - - - + + + ..\..\lib\Catel.Core.4.3.0\lib\net45\Catel.Core.dll + - + + PreserveNewest + + + PreserveNewest + + + + + + + + {d68add77-913f-46d2-9a4f-5cc71c4718d8} + GitLink + + + + + {d68add77-913f-46d2-9a4f-5cc71c4718d8} + GitLink + - \ No newline at end of file diff --git a/src/GitLinkTask/GitLinkTask.ruleset b/src/GitLinkTask/GitLinkTask.ruleset new file mode 100644 index 0000000..a7d6baf --- /dev/null +++ b/src/GitLinkTask/GitLinkTask.ruleset @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/GitLinkTask/LinkPdbToGitRemote.cs b/src/GitLinkTask/LinkPdbToGitRemote.cs new file mode 100644 index 0000000..2b4a06c --- /dev/null +++ b/src/GitLinkTask/LinkPdbToGitRemote.cs @@ -0,0 +1,80 @@ +// Copyright (c) Andrew Arnott. All rights reserved. + +namespace GitLinkTask +{ + using System; + using Catel.Logging; + using global::GitLink; + using Microsoft.Build.Framework; + using Microsoft.Build.Utilities; + + public class LinkPdbToGitRemote : Task + { + [Required] + public ITaskItem PdbFile { get; set; } + + public string Method + { + get { return MethodEnum.ToString(); } + set { MethodEnum = string.IsNullOrEmpty(value) ? LinkMethod.Http : (LinkMethod)Enum.Parse(typeof(LinkMethod), value); } + } + + public bool SkipVerify { get; set; } + + public string GitRemoteUrl { get; set; } + + public string GitCommitId { get; set; } + + public string GitWorkingDirectory { get; set; } + + private LinkMethod MethodEnum { get; set; } + + public override bool Execute() + { + LogManager.AddListener(new MSBuildListener(Log)); + + var options = new LinkOptions + { + Method = MethodEnum, + SkipVerify = SkipVerify, + GitRemoteUrl = GitRemoteUrl != null ? new Uri(GitRemoteUrl, UriKind.Absolute) : null, + CommitId = GitCommitId, + GitWorkingDirectory = GitWorkingDirectory, + }; + bool success = Linker.Link(PdbFile.GetMetadata("FullPath"), options); + + return success && !Log.HasLoggedErrors; + } + + private class MSBuildListener : LogListenerBase + { + private readonly TaskLoggingHelper _log; + + internal MSBuildListener(TaskLoggingHelper log) + { + _log = log; + } + + protected override void Write(ILog log, string message, LogEvent logEvent, object extraData, LogData logData, DateTime time) + { + switch (logEvent) + { + case LogEvent.Error: + _log.LogError(message); + break; + case LogEvent.Warning: + _log.LogWarning(message); + break; + case LogEvent.Info: + _log.LogMessage(MessageImportance.Normal, message); + break; + case LogEvent.Debug: + _log.LogMessage(MessageImportance.Low, message); + break; + default: + break; + } + } + } + } +} diff --git a/src/GitLinkTask/LinkProject.cs b/src/GitLinkTask/LinkProject.cs deleted file mode 100644 index 79a6bdb..0000000 --- a/src/GitLinkTask/LinkProject.cs +++ /dev/null @@ -1,28 +0,0 @@ -// -------------------------------------------------------------------------------------------------------------------- -// -// 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 index e67bdcc..ae23dfa 100644 --- a/src/GitLinkTask/Properties/AssemblyInfo.cs +++ b/src/GitLinkTask/Properties/AssemblyInfo.cs @@ -1,24 +1,12 @@ // -------------------------------------------------------------------------------------------------------------------- // -// Copyright (c) 2014 - 2016 CatenaLogic. All rights reserved. +// Copyright (c) 2014 - 2017 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 +[assembly: AssemblyDescription("GitLinkTask library")] \ No newline at end of file diff --git a/src/GitLinkTask/TaskItemExtensions.cs b/src/GitLinkTask/TaskItemExtensions.cs deleted file mode 100644 index d9e965f..0000000 --- a/src/GitLinkTask/TaskItemExtensions.cs +++ /dev/null @@ -1,30 +0,0 @@ -// -------------------------------------------------------------------------------------------------------------------- -// -// 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/src/GitLinkTask/project.json b/src/GitLinkTask/project.json new file mode 100644 index 0000000..6c9ca4f --- /dev/null +++ b/src/GitLinkTask/project.json @@ -0,0 +1,12 @@ +{ + "dependencies": { + "GitVersionTask": "4.0.0-beta0009", + "NuProj.Common": "0.11.14-beta" + }, + "frameworks": { + "net45": {} + }, + "runtimes": { + "win": {} + } +} \ No newline at end of file diff --git a/src/GitLinkTask/stylecop.json b/src/GitLinkTask/stylecop.json new file mode 100644 index 0000000..c48d1e4 --- /dev/null +++ b/src/GitLinkTask/stylecop.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "documentationRules": { + "companyName": "Andrew Arnott", + "xmlHeader": false + } + } +} diff --git a/src/Settings.StyleCop b/src/Settings.StyleCop deleted file mode 100644 index 000eac0..0000000 --- a/src/Settings.StyleCop +++ /dev/null @@ -1,359 +0,0 @@ - - - - preprocessor, pre-processor - shortlived, short-lived - - NoMerge - - db - - - - - - - \.g\.cs$ - \.generated\.cs$ - \.g\.i\.cs$ - - - - - - - - - - False - - - - - False - - - - - False - - - - - - as - do - id - if - in - is - my - no - on - to - ui - - - - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - - - - - - False - - - - - False - - - - - False - - - - - False - - - - - False - - - - - - - - - - False - - - - - False - - - - - False - - - - - False - - - - - - - - - - False - - - - - False - - - - - False - - - - - - - - - - False - - - - - - - \ No newline at end of file diff --git a/src/SolutionAssemblyInfo.cs b/src/SolutionAssemblyInfo.cs deleted file mode 100644 index 640e15e..0000000 --- a/src/SolutionAssemblyInfo.cs +++ /dev/null @@ -1,38 +0,0 @@ -// -------------------------------------------------------------------------------------------------------------------- -// -// Copyright (c) 2014 - 2014 CatenaLogic. All rights reserved. -// -// -------------------------------------------------------------------------------------------------------------------- - - -#pragma warning disable 1699 // 1699 = Use command line option '/keyfile' or appropriate project settings instead of 'AssemblyKeyFile' - -using System; -using System.Reflection; -using System.Resources; - -// Shared assembly info that is common for all assemblies of this project - -////[assembly: AssemblyTitle("DEFINED IN ACTUAL ASSEMBLYINFO")] -////[assembly: AssemblyProduct("DEFINED IN ACTUAL ASSEMBLYINFO")] -////[assembly: AssemblyDescription("DEFINED IN ACTUAL ASSEMBLYINFO")] - -[assembly: AssemblyCompany("CatenaLogic")] -[assembly: AssemblyCopyright("Copyright © CatenaLogic 2014")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] -[assembly: NeutralResourcesLanguage("en-US")] - -// 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.2.0")] -[assembly: AssemblyInformationalVersion("1.2.0, manually released in Visual Studio")] -[assembly: CLSCompliant(false)] \ No newline at end of file diff --git a/src/nuget.config b/src/nuget.config index 29a9bd8..f1cb37a 100644 --- a/src/nuget.config +++ b/src/nuget.config @@ -1,5 +1,9 @@ - + + + + + \ No newline at end of file diff --git a/tools/Get-NuGetTool.ps1 b/tools/Get-NuGetTool.ps1 new file mode 100644 index 0000000..5dae5aa --- /dev/null +++ b/tools/Get-NuGetTool.ps1 @@ -0,0 +1,15 @@ +<# +.SYNOPSIS + Downloads the NuGet.exe tool and returns the path to it. +#> + +$binaryToolsPath = "$PSScriptRoot\..\obj\tools" +if (!(Test-Path $binaryToolsPath)) { $null = mkdir $binaryToolsPath } +$nugetPath = "$binaryToolsPath\nuget.exe" +if (!(Test-Path $nugetPath)) { + $NuGetVersion = "3.4.4" + Write-Host "Downloading nuget.exe $NuGetVersion..." -ForegroundColor Yellow + Invoke-WebRequest -Uri "https://dist.nuget.org/win-x86-commandline/v$NuGetVersion/NuGet.exe" -OutFile $nugetPath +} + +$nugetPath diff --git a/tools/Install-NuGetPackage.ps1 b/tools/Install-NuGetPackage.ps1 new file mode 100644 index 0000000..4bca51c --- /dev/null +++ b/tools/Install-NuGetPackage.ps1 @@ -0,0 +1,41 @@ +<# +.SYNOPSIS + Installs a NuGet package. +.PARAMETER PackageID + The Package ID to install. +.PARAMETER Version + The version of the package to install. If unspecified, the latest stable release is installed. +.PARAMETER Source + The package source feed to find the package to install from. +.PARAMETER PackagesDir + The directory to install the package to. By default, it uses the Packages folder at the root of the repo. +#> +Param( + [Parameter(Position=1,Mandatory=$true)] + [string]$PackageId, + [Parameter()] + [string]$Version, + [Parameter()] + [string]$Source, + [Parameter()] + [switch]$Prerelease, + [Parameter()] + [ValidateSet('Quiet','Normal','Detailed')] + [string]$Verbosity='normal' +) + +$nugetPath = & "$PSScriptRoot\Get-NuGetTool.ps1" + +try { + Write-Verbose "Installing $PackageId..." + $args = "Install",$PackageId + if ($Version) { $args += "-Version",$Version } + if ($Source) { $args += "-Source",$Source } + if ($Prerelease) { $args += "-Prerelease" } + $args += '-Verbosity',$Verbosity + + $p = Start-Process $nugetPath $args -NoNewWindow -Wait -PassThru + if ($p.ExitCode -ne 0) { throw } +} finally { + Pop-Location +} diff --git a/tools/NuGet/NuGet.exe b/tools/NuGet/NuGet.exe deleted file mode 100644 index 9552e30..0000000 Binary files a/tools/NuGet/NuGet.exe and /dev/null differ diff --git a/tools/Restore-NuGetPackages.ps1 b/tools/Restore-NuGetPackages.ps1 new file mode 100644 index 0000000..3e345e1 --- /dev/null +++ b/tools/Restore-NuGetPackages.ps1 @@ -0,0 +1,21 @@ +<# +.SYNOPSIS + Restores NuGet packages. +.PARAMETER Path + The path of the solution, directory, packages.config or project.json file to restore packages from. + If not specified, the current directory is used. +.PARAMETER Verbosity +#> +Param( + [Parameter(Position=1)] + [string]$Path=(Get-Location), + [Parameter()] + [ValidateSet('Quiet','Normal','Detailed')] + [string]$Verbosity='normal' +) + +$nugetPath = & "$PSScriptRoot\Get-NuGetTool.ps1" + +Write-Verbose "Restoring NuGet packages for $Path" +& $nugetPath restore $Path -Verbosity $Verbosity +if ($lastexitcode -ne 0) { throw }