Skip to content
This repository was archived by the owner on Jun 21, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/DesignTimeStyleHelper/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
using GitHub.SampleData;
using GitHub.Services;
using GitHub.UI;
using GitHub.VisualStudio;
using GitHub.Extensions;
using GitHub.Models;

namespace DesignTimeStyleHelper
Expand Down
2 changes: 1 addition & 1 deletion src/GitHub.App/Services/RepositoryPublishService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ namespace GitHub.Services
public class RepositoryPublishService : IRepositoryPublishService
{
readonly IGitClient gitClient;
readonly Repository activeRepository;
readonly IRepository activeRepository;

[ImportingConstructor]
public RepositoryPublishService(IGitClient gitClient, IVSServices services)
Expand Down
10 changes: 4 additions & 6 deletions src/GitHub.Exports/Extensions/SimpleRepositoryModelExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using GitHub.Models;
using System;
using System;
using System.Linq;
using System.IO;
using GitHub.Models;
using Microsoft.VisualStudio.TeamFoundation.Git.Extensibility;

namespace GitHub.Extensions
Expand All @@ -13,14 +13,12 @@ public static class SimpleRepositoryModelExtensions
/// </summary>
public static ISimpleRepositoryModel ToModel(this IGitRepositoryInfo repo)
{
if (repo == null)
return null;
return SimpleRepositoryModel.Create(repo.RepositoryPath);
return repo == null ? null : new SimpleRepositoryModel(repo.RepositoryPath);
}

public static bool HasCommits(this ISimpleRepositoryModel repository)
{
var repo = GitHelpers.GetRepoFromPath(repository.LocalPath);
var repo = VisualStudio.Services.IGitService.GetRepo(repository.LocalPath);
return repo?.Commits.Any() ?? false;
}

Expand Down
14 changes: 11 additions & 3 deletions src/GitHub.Exports/Extensions/VSExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using GitHub.Services;
using Microsoft.TeamFoundation.Controls;
using System;
using System;
using System.Diagnostics;
using GitHub.Services;
using Microsoft.TeamFoundation.Controls;

namespace GitHub.Extensions
{
Expand Down Expand Up @@ -36,6 +36,14 @@ public static T GetService<T>(this IServiceProvider serviceProvider)
return (T)serviceProvider.GetService(typeof(T));
}

public static T GetExportedValue<T>(this IServiceProvider serviceProvider)
{
var ui = serviceProvider as IUIProvider;
return ui != null
? ui.GetService<T>()
: VisualStudio.Services.ComponentModel.DefaultExportProvider.GetExportedValue<T>();
}

public static ITeamExplorerSection GetSection(this IServiceProvider serviceProvider, Guid section)
{
return serviceProvider?.GetService<ITeamExplorerPage>()?.GetSection(section);
Expand Down
2 changes: 2 additions & 0 deletions src/GitHub.Exports/GitHub.Exports.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@
<Compile Include="Models\SimpleRepositoryModel.cs" />
<Compile Include="Helpers\NotificationAwareObject.cs" />
<Compile Include="Services\Connection.cs" />
<Compile Include="Services\GitService.cs" />
<Compile Include="Services\IGitService.cs" />
<Compile Include="Services\ITeamExplorerServiceHolder.cs" />
<Compile Include="Services\Logger.cs" />
<Compile Include="Services\Services.cs" />
Expand Down
46 changes: 16 additions & 30 deletions src/GitHub.Exports/Models/SimpleRepositoryModel.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
using GitHub.Extensions;
using GitHub.Primitives;
using GitHub.UI;
using GitHub.VisualStudio;
using GitHub.VisualStudio.Helpers;
using System;
using System;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using GitHub.Primitives;
using GitHub.UI;
using GitHub.VisualStudio.Helpers;

namespace GitHub.Models
{
Expand All @@ -28,25 +26,14 @@ public SimpleRepositoryModel(string path)
var dir = new DirectoryInfo(path);
if (!dir.Exists)
throw new ArgumentException("Path does not exist", nameof(path));
var uri = GitHelpers.GetRepoFromPath(path)?.GetUri();
var name = uri?.NameWithOwner;
if (name == null)
name = dir.Name;
var uri = VisualStudio.Services.IGitService.GetUri(path);
var name = uri?.NameWithOwner ?? dir.Name;
Name = name;
LocalPath = path;
CloneUrl = uri;
Icon = Octicon.repo;
}

public static ISimpleRepositoryModel Create(string path)
{
if (path == null)
return null;
if (!Directory.Exists(path))
return null;
return new SimpleRepositoryModel(path);
}

public void SetIcon(bool isPrivate, bool isFork)
{
Icon = isPrivate
Expand All @@ -60,15 +47,15 @@ public void Refresh()
{
if (LocalPath == null)
return;
var uri = GitHelpers.GetRepoFromPath(LocalPath)?.GetUri();
var uri = VisualStudio.Services.IGitService.GetUri(LocalPath);
if (CloneUrl != uri)
CloneUrl = uri;
}

public string Name { get; private set; }
public string Name { get; }
UriString cloneUrl;
public UriString CloneUrl { get { return cloneUrl; } set { cloneUrl = value; this.RaisePropertyChange(); } }
public string LocalPath { get; private set; }
public string LocalPath { get; }
Octicon icon;
public Octicon Icon { get { return icon; } set { icon = value; this.RaisePropertyChange(); } }

Expand Down Expand Up @@ -97,13 +84,12 @@ bool IEquatable<SimpleRepositoryModel>.Equals(SimpleRepositoryModel other)
return other != null && String.Equals(Name, other.Name) && String.Equals(CloneUrl, other.CloneUrl) && String.Equals(LocalPath?.TrimEnd('\\'), other.LocalPath?.TrimEnd('\\'), StringComparison.CurrentCultureIgnoreCase);
}

internal string DebuggerDisplay
{
get
{
return String.Format(CultureInfo.InvariantCulture,
"{3}\tName: {0} CloneUrl: {1} LocalPath: {2}", Name, CloneUrl, LocalPath, GetHashCode());
}
}
internal string DebuggerDisplay => String.Format(
CultureInfo.InvariantCulture,
"{3}\tName: {0} CloneUrl: {1} LocalPath: {2}",
Name,
CloneUrl,
LocalPath,
GetHashCode());
}
}
98 changes: 98 additions & 0 deletions src/GitHub.Exports/Services/GitService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
using System;
using System.ComponentModel.Composition;
using System.Linq;
using GitHub.Primitives;
using LibGit2Sharp;
using Microsoft.VisualStudio.TeamFoundation.Git.Extensibility;

