Skip to content

Commit

Permalink
Updated for Visual Stufio 2017
Browse files Browse the repository at this point in the history
  • Loading branch information
CDuke committed May 8, 2017
1 parent 322c29e commit 7c30fa1
Show file tree
Hide file tree
Showing 9 changed files with 206 additions and 55 deletions.
9 changes: 9 additions & 0 deletions build_15.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
@echo off
cls
IF NOT EXIST "tools/FAKE" (
"tools/nuget/nuget.exe" "install" "FAKE" "-OutputDirectory" "tools" "-ExcludeVersion"
)

"tools/FAKE/tools/Fake.exe" "%~dp0build/build.fsx" "VisualStudioVersion=15.0"
pause
exit /b %errorlevel%
69 changes: 53 additions & 16 deletions src/AutoUncheckout/AutoUncheckout.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
<SignAssembly>True</SignAssembly>
<AssemblyOriginatorKeyFile>Key.snk</AssemblyOriginatorKeyFile>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<TargetFrameworkVersion Condition="'$(VisualStudioVersion)' == '15.0'">v4.6.2</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
Expand All @@ -43,18 +44,56 @@
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.CSharp" />
<Reference Include="Microsoft.VisualStudio.OLE.Interop" />
<Reference Include="Microsoft.VisualStudio.Shell.Interop" />
<Reference Include="Microsoft.VisualStudio.Shell.Interop.8.0" />
<Reference Include="Microsoft.VisualStudio.Shell.Interop.9.0" />
<Reference Include="Microsoft.VisualStudio.Shell.Interop.9.0" />
<Reference Include="Microsoft.VisualStudio.Shell.Interop.10.0" />
<Reference Include="Microsoft.VisualStudio.Shell.12.0" />
<Reference Include="Microsoft.VisualStudio.Shell.Immutable.10.0" />
<Reference Include="Microsoft.VisualStudio.OLE.Interop">
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.VisualStudio.Shell.Interop">
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.VisualStudio.Shell.Interop.8.0">
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.VisualStudio.Shell.Interop.9.0">
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.VisualStudio.Shell.Interop.10.0">
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.VisualStudio.Shell.Interop.11.0">
<EmbedInteropTypes>true</EmbedInteropTypes>
</Reference>
<Reference Include="Microsoft.VisualStudio.Shell.Interop.12.0">
<EmbedInteropTypes>true</EmbedInteropTypes>
</Reference>
<Reference Include="Microsoft.VisualStudio.Shell.12.0">
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.VisualStudio.Shell.Immutable.10.0">
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.VisualStudio.Shell.Immutable.11.0">
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.VisualStudio.Shell.Immutable.12.0">
<Private>False</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
</ItemGroup>
<Choose>
<When Condition="$(VisualStudioVersion)== '15.0'">
<ItemGroup>
<Reference Include="Microsoft.VisualStudio.Shell.Framework, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
<Reference Include="Microsoft.TeamFoundation.Client">
<HintPath>C:\Program Files\Common Files\microsoft shared\Team Foundation Server\15.0\Microsoft.TeamFoundation.Client.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.TeamFoundation.VersionControl.Client">
<HintPath>C:\Program Files\Common Files\microsoft shared\Team Foundation Server\15.0\Microsoft.TeamFoundation.VersionControl.Client.dll</HintPath>
<Private>False</Private>
</Reference>
</ItemGroup>
</When>
<When Condition="$(VisualStudioVersion)== '14.0'">
<ItemGroup>
<Reference Include="Microsoft.TeamFoundation.Client">
Expand All @@ -81,15 +120,11 @@
</When>
</Choose>
<ItemGroup>
<COMReference Include="EnvDTE">
<Guid>{80CC9F66-E7D8-4DDD-85B6-D9E6CD0E93E2}</Guid>
<VersionMajor>8</VersionMajor>
<VersionMinor>0</VersionMinor>
<Lcid>0</Lcid>
<WrapperTool>primary</WrapperTool>
<Isolated>False</Isolated>
<Reference Include="EnvDTE, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<EmbedInteropTypes>False</EmbedInteropTypes>
</COMReference>
<HintPath>..\..\lib\EnvDTE.8.0.1\lib\net10\EnvDTE.dll</HintPath>
<Private>True</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Guids.cs" />
Expand All @@ -101,6 +136,7 @@
<Compile Include="GlobalSuppressions.cs" />
<Compile Include="AutoUncheckoutPackage.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SaveListener.cs" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Resources.resx">
Expand Down Expand Up @@ -145,6 +181,7 @@
<Copy SourceFiles="source.vs11.extension.vsixmanifest" DestinationFiles="source.extension.vsixmanifest" Condition="$(VisualStudioVersion)=='11.0'" />
<Copy SourceFiles="source.vs12.extension.vsixmanifest" DestinationFiles="source.extension.vsixmanifest" Condition="$(VisualStudioVersion)=='12.0'" />
<Copy SourceFiles="source.vs14.extension.vsixmanifest" DestinationFiles="source.extension.vsixmanifest" Condition="$(VisualStudioVersion)=='14.0'" />
<Copy SourceFiles="source.vs15.extension.vsixmanifest" DestinationFiles="source.extension.vsixmanifest" Condition="$(VisualStudioVersion)=='15.0'" />
</Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
Expand Down
77 changes: 44 additions & 33 deletions src/AutoUncheckout/AutoUncheckoutPackage.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using EnvDTE;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.VersionControl.Client;
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.OLE.Interop;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using Constants = EnvDTE.Constants;
Expand Down Expand Up @@ -35,9 +35,8 @@ namespace KulikovDenis.AutoUncheckout
public sealed class AutoUncheckoutPackage : Package, IVsShellPropertyEvents
{
private uint _cookie;
private Events _events;
private DocumentEvents _documentEvents;
private MD5CryptoServiceProvider _md5Provider;
internal RunningDocumentTable Rdt;

/// <summary>
/// Default constructor of the package.
Expand All @@ -48,7 +47,7 @@ public sealed class AutoUncheckoutPackage : Package, IVsShellPropertyEvents
/// </summary>
public AutoUncheckoutPackage()
{
Debug.WriteLine(string.Format(CultureInfo.CurrentCulture, "Entering constructor for: {0}", this.ToString()));
Debug.WriteLine(string.Format(CultureInfo.CurrentCulture, "Entering constructor for: {0}", this.ToString()));
}

/////////////////////////////////////////////////////////////////////////////
Expand All @@ -69,14 +68,21 @@ protected override void Initialize()

if (shellService != null)
ErrorHandler.ThrowOnFailure(shellService.AdviseShellPropertyChanges(this, out _cookie));
var serviceProvider = GetGlobalService(typeof (IServiceProvider)) as IServiceProvider;
Rdt = new RunningDocumentTable(new ServiceProvider(serviceProvider));
Rdt.Advise(new SaveListener(this));
}

