From b5902c7e2726f644f697d008401957c34fd0480f Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Wed, 22 Dec 2010 21:11:39 +0100 Subject: [PATCH] implemented GitVersionProvider, simplified initial setup of DefaultChangeWatcher --- .../Src/DefaultChangeWatcher.cs | 60 ++------- .../VersionControl/GitAddIn/GitAddIn.addin | 5 + .../VersionControl/GitAddIn/GitAddIn.csproj | 1 + .../GitAddIn/Src/GitVersionProvider.cs | 118 ++++++++++++++++++ ...nDiffProvider.cs => SvnVersionProvider.cs} | 9 -- .../SubversionAddIn/SubversionAddIn.csproj | 2 +- .../Editor/IDocumentBaseVersionProvider.cs | 7 -- 7 files changed, 132 insertions(+), 70 deletions(-) create mode 100644 src/AddIns/VersionControl/GitAddIn/Src/GitVersionProvider.cs rename src/AddIns/VersionControl/SubversionAddIn/Src/{SvnDiffProvider.cs => SvnVersionProvider.cs} (72%) diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/DefaultChangeWatcher.cs b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/DefaultChangeWatcher.cs index c38b653d7d..79eabf5031 100644 --- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/DefaultChangeWatcher.cs +++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/DefaultChangeWatcher.cs @@ -64,13 +64,10 @@ namespace ICSharpCode.AvalonEdit.AddIn Stream baseFileStream = GetBaseVersion(); string baseFile = ReadAll(baseFileStream); - Stream currentFileStream = GetCurrentVersion(); - string currentFile = ReadAll(currentFileStream); - - List baseFileOffsets = CalculateLineOffsets(baseFile); - List currentFileOffsets = CalculateLineOffsets(currentFile); - - MyersDiff.MyersDiff diff = new MyersDiff.MyersDiff(new StringSequence(baseFile), new StringSequence(currentFile)); + MyersDiff.MyersDiff diff = new MyersDiff.MyersDiff( + new StringSequence(baseFile), + new StringSequence(textDocument.Text) + ); if (diff == null) changeList.InsertRange(0, document.TotalNumberOfLines + 1, new LineChangeInfo(ChangeType.None, "")); @@ -78,48 +75,18 @@ namespace ICSharpCode.AvalonEdit.AddIn changeList.Add(new LineChangeInfo(ChangeType.None, "")); int lastEndLine = 0; foreach (Edit edit in diff.GetEdits()) { - int beginLine = OffsetToLineNumber(currentFileOffsets, edit.BeginB); - int endLine = OffsetToLineNumber(currentFileOffsets, edit.EndB); + int beginLine = textDocument.GetLineByOffset(edit.BeginB).LineNumber; + int endLine = textDocument.GetLineByOffset(edit.EndB).LineNumber; changeList.InsertRange(changeList.Count, beginLine - lastEndLine, new LineChangeInfo(ChangeType.None, "")); changeList.InsertRange(changeList.Count, endLine - beginLine, new LineChangeInfo(edit.EditType, "")); lastEndLine = endLine; } - changeList.InsertRange(changeList.Count, document.TotalNumberOfLines - lastEndLine, new LineChangeInfo(ChangeType.None, "")); + changeList.InsertRange(changeList.Count, textDocument.LineCount - lastEndLine, new LineChangeInfo(ChangeType.None, "")); } OnChangeOccurred(EventArgs.Empty); } - List CalculateLineOffsets(string fileContent) - { - List offsets = new List(); - - int current = 0; - offsets.Add(current); - - while ((current = fileContent.IndexOfAny(new[] { '\r', '\n' }, current + 1)) != -1) { - switch (fileContent[current]) { - case '\r': - if (current + 1 < fileContent.Length && fileContent[current + 1] != '\n') - offsets.Add(current + 1); - break; - case '\n': - offsets.Add(current + 1); - break; - } - } - - return offsets; - } - - int OffsetToLineNumber(List lineOffsets, int offset) - { - int lineNumber = lineOffsets.BinarySearch(offset); - if (lineNumber < 0) - lineNumber = (~lineNumber) - 1; - return lineNumber + 1; - } - string ReadAll(Stream stream) { using (StreamReader reader = new StreamReader(stream)) { @@ -140,19 +107,6 @@ namespace ICSharpCode.AvalonEdit.AddIn return new DefaultVersionProvider().OpenBaseVersion(fileName); } - Stream GetCurrentVersion() - { - string fileName = ((ITextEditor)document.GetService(typeof(ITextEditor))).FileName; - - foreach (IDocumentVersionProvider provider in VersioningServices.Instance.DocumentVersionProviders) { - var result = provider.OpenCurrentVersion(fileName); - if (result != null) - return result; - } - - return new DefaultVersionProvider().OpenCurrentVersion(fileName); - } - void UndoStackPropertyChanged(object sender, PropertyChangedEventArgs e) { // if (textDocument.UndoStack.IsOriginalFile) diff --git a/src/AddIns/VersionControl/GitAddIn/GitAddIn.addin b/src/AddIns/VersionControl/GitAddIn/GitAddIn.addin index 9bfc432a5a..b03e2245c8 100644 --- a/src/AddIns/VersionControl/GitAddIn/GitAddIn.addin +++ b/src/AddIns/VersionControl/GitAddIn/GitAddIn.addin @@ -18,6 +18,11 @@ class = "ICSharpCode.GitAddIn.RegisterEventsCommand"/> + + + + diff --git a/src/AddIns/VersionControl/GitAddIn/GitAddIn.csproj b/src/AddIns/VersionControl/GitAddIn/GitAddIn.csproj index 64debaa93f..0160ca1664 100644 --- a/src/AddIns/VersionControl/GitAddIn/GitAddIn.csproj +++ b/src/AddIns/VersionControl/GitAddIn/GitAddIn.csproj @@ -61,6 +61,7 @@ + diff --git a/src/AddIns/VersionControl/GitAddIn/Src/GitVersionProvider.cs b/src/AddIns/VersionControl/GitAddIn/Src/GitVersionProvider.cs new file mode 100644 index 0000000000..04ec07f143 --- /dev/null +++ b/src/AddIns/VersionControl/GitAddIn/Src/GitVersionProvider.cs @@ -0,0 +1,118 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using System.IO.Pipes; +using System.Runtime.InteropServices; + +using ICSharpCode.SharpDevelop.Editor; +using ICSharpCode.SharpDevelop.Util; +using Microsoft.Win32.SafeHandles; + +namespace ICSharpCode.GitAddIn +{ + public class GitVersionProvider : IDocumentVersionProvider + { + #region PInvoke + [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] + [return: MarshalAs(UnmanagedType.Bool)] + static extern bool CreateProcess( + string lpApplicationName, + string lpCommandLine, + IntPtr lpProcessAttributes, + IntPtr lpThreadAttributes, + [MarshalAs(UnmanagedType.Bool)] bool bInheritHandles, + uint dwCreationFlags, + IntPtr lpEnvironment, + string lpCurrentDirectory, + [In] ref StartupInfo lpStartupInfo, + out PROCESS_INFORMATION lpProcessInformation + ); + + [DllImport("kernel32.dll", SetLastError = true)] + static extern IntPtr GetStdHandle(int nStdHandle); + + const uint STARTF_USESTDHANDLES = 0x00000100; + + const int STD_INPUT_HANDLE = -10; + const int STD_OUTPUT_HANDLE = -11; + const int STD_ERROR_HANDLE = -12; + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] + struct StartupInfo + { + public uint cb; + public string lpReserved; + public string lpDesktop; + public string lpTitle; + public uint dwX; + public uint dwY; + public uint dwXSize; + public uint dwYSize; + public uint dwXCountChars; + public uint dwYCountChars; + public uint dwFillAttribute; + public uint dwFlags; + public short wShowWindow; + public short cbReserved2; + public IntPtr lpReserved2; + public IntPtr hStdInput; + public SafePipeHandle hStdOutput; + public IntPtr hStdError; + } + + [StructLayout(LayoutKind.Sequential)] + struct PROCESS_INFORMATION + { + public IntPtr hProcess; + public IntPtr hThread; + public int dwProcessId; + public int dwThreadId; + } + #endregion + + public Stream OpenBaseVersion(string fileName) + { + if (!Git.IsInWorkingCopy(fileName)) + return null; + + return OpenOutput(fileName, GetBlobHash(fileName)); + } + + string GetBlobHash(string fileName) + { + ProcessRunner runner = new ProcessRunner(); + runner.WorkingDirectory = Path.GetDirectoryName(fileName); + runner.Start("cmd", "/c git ls-tree HEAD " + Path.GetFileName(fileName)); + runner.WaitForExit(); + + return runner.StandardOutput + .Trim() + .Split(new[] { " ", "\t" }, StringSplitOptions.RemoveEmptyEntries)[2]; + } + + Stream OpenOutput(string fileName, string blobHash) + { + AnonymousPipeServerStream pipe = new AnonymousPipeServerStream(PipeDirection.In, HandleInheritability.Inheritable); + + StartupInfo startupInfo = new GitVersionProvider.StartupInfo(); + startupInfo.dwFlags = STARTF_USESTDHANDLES; + startupInfo.hStdOutput = pipe.ClientSafePipeHandle; + startupInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE); + startupInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE); + startupInfo.cb = 16; + + PROCESS_INFORMATION procInfo; + + if (!CreateProcess(null, string.Format("cmd /c git cat-file blob {0}", blobHash), + IntPtr.Zero, IntPtr.Zero, true, 0, IntPtr.Zero, Path.GetDirectoryName(fileName), ref startupInfo, + out procInfo)) + return null; + + pipe.DisposeLocalCopyOfClientHandle(); + + return pipe; + } + } +} diff --git a/src/AddIns/VersionControl/SubversionAddIn/Src/SvnDiffProvider.cs b/src/AddIns/VersionControl/SubversionAddIn/Src/SvnVersionProvider.cs similarity index 72% rename from src/AddIns/VersionControl/SubversionAddIn/Src/SvnDiffProvider.cs rename to src/AddIns/VersionControl/SubversionAddIn/Src/SvnVersionProvider.cs index 0e4a4b323b..45c91d2329 100644 --- a/src/AddIns/VersionControl/SubversionAddIn/Src/SvnDiffProvider.cs +++ b/src/AddIns/VersionControl/SubversionAddIn/Src/SvnVersionProvider.cs @@ -19,14 +19,5 @@ namespace ICSharpCode.Svn using (SvnClientWrapper client = new SvnClientWrapper()) return client.OpenBaseVersion(fileName); } - - public Stream OpenCurrentVersion(string fileName) - { - if (!SvnClientWrapper.IsInSourceControl(fileName)) - return null; - - using (SvnClientWrapper client = new SvnClientWrapper()) - return client.OpenCurrentVersion(fileName); - } } } diff --git a/src/AddIns/VersionControl/SubversionAddIn/SubversionAddIn.csproj b/src/AddIns/VersionControl/SubversionAddIn/SubversionAddIn.csproj index d30caa151e..999b5d4f2b 100644 --- a/src/AddIns/VersionControl/SubversionAddIn/SubversionAddIn.csproj +++ b/src/AddIns/VersionControl/SubversionAddIn/SubversionAddIn.csproj @@ -83,7 +83,7 @@ - + InfoPanel.cs diff --git a/src/Main/Base/Project/Src/Editor/IDocumentBaseVersionProvider.cs b/src/Main/Base/Project/Src/Editor/IDocumentBaseVersionProvider.cs index 8fb96afdb8..89cacce1f3 100644 --- a/src/Main/Base/Project/Src/Editor/IDocumentBaseVersionProvider.cs +++ b/src/Main/Base/Project/Src/Editor/IDocumentBaseVersionProvider.cs @@ -16,8 +16,6 @@ namespace ICSharpCode.SharpDevelop.Editor /// to disk or a base version provided by any VCS. /// Stream OpenBaseVersion(string fileName); - - Stream OpenCurrentVersion(string fileName); } public sealed class DefaultVersionProvider : IDocumentVersionProvider @@ -26,11 +24,6 @@ namespace ICSharpCode.SharpDevelop.Editor { return File.OpenRead(fileName); } - - public Stream OpenCurrentVersion(string fileName) - { - return File.OpenRead(fileName); - } } public class VersioningServices