namespace GitHub.Services
{
[Export(typeof(IVSServices))]
[PartCreationPolicy(CreationPolicy.Shared)]
public class GitService : IGitService
{
/// <summary>
/// Returns the URL of the remote named "origin" for the specified <see cref="repository"/>. If the repository
/// is null or no remote named origin exists, this method returns null
/// </summary>
/// <param name="repository">The repository to look at for the remote.</param>
/// <returns>A <see cref="UriString"/> representing the origin or null if none found.</returns>
public UriString GetUri(IRepository repository)
{
return UriString.ToUriString(GetUriFromRepository(repository)?.ToRepositoryUrl());
}

/// <summary>
/// Probes for a git repository and if one is found, returns a <see cref="UriString"/> for the repository's
/// remote named "origin" if one is found
/// </summary>
/// <remarks>
/// The lookup checks to see if the specified <paramref name="path"/> is a repository. If it's not, it then
/// walks up the parent directories until it either finds a repository, or reaches the root disk.
/// </remarks>
/// <param name="path">The path to start probing</param>
/// <returns>A <see cref="UriString"/> representing the origin or null if none found.</returns>
public UriString GetUri(string path)
{
return GetUri(GetRepo(path));
}

/// <summary>
/// Probes for a git repository and if one is found, returns a <see cref="UriString"/> for the repository's
/// remote named "origin" if one is found
/// </summary>
/// <remarks>
/// The lookup checks to see if the path specified by the RepositoryPath property of the specified
/// <see cref="repoInfo"/> is a repository. If it's not, it then walks up the parent directories until it
/// either finds a repository, or reaches the root disk.
/// </remarks>
/// <param name="repoInfo">The repository information containing the path to start probing</param>
/// <returns>A <see cref="UriString"/> representing the origin or null if none found.</returns>
public UriString GetUri(IGitRepositoryInfo repoInfo)
{
return GetUri(GetRepo(repoInfo));
}

/// <summary>
/// Probes for a git repository and if one is found, returns a <see cref="IRepository"/> instance for the
/// repository.
/// </summary>
/// <remarks>
/// The lookup checks to see if the path specified by the RepositoryPath property of the specified
/// <see cref="repoInfo"/> is a repository. If it's not, it then walks up the parent directories until it
/// either finds a repository, or reaches the root disk.
/// </remarks>
/// <param name="repoInfo">The repository information containing the path to start probing</param>
/// <returns>An instance of <see cref="IRepository"/> or null</returns>

public IRepository GetRepo(IGitRepositoryInfo repoInfo)
{
return GetRepo(repoInfo?.RepositoryPath);
}

/// <summary>
/// Probes for a git repository and if one is found, returns a <see cref="IRepository"/> instance for the
/// repository.
/// </summary>
/// <remarks>
/// The lookup checks to see if the specified <paramref name="path"/> is a repository. If it's not, it then
/// walks up the parent directories until it either finds a repository, or reaches the root disk.
/// </remarks>
/// <param name="path">The path to start probing</param>
/// <returns>An instance of <see cref="IRepository"/> or null</returns>
public IRepository GetRepo(string path)
{
var repoPath = Repository.Discover(path);
return repoPath == null ? null : new Repository(repoPath);
}

internal static UriString GetUriFromRepository(IRepository repo)
{
return repo
?.Network
.Remotes
.FirstOrDefault(x => x.Name.Equals("origin", StringComparison.Ordinal))
?.Url;
}
}
}
68 changes: 68 additions & 0 deletions src/GitHub.Exports/Services/IGitService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
using GitHub.Primitives;
using LibGit2Sharp;
using Microsoft.VisualStudio.TeamFoundation.Git.Extensibility;