#endregion

private void DocumentEvents_DocumentSaved(Document document)
internal void Uncheckout(string fileName)
{
try
{
var fileInfo = new FileInfo(fileName);
if (fileInfo.IsReadOnly)
return;

var tfsContext = GetService<ITeamFoundationContextManager>();
if (tfsContext == null)
return;
Expand All @@ -89,41 +95,37 @@ private void DocumentEvents_DocumentSaved(Document document)
if (vcs == null)
return;

var fileName = document.FullName;

// If file is new nothing comparer
if (!vcs.ServerItemExists(fileName, ItemType.File))
return;

var workspace = vcs.TryGetWorkspace(fileName);
// vcs.QueryWorkspaces(null, tfs.AuthorizedIdentity.UniqueName, Environment.MachineName).FirstOrDefault();
if (workspace == null)
return;
var fileInfoItem = vcs.GetItem(fileName);

if (fileInfoItem != null)
{
using (var fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read))
using (var fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, FileOptions.SequentialScan))
{
var currentHash = _md5Provider.ComputeHash(fileStream);
var hashEquals = fileInfoItem.HashValue.SequenceEqual(currentHash);
var hashEquals = HashEquals(currentHash, fileInfoItem.HashValue);
if (hashEquals && !IsMerged(workspace, fileName))
{
var fileInfo = new FileInfo(fileName);
if (!fileInfo.IsReadOnly)
// This is from
// Assembly: Microsoft.VisualStudio.TeamFoundation.VersionControl, Version=12.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
// Type: Microsoft.VisualStudio.TeamFoundation.VersionControl.ClientHelperVS
// Method: internal static void Undo(Workspace workspace, PendingChange[] changes)
using (new WorkspaceSuppressAsynchronousScanner(workspace))
{
// This is from
// Assembly: Microsoft.VisualStudio.TeamFoundation.VersionControl, Version=12.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
// Type: Microsoft.VisualStudio.TeamFoundation.VersionControl.ClientHelperVS
// Method: internal static void Undo(Workspace workspace, PendingChange[] changes)
//using (new WorkspaceSuppressAsynchronousScanner(workspace))
//{
// using (new WorkspacePersistedMetadataTables(workspace))
// {
workspace.Undo(ItemSpec.FromStrings(new[] {fileName}, RecursionType.None), false);
var vsFileChangeEx = GetService<SVsFileChangeEx, IVsFileChangeEx>();
vsFileChangeEx.SyncFile(fileName);
// }
//}
using (new WorkspacePersistedMetadataTables(workspace))
{
workspace.Undo(ItemSpec.FromStrings(new[] { fileInfoItem.ServerItem }, RecursionType.None), false);
workspace.UnqueueForEdit(fileName);
//workspace.Get(new GetRequest(fileInfoItem.ServerItem, RecursionType.None, VersionSpec.Latest), GetOptions.None);
var vsFileChangeEx = GetService<SVsFileChangeEx, IVsFileChangeEx>();
vsFileChangeEx.SyncFile(fileName);
}
}
}
}
Expand Down Expand Up @@ -152,18 +154,13 @@ public int OnShellPropertyChange(int propid, object var)
if (!(bool)var)
{
// zombie state dependent code
var dte = GetService<DTE, DTE>();
var dte = GetService<DTE>();
if (dte != null)
{
_events = dte.Events;
_documentEvents = _events.DocumentEvents;
_documentEvents.DocumentSaved += DocumentEvents_DocumentSaved;

// eventlistener no longer needed
var shellService = GetService<SVsShell, IVsShell>();

if (shellService != null)

ErrorHandler.ThrowOnFailure(shellService.UnadviseShellPropertyChanges(_cookie));

_cookie = 0;
Expand All @@ -175,15 +172,29 @@ public int OnShellPropertyChange(int propid, object var)
return VSConstants.S_OK;
}

private T GetService<T>() where T : class
internal T GetService<T>() where T : class
{
return GetService(typeof(T)) as T;
}

private TInterface GetService<TType, TInterface>()
internal TInterface GetService<TType, TInterface>()
where TInterface : class
{
return GetService(typeof(TType)) as TInterface;
}

private static bool HashEquals(byte[] hash1, byte[] hash2)
{
if (hash1.Length != hash2.Length)
return false;

for (int i = 0; i < hash1.Length; i++)
{
if (hash1[i] != hash2[i])
return false;
}

return true;
}
}
}
61 changes: 61 additions & 0 deletions src/AutoUncheckout/SaveListener.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.Shell.Interop;

