Skip to content

Commit

Permalink
I tried to implement the functionality mentioned in the issue GitTool…
Browse files Browse the repository at this point in the history
…s#66

I did pretty much the same thing as Marcind with his CustomRawUrlProvider, here is the readme part.

Running for an uncommon 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.

I also added an option to download the sources with powershell because SRCSRV http support doesn't accept characters like "?" thus another option was needed
  • Loading branch information
Simon Musy committed Nov 30, 2015
1 parent fa353f6 commit fc4ec89
Show file tree
Hide file tree
Showing 11 changed files with 222 additions and 11 deletions.
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,13 @@ When specific projects should be ignored, use the *-ignore* option. This option

GitLink.exe c:\source\catel -u https://github.com/catel/catel -f Catel.sln -ignore Catel.Core.WP80,Catel.MVVM.WP80

## 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
Expand Down
8 changes: 8 additions & 0 deletions src/GitLink.Tests/ArgumentParserFacts.cs
Original file line number Diff line number Diff line change
Expand Up @@ -124,5 +124,13 @@ public void ThrowsExceptionForUnknownArgument()
{
ExceptionTester.CallMethodAndExpectException<GitLinkException>(() => 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);
}
}
}
82 changes: 82 additions & 0 deletions src/GitLink.Tests/Providers/CustomUrlProviderFacts.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
using GitLink.Providers;
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace GitLink.Tests.Providers
{
public class CustomUrlProviderFacts
{
private const string correctUrl = "https://bitbucket.intra.company.com/projects/aaa/repos/a/browse/{filename}?at={revision}&raw";
[TestFixture]
public class TheInitialization
{
[TestCase(correctUrl, true)]
[TestCase("https://example.com/repo", false)]
[TestCase("https://bitbucket.intra.company.com/projects/aaa/repos/a/browse/{filename}?raw", true)]
[TestCase("gopher://example.com/repo", false)]
public void CorrectlyValidatesForUrls(string url, bool expectedValue)
{
var provider = new CustomUrlProvider();
var valid = provider.Initialize(url);

Assert.AreEqual(expectedValue, valid);
}
}

[TestFixture]
public class TheGitHubProviderProperties
{
[TestCase]
public void ReturnsNullCompany()
{
var provider = new CustomUrlProvider();
provider.Initialize(correctUrl);

Assert.IsNull(provider.CompanyName);
}

[TestCase]
public void ReturnsNullCompanyUrl()
{
var provider = new CustomUrlProvider();
provider.Initialize(correctUrl);

Assert.IsNull(provider.CompanyUrl);
}

[TestCase]
public void ReturnsNullProject()
{
var provider = new CustomUrlProvider();
provider.Initialize(correctUrl);

Assert.IsNull(provider.ProjectName);
}

[TestCase]
public void ReturnsNullProjectUrl()
{
var provider = new CustomUrlProvider();
provider.Initialize(correctUrl);

Assert.IsNull(provider.ProjectUrl);
}

[TestCase]
public void ReturnsValidRawGitUrl()
{
var provider = new CustomUrlProvider();
provider.Initialize(correctUrl);

string correctReturnedUrl = correctUrl.Replace("{filename}", "%var2%");
correctReturnedUrl = correctReturnedUrl.Replace("{revision}", "{0}");

Assert.AreEqual(correctReturnedUrl, provider.RawGitUrl);
}
}
}
}
6 changes: 6 additions & 0 deletions src/GitLink/ArgumentParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,12 @@ public static Context ParseArguments(List<string> commandLineArguments, IProvide
continue;
}

if (IsSwitch("powershell", name))
{
context.DownloadWithPowershell = true;
continue;
}

// After this point, all arguments should have a value
index++;
var valueInfo = GetValue(namedArguments, index);
Expand Down
1 change: 1 addition & 0 deletions src/GitLink/Context.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ public Context(IProviderManager providerManager)
IgnoredProjects = new List<string>();
}