namespace GitHub.Services
{
public interface IGitService
{
/// <summary>
/// Returns the URL of the remote named "origin" for the specified <see cref="repository"/>. If the repository
/// is null or no remote named origin exists, this method returns null
/// </summary>
/// <param name="repository">The repository to look at for the remote.</param>
/// <returns>A <see cref="UriString"/> representing the origin or null if none found.</returns>
UriString GetUri(IRepository repository);

/// <summary>
/// Probes for a git repository and if one is found, returns a <see cref="UriString"/> for the repository's
/// remote named "origin" if one is found
/// </summary>
/// <remarks>
/// The lookup checks to see if the specified <paramref name="path"/> is a repository. If it's not, it then
/// walks up the parent directories until it either finds a repository, or reaches the root disk.
/// </remarks>
/// <param name="path">The path to start probing</param>
/// <returns>A <see cref="UriString"/> representing the origin or null if none found.</returns>
UriString GetUri(string path);

/// <summary>
/// Probes for a git repository and if one is found, returns a <see cref="UriString"/> for the repository's
/// remote named "origin" if one is found
/// </summary>
/// <remarks>
/// The lookup checks to see if the path specified by the RepositoryPath property of the specified
/// <see cref="repoInfo"/> is a repository. If it's not, it then walks up the parent directories until it
/// either finds a repository, or reaches the root disk.
/// </remarks>
/// <param name="repoInfo">The repository information containing the path to start probing</param>
/// <returns>A <see cref="UriString"/> representing the origin or null if none found.</returns>
UriString GetUri(IGitRepositoryInfo repoInfo);

/// <summary>
/// Probes for a git repository and if one is found, returns a <see cref="IRepository"/> instance for the
/// repository.
/// </summary>
/// <remarks>
/// The lookup checks to see if the path specified by the RepositoryPath property of the specified
/// <see cref="repoInfo"/> is a repository. If it's not, it then walks up the parent directories until it
/// either finds a repository, or reaches the root disk.
/// </remarks>
/// <param name="repoInfo">The repository information containing the path to start probing</param>
/// <returns>An instance of <see cref="IRepository"/> or null</returns>

IRepository GetRepo(IGitRepositoryInfo repoInfo);

/// <summary>
/// Probes for a git repository and if one is found, returns a <see cref="IRepository"/> instance for the
/// repository.
/// </summary>
/// <remarks>
/// The lookup checks to see if the specified <paramref name="path"/> is a repository. If it's not, it then
/// walks up the parent directories until it either finds a repository, or reaches the root disk.
/// </remarks>
/// <param name="path">The path to start probing</param>
/// <returns>An instance of <see cref="IRepository"/> or null</returns>
IRepository GetRepo(string path);
}
}
Loading