namespace KulikovDenis.AutoUncheckout
{
internal class SaveListener : IVsRunningDocTableEvents3
{
private readonly AutoUncheckoutPackage _package;

public SaveListener(AutoUncheckoutPackage package)
{
_package = package;
}

public int OnAfterAttributeChange(uint docCookie, uint grfAttribs)
{
return VSConstants.S_OK;
}

public int OnAfterAttributeChangeEx(uint docCookie, uint grfAttribs, IVsHierarchy pHierOld, uint itemidOld,
string pszMkDocumentOld, IVsHierarchy pHierNew, uint itemidNew, string pszMkDocumentNew)
{
return VSConstants.S_OK;
}

public int OnAfterDocumentWindowHide(uint docCookie, IVsWindowFrame pFrame)
{
return VSConstants.S_OK;
}

public int OnAfterFirstDocumentLock(uint docCookie, uint dwRDTLockType, uint dwReadLocksRemaining,
uint dwEditLocksRemaining)
{
return VSConstants.S_OK;
}

public int OnAfterSave(uint docCookie)
{
var info = _package.Rdt.GetDocumentInfo(docCookie);
var fileName = info.Moniker;
_package.Uncheckout(fileName);
return VSConstants.S_OK;
}

public int OnBeforeDocumentWindowShow(uint docCookie, int fFirstShow, IVsWindowFrame pFrame)
{
return VSConstants.S_OK;
}

public int OnBeforeLastDocumentUnlock(uint docCookie, uint dwRDTLockType, uint dwReadLocksRemaining,
uint dwEditLocksRemaining)
{
return VSConstants.S_OK;
}

public int OnBeforeSave(uint docCookie)
{
return VSConstants.S_OK;
}
}
}
4 changes: 4 additions & 0 deletions src/AutoUncheckout/package.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="EnvDTE" version="8.0.1" targetFramework="net462" />
</packages>
14 changes: 9 additions & 5 deletions src/AutoUncheckout/source.extension.vsixmanifest
Original file line number Diff line number Diff line change
@@ -1,21 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<PackageManifest Version="2.0.0" xmlns="http://schemas.microsoft.com/developer/vsx-schema/2011" xmlns:d="http://schemas.microsoft.com/developer/vsx-schema-design/2011">
<Metadata>
<Identity Id="AutoUncheckout.VS2015.1954660f-1535-4694-9e6d-c27e8eb476a4" Version="1.1" Language="en-US" Publisher="Kulikov Denis" />
<DisplayName>Auto Uncheckout for Visual Studio 2015</DisplayName>
<Identity Id="AutoUncheckout.VS2017.1954660f-1535-4694-9e6d-c27e8eb476a4" Version="1.1" Language="en-US" Publisher="Kulikov Denis" />
<DisplayName>Auto Uncheckout for Visual Studio 2017</DisplayName>
<Description xml:space="preserve">Automatically undo check out file, if it has not been modified</Description>
<MoreInfo>https://github.com/CDuke/AutoUncheckout</MoreInfo>
<License>LICENSE.txt</License>
<Tags>auto, undo, check out, tfs, automatically</Tags>
</Metadata>
<Installation InstalledByMsi="false">
<InstallationTarget Id="Microsoft.VisualStudio.Pro" Version="[14.0, 15.0)" />
<InstallationTarget Id="Microsoft.VisualStudio.Pro" Version="[15.0, 16.0)" />
</Installation>
<Dependencies>
<Dependency Id="Microsoft.Framework.NDP" DisplayName="Microsoft .NET Framework" d:Source="Manual" Version="[4.5,)" />
<Dependency Id="Microsoft.VisualStudio.MPF.14.0" DisplayName="Visual Studio MPF 14.0" d:Source="Installed" Version="[14.0, 15.0)" />
<Dependency Id="Microsoft.Framework.NDP" DisplayName="Microsoft .NET Framework" d:Source="Manual" Version="[4.6,)" />
<Dependency Id="Microsoft.VisualStudio.MPF.15.0" DisplayName="Visual Studio MPF 15.0" d:Source="Installed" Version="[15.0, 16.0)" />
</Dependencies>
<Assets>
<Asset Type="Microsoft.VisualStudio.VsPackage" d:Source="Project" d:ProjectName="%CurrentProject%" Path="|%CurrentProject%;PkgdefProjectOutputGroup|" />
<Asset Type="Microsoft.VisualStudio.MefComponent" d:Source="Project" d:ProjectName="%CurrentProject%" Path="|%CurrentProject%|" />
</Assets>
<Prerequisites>
<Prerequisite Id="Microsoft.VisualStudio.Component.CoreEditor" Version="[15.0.26208.0,16.0)" DisplayName="Visual Studio core editor" />
</Prerequisites>
</PackageManifest>
Loading

0 comments on commit 7c30fa1

Please sign in to comment.