public bool DownloadWithPowershell { get; set; } = false;
public bool IsHelp { get; set; }

public bool IsDebug { get; set; }
Expand Down
44 changes: 44 additions & 0 deletions src/GitLink/CustomUrlProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
namespace GitLink.Providers
{
using GitTools.Git;
using System.Text.RegularExpressions;

public sealed class CustomUrlProvider : ProviderBase
{
private static readonly string fileNamePlaceHolder = "{filename}";
private static readonly string revisionPlaceHolder = "{revision}";
private readonly Regex _regexUrl = new Regex(@"https?://.+");

private string _rawUrl;

public CustomUrlProvider()
: base(new GitPreparer())
{
}

public override string RawGitUrl
{
get
{
return _rawUrl;
}
}

public override bool Initialize(string url)
{
if (string.IsNullOrEmpty(url) || !_regexUrl.IsMatch(url) ||(
!url.Contains(fileNamePlaceHolder) && !url.Contains(revisionPlaceHolder)))
{
return false;
}

if(url.Contains(fileNamePlaceHolder))
_rawUrl = url.Replace(fileNamePlaceHolder, "%var2%");

if(url.Contains(revisionPlaceHolder))
_rawUrl = _rawUrl.Replace(revisionPlaceHolder, "{0}");

return true;
}
}
}
8 changes: 4 additions & 4 deletions src/GitLink/Extensions/ProjectExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,25 +47,25 @@ public static string GetProjectName(this Project project)
return projectName ?? Path.GetFileName(project.FullPath);
}

public static void CreateSrcSrv(this Project project, string rawUrl, string revision, Dictionary<string, string> paths)
public static void CreateSrcSrv(this Project project, string rawUrl, string revision, Dictionary<string, string> paths, bool DownloadWithPowershell)
{
Argument.IsNotNull(() => project);
Argument.IsNotNullOrWhitespace(() => rawUrl);
Argument.IsNotNullOrWhitespace(() => revision);

var srcsrvFile = GetOutputSrcSrvFile(project);

CreateSrcSrv(project, rawUrl, revision, paths, srcsrvFile);
CreateSrcSrv(project, rawUrl, revision, paths, srcsrvFile, DownloadWithPowershell);
}

public static void CreateSrcSrv(this Project project, string rawUrl, string revision, Dictionary<string, string> paths, string srcsrvFile)
public static void CreateSrcSrv(this Project project, string rawUrl, string revision, Dictionary<string, string> paths, string srcsrvFile, bool DownloadWithPowershell)
{
Argument.IsNotNull(() => project);
Argument.IsNotNullOrWhitespace(() => rawUrl);
Argument.IsNotNullOrWhitespace(() => revision);
Argument.IsNotNullOrWhitespace(() => srcsrvFile);

File.WriteAllBytes(srcsrvFile, SrcSrv.Create(rawUrl, revision, paths.Select(x => new Tuple<string, string>(x.Key, x.Value))));
File.WriteAllBytes(srcsrvFile, SrcSrv.Create(rawUrl, revision, paths.Select(x => new Tuple<string, string>(x.Key, x.Value)), DownloadWithPowershell));
}

public static IEnumerable<ProjectItem> GetCompilableItems(this Project project)
Expand Down
2 changes: 2 additions & 0 deletions src/GitLink/HelpWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ solutionPath The directory containing the solution with the pdb files.
-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.
Expand Down
10 changes: 8 additions & 2 deletions src/GitLink/Linker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,13 @@ private static bool LinkProject(Context context, Project project, string pdbStrF
}
}

var rawUrl = string.Format("{0}/{{0}}/%var2%", context.Provider.RawGitUrl);
var rawUrl = context.Provider.RawGitUrl;

if(!rawUrl.Contains("%var2%") && !rawUrl.Contains("{0}"))
{
rawUrl= string.Format("{0}/{{0}}/%var2%", context.Provider.RawGitUrl);
}

var paths = new Dictionary<string, string>();
foreach (var compilable in compilables)
{
Expand All @@ -212,7 +218,7 @@ private static bool LinkProject(Context context, Project project, string pdbStrF
paths.Add(compilable, relativePathForUrl);
}

project.CreateSrcSrv(rawUrl, shaHash, paths, projectSrcSrvFile);
project.CreateSrcSrv(rawUrl, shaHash, paths, projectSrcSrvFile, context.DownloadWithPowershell);

Log.Debug("Created source server link file, updating pdb file '{0}'", context.GetRelativePath(projectPdbFile));

Expand Down
20 changes: 15 additions & 5 deletions src/GitLink/Pdb/SrcSrv.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ private static string CreateTarget(string rawUrl, string revision)
return string.Format(rawUrl, revision);
}

public static byte[] Create(string rawUrl, string revision, IEnumerable<Tuple<string, string>> paths)
public static byte[] Create(string rawUrl, string revision, IEnumerable<Tuple<string, string>> paths, bool DebugWithPowershell)
{
Argument.IsNotNullOrWhitespace(() => rawUrl);
Argument.IsNotNullOrWhitespace(() => revision);
Expand All @@ -29,12 +29,22 @@ public static byte[] Create(string rawUrl, string revision, IEnumerable<Tuple<st
using (var sw = new StreamWriter(ms))
{
var scheme = new Uri(rawUrl).Scheme;

sw.WriteLine("SRCSRV: ini ------------------------------------------------");
sw.WriteLine("VERSION=2");
sw.WriteLine("SRCSRV: variables ------------------------------------------");
sw.WriteLine("SRCSRVVERCTRL={0}", scheme);
sw.WriteLine("SRCSRVTRG={0}", CreateTarget(rawUrl, revision));
sw.WriteLine("SRCSRV: variables ------------------------------------------");
sw.WriteLine("RAWURL={0}", CreateTarget(rawUrl, revision));
if(DebugWithPowershell)
{
sw.WriteLine("TRGFILE=%fnbksl%(%targ%%var2%)");
sw.WriteLine("SRCSRVTRG=%TRGFILE%");
sw.WriteLine("SRCSRVCMD=powershell -NoProfile -Command \"(New-Object system.net.WebClient).DownloadFile('%RAWURL%', '%TRGFILE%')\"");
}
else
{
sw.WriteLine("SRCSRVVERCTRL={0}", scheme);
sw.WriteLine("SRCSRVTRG=%RAWURL%");
}
sw.WriteLine("SRCSRV: source files ---------------------------------------");

foreach (var tuple in paths)
Expand Down
45 changes: 45 additions & 0 deletions src/GitLink/ProviderManager.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="ProviderManager.cs" company="CatenaLogic">
// Copyright (c) 2014 - 2014 CatenaLogic. All rights reserved.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------


namespace GitLink.Providers
{
using Catel.IoC;
using Catel.Reflection;

public class ProviderManager : IProviderManager
{
public ProviderBase GetProvider(string url)
{
var providerTypes = TypeCache.GetTypes(x => typeof(ProviderBase).IsAssignableFromEx(x) && !x.IsAbstract && x != typeof(CustomRawUrlProvider) && x != typeof(CustomUrlProvider));

var typeFactory = TypeFactory.Default;

var customUrlProvider = typeFactory.CreateInstance<CustomUrlProvider>();
if (customUrlProvider.Initialize(url))
{
return customUrlProvider;
}

foreach (var providerType in providerTypes)
{
var provider = (ProviderBase) typeFactory.CreateInstance(providerType);
if (provider.Initialize(url))
{
return provider;
}
}

var customProvider = typeFactory.CreateInstance<CustomRawUrlProvider>();
if (customProvider.Initialize(url))
{
return customProvider;
}

return null;
}
}
}

0 comments on commit fc4ec89

Please sign in to comment.