internal void Open(string directory)
        {
            workingDirectory = directory;

            tracker = new GitFileStatusTracker(directory);
            if (tracker.IsGit)
            {
                directory = tracker.WorkingDirectory;
            }

            if (Directory.Exists(directory))
            {
                if (fileSystemWatcher != null)
                {
                    fileSystemWatcher.Dispose();
                }

                fileSystemWatcher = new FileSystemWatcher(directory);
                fileSystemWatcher.IncludeSubdirectories = true;
                //fileSystemWatcher.Created += new FileSystemEventHandler(fileSystemWatcher_Changed);
                fileSystemWatcher.Deleted += new FileSystemEventHandler(fileSystemWatcher_Changed);
                //fileSystemWatcher.Renamed += new FileSystemEventHandler(fileSystemWatcher_Changed);
                fileSystemWatcher.Changed            += new FileSystemEventHandler(fileSystemWatcher_Changed);
                fileSystemWatcher.EnableRaisingEvents = true;
            }

            GraphChanged(this, null);
        }
        public IEnumerable<HunkRangeInfo> GetGitDiffFor(ITextDocument textDocument, ITextSnapshot snapshot)
        {
            string fileName = textDocument.FilePath;
            GitFileStatusTracker tracker = new GitFileStatusTracker(Path.GetDirectoryName(fileName));
            if (!tracker.HasGitRepository || tracker.Repository.Resolve(Constants.HEAD) == null)
                yield break;

            GitFileStatus status = tracker.GetFileStatus(fileName);
            if (status == GitFileStatus.New || status == GitFileStatus.Added)
                yield break;

            HistogramDiff diff = new HistogramDiff();
            diff.SetFallbackAlgorithm(null);
            string currentText = snapshot.GetText();

            byte[] preamble = textDocument.Encoding.GetPreamble();
            byte[] content = textDocument.Encoding.GetBytes(currentText);
            if (preamble.Length > 0)
            {
                byte[] completeContent = new byte[preamble.Length + content.Length];
                Buffer.BlockCopy(preamble, 0, completeContent, 0, preamble.Length);
                Buffer.BlockCopy(content, 0, completeContent, preamble.Length, content.Length);
                content = completeContent;
            }

            byte[] previousContent = GetPreviousRevision(tracker, fileName);
            RawText b = new RawText(content);
            RawText a = new RawText(previousContent);
            EditList edits = diff.Diff(RawTextComparator.DEFAULT, a, b);
            foreach (Edit edit in edits)
                yield return new HunkRangeInfo(snapshot, edit, a, b);
        }
        public void GetChangedFilesTest1()
        {
            var stopwatch = new Stopwatch();

            string workingFolder        = @"D:\Users\Public\My Projects Tryout\orchard-1.0.20\src";
            GitFileStatusTracker target = new GitFileStatusTracker(workingFolder);

            stopwatch.Start();
            var list = target.GetChangedFiles();

            stopwatch.Stop();
            Debug.WriteLine(list.Count() + ":" + stopwatch.ElapsedMilliseconds);

            stopwatch.Reset();
            stopwatch.Start();
            var changes = target.ChangedFiles;

            stopwatch.Stop();
            Debug.WriteLine(changes.Count() + ":" + stopwatch.ElapsedMilliseconds);

            Assert.AreEqual(list.Count(), changes.Count());

            GitBash.GitExePath = @"C:\Program Files (x86)\Git\bin\sh.exe";
            stopwatch.Reset();
            stopwatch.Start();
            GitBash.Run("status --porcelain -z --untracked-files", workingFolder);

            stopwatch.Stop();
            Debug.WriteLine(stopwatch.ElapsedMilliseconds);
        }
        private static byte[] GetPreviousRevision(GitFileStatusTracker tracker, string fileName)
        {
            byte[] cachedBytes = tracker.GetFileContent(fileName);
            if (cachedBytes == null)
                return cachedBytes;

            if (Environment.NewLine != "\r\n")
                return cachedBytes;

            WorkingTreeOptions options = tracker.Repository.GetConfig().Get(WorkingTreeOptions.KEY);
            if (options.GetAutoCRLF() != CoreConfig.AutoCRLF.TRUE)
                return cachedBytes;

            int lines = 0;
            for (int i = 0; i < cachedBytes.Length; i++)
            {
                if (cachedBytes[i] == '\n' && (i == 0 || cachedBytes[i - 1] != '\r'))
                    lines++;
            }

            byte[] result = new byte[cachedBytes.Length + lines];
            for (int i = 0, j = 0; i < cachedBytes.Length; i++)
            {
                byte current = cachedBytes[i];
                if (current == '\n' && (i == 0 || cachedBytes[i - 1] != '\r'))
                    result[j++] = (byte)'\r';

                result[j++] = current;
            }

            return result;
        }
        internal void Show(GitFileStatusTracker tracker, string commitId)
        {
            this.tracker = tracker;
            var repositoryGraph = tracker.RepositoryGraph;
            var commit = repositoryGraph.GetCommit(commitId);
            if (commit == null)
            {
                this.lblCommit.Content = "Cannot find commit: " + commit.Id;
            }
            else
            {
                this.lblCommit.Content = "Hash: " + commit.Id;
                this.lblMessage.Content = "Message: " + commit.Message;
                this.lblAuthor.Content = commit.CommitterName + " " + commit.CommitDateRelative;
                this.fileTree.ItemsSource = repositoryGraph.GetTree(commitId).Children;
                this.patchList.ItemsSource = repositoryGraph.GetChanges(commitId);
                //this.radioShowFileTree.IsChecked = true;
                this.radioShowFileTree.IsEnabled = true;
                this.toolWindow.ClearEditor();
                this.commitId1 = commit.ParentIds.Count > 0 ? commit.ParentIds[0] : null;
                this.commitId2 = commit.Id;
                this.btnSwitch.Visibility = Visibility.Collapsed;
                this.txtFileName.Text = "";

                this.radioShowChanges.IsChecked = true;
                this.fileTree.Visibility = Visibility.Collapsed;
                this.patchList.Visibility = Visibility.Visible;

            }
        }
예제 #6
0
        private void AddProject(IVsHierarchy pHierarchy)
        {
            string projectName = GetProjectFileName(pHierarchy);

            if (string.IsNullOrEmpty(projectName))
            {
                return;
            }
            string projectDirecotry = Path.GetDirectoryName(projectName);

            // Debug.WriteLine("==== Adding project: " + projectDirecotry);

            var tracker = new GitFileStatusTracker(projectDirecotry);

            if (string.IsNullOrEmpty(projectDirecotry) ||
                trackers.Any(t => t.IsGit && string.Compare(
                                 t.WorkingDirectory,
                                 tracker.WorkingDirectory, true) == 0))
            {
                return;
            }

            trackers.Add(tracker);

            // Debug.WriteLine("==== Added git tracker: " + tracker.WorkingDirectory);
        }
        public void GetFileStatusTest1()
        {
            var stopwatch = new Stopwatch();

            string workingFolder        = @"D:\Users\Public\My Projects Tryout\orchard-1.0.20\src";
            GitFileStatusTracker target = new GitFileStatusTracker(workingFolder);

            var list1 = new List <GitFileStatus>();
            var list2 = new List <GitFileStatus>();

            var list = target.GetChangedFiles();

            stopwatch.Start();
            foreach (var f in list)
            {
                list1.Add(target.GetFileStatusNoCache(f.FileName));
            }
            stopwatch.Stop();
            Debug.WriteLine(list.Count() + ":" + stopwatch.ElapsedMilliseconds);

            stopwatch.Reset();
            stopwatch.Start();
            foreach (var f in list)
            {
                list2.Add(target.GetFileStatusNoCacheOld(f.FileName));
            }
            stopwatch.Stop();
            Debug.WriteLine(list.Count() + ":" + stopwatch.ElapsedMilliseconds);

            for (int i = 0; i < list1.Count; i++)
            {
                Assert.AreEqual(list1[i], list2[i]);
            }
        }
        internal void Show(GitFileStatusTracker tracker, string commitId)
        {
            try
            {
                //var stopWatch = new Stopwatch();
                //stopWatch.Start();

                this.fileTree.ItemsSource = null;
                this.patchList.ItemsSource = null;

                this.tracker = tracker;
                var repositoryGraph = tracker.RepositoryGraph;
                var commit = repositoryGraph.GetCommit(commitId);
                if (commit == null)
                {
                    this.lblCommit.Content = "Cannot find commit: " + commit.Id;
                    this.radioShowChanges.IsEnabled = false;
                    this.radioShowFileTree.IsEnabled = false;
                }
                else
                {
                    this.radioShowChanges.IsEnabled = true;
                    this.radioShowFileTree.IsEnabled = true;

                    //this.lblCommit.Content = commit.Id;
                    this.lblMessage.Content = commit.ToString();
                    this.lblAuthor.Content = commit.CommitterName + " " + commit.CommitDateRelative;
                    //this.fileTree.ItemsSource = repositoryGraph.GetTree(commitId).Children;
                    this.patchList.ItemsSource = repositoryGraph.GetChanges(commitId);
                    this.radioShowFileTree.IsEnabled = true;
                    ClearEditor();
                    this.commitId1 = commit.ParentIds.Count > 0 ? commit.ParentIds[0] : null;
                    this.commitId2 = commit.Id;
                    this.btnSwitch.Visibility = Visibility.Collapsed;
                    this.txtFileName.Text = "";
                    this.Comments = commit.Message;

                    this.radioShowChanges.IsChecked = true;
                    this.fileTree.Visibility = Visibility.Collapsed;
                    this.patchList.Visibility = Visibility.Visible;

                    var names2 = repositoryGraph.Refs
                        .Where(r => r.Id.StartsWith(commitId2))
                        .Select(r => r.Name);

                    var name2 = names2.Count() == 0 ? commitId2 : string.Join(", ", names2.ToArray());
                    this.lblCommit.Content = name2;

                    if (this.patchList.Items.Count > 0) this.patchList.SelectedIndex = 0;
                }

                //stopWatch.Stop();
                //this.lblCommit.Content = stopWatch.ElapsedMilliseconds.ToString();
            }
            catch (Exception ex)
            {
                this.lblCommit.Content = ex.Message + " Please try again.";
            }
        }
        public void HasGitRepositoryTest()
        {
            GitFileStatusTracker.Init(tempFolder);
            GitFileStatusTracker tracker = new GitFileStatusTracker(tempFolder);

            Assert.IsTrue(tracker.HasGitRepository);
            Assert.AreEqual(tempFolder, tracker.GitWorkingDirectory);
            Assert.IsTrue(Directory.Exists(tempFolder + "\\.git"));
        }
        public void GetRepositoryDirectoryTest()
        {
            GitFileStatusTracker.Init(tempFolder);
            var newFolder = tempFolder + "\\t t\\a a";

            Directory.CreateDirectory(newFolder);
            GitFileStatusTracker tracker = new GitFileStatusTracker(newFolder);

            Assert.AreEqual(tempFolder, tracker.GitWorkingDirectory);
        }
        public void LastCommitMessageTest()
        {
            GitFileStatusTracker.Init(tempFolder);
            File.WriteAllLines(tempFile, lines);

            GitFileStatusTracker tracker = new GitFileStatusTracker(tempFolder);

            tracker.StageFile(tempFile);

            tracker.Commit("中文 1čtestč");
            Assert.IsTrue(tracker.LastCommitMessage.StartsWith("中文 1čtestč"));
        }
예제 #12
0
        /// <summary>
        /// Determines whether the solution is git TFS controlled.
        /// </summary>
        /// <returns>
        /// <c>true</c> if the solution is git TFS controlled.
        /// </returns>
        private bool IsSolutionGitTfsControlled()
        {
            var repositoryDirectory = GitFileStatusTracker.GetRepositoryDirectory(this.GetSolutionDirectory());

            if (!string.IsNullOrEmpty(repositoryDirectory))
            {
                var expectedGitTfsDirectory = repositoryDirectory + "\\.git\\tfs";
                return(Directory.Exists(expectedGitTfsDirectory));
            }

            return(false);
        }
        internal static string GetPrompt(GitFileStatusTracker tracker)
        {
            if (tracker == null || !tracker.IsGit)
            {
                return("No Git Repository");
            }
            var changed = tracker.ChangedFiles;

            return(string.Format("{0} +{1} ~{2} -{3} !{4}", tracker.CurrentBranchDisplayName,
                                 changed.Where(f => f.Status == GitFileStatus.New || f.Status == GitFileStatus.Added).Count(),
                                 changed.Where(f => f.Status == GitFileStatus.Modified || f.Status == GitFileStatus.Staged).Count(),
                                 changed.Where(f => f.Status == GitFileStatus.Deleted || f.Status == GitFileStatus.Removed).Count(),
                                 changed.Where(f => f.Status == GitFileStatus.Conflict).Count()
                                 ));
        }
        public void DiffFileTest()
        {
            GitFileStatusTracker.Init(tempFolder);
            File.WriteAllLines(tempFile, lines);

            GitFileStatusTracker tracker = new GitFileStatusTracker(tempFolder);

            tracker.StageFile(tempFile);
            tracker.Commit("test message");
            File.WriteAllText(tempFile, "changed text");
            var diffFile = tracker.DiffFile(tempFile);
            var diff     = File.ReadAllText(diffFile);

            Console.WriteLine(diff);
            Assert.IsTrue(diff.Contains("@@ -1,3 +1 @@"));
        }
예제 #15
0
        public void FileNameCaseTest()
        {
            GitFileStatusTracker.Init(tempFolder);
            File.WriteAllLines(tempFile, lines);

            GitFileStatusTracker tracker = new GitFileStatusTracker(tempFolder);

            tracker.StageFile(tempFile);

            tracker.Commit("test message");
            Assert.IsTrue(tracker.LastCommitMessage.StartsWith("test message"));
            tempFile = tempFile.Replace("test", "TEST");
            File.WriteAllText(tempFile, "changed text");
            tracker.Refresh();
            Assert.AreEqual(GitFileStatus.Modified, tracker.GetFileStatus(tempFile));
        }
        internal static IEnumerable <string> GetOptions(GitFileStatusTracker tracker, string command)
        {
            if (tracker == null)
            {
                return new string[] { }
            }
            ;
            var options = Commands.Where(i => Regex.IsMatch(command, i.Key)).Select(i => i.Value).FirstOrDefault();

            if (options == null)
            {
                return new string[] { }
            }
            ;
            switch (options[0])
            {
            case "*branches*":
                return(tracker.RepositoryGraph.Refs
                       .Where(r => r.Type == RefTypes.Branch)
                       .Select(r => r.Name));

            case "*tags*":
                return(tracker.RepositoryGraph.Refs
                       .Where(r => r.Type == RefTypes.Tag)
                       .Select(r => r.Name));

            case "*remotes*":
                return(tracker.Remotes);

            case "*configs*":
                return(tracker.Configs.Keys);

            case "*commits*":
                return(tracker.RepositoryGraph.Commits
                       .OrderByDescending(c => c.AuthorDate)
                       .Select(r => r.ShortId));
            }

            if (options[0].Contains("|"))
            {
                return(options[0].Split('|'));
            }
            else
            {
                return(options);
            }
        }
        public void GetFileStatusTest()
        {
            GitFileStatusTracker.Init(tempFolder);
            GitFileStatusTracker tracker = new GitFileStatusTracker(tempFolder);

            File.WriteAllLines(tempFile, lines);
            Assert.AreEqual(GitFileStatus.New, tracker.GetFileStatus(tempFile));

            tracker.StageFile(tempFile);
            tracker.Refresh();
            Assert.AreEqual(GitFileStatus.Added, tracker.GetFileStatus(tempFile));

            tracker.UnStageFile(tempFile);
            tracker.Refresh();
            Assert.AreEqual(GitFileStatus.New, tracker.GetFileStatus(tempFile));

            tracker.StageFile(tempFile);
            tracker.Refresh();
            Assert.AreEqual(GitFileStatus.Added, tracker.GetFileStatus(tempFile));

            tracker.Commit("中文 1čtestč");
            Assert.AreEqual(GitFileStatus.Tracked, tracker.GetFileStatus(tempFile));

            File.WriteAllText(tempFile, "changed text");
            tracker.Refresh();
            Assert.AreEqual(GitFileStatus.Modified, tracker.GetFileStatus(tempFile));

            tracker.StageFile(tempFile);
            tracker.Refresh();
            Assert.AreEqual(GitFileStatus.Staged, tracker.GetFileStatus(tempFile));

            tracker.UnStageFile(tempFile);
            tracker.Refresh();
            Assert.AreEqual(GitFileStatus.Modified, tracker.GetFileStatus(tempFile));

            File.Delete(tempFile);
            tracker.Refresh();
            Assert.AreEqual(GitFileStatus.Deleted, tracker.GetFileStatus(tempFile));

            tracker.StageFile(tempFile);
            tracker.Refresh();
            Assert.AreEqual(GitFileStatus.Removed, tracker.GetFileStatus(tempFile));

            tracker.UnStageFile(tempFile);
            tracker.Refresh();
            Assert.AreEqual(GitFileStatus.Deleted, tracker.GetFileStatus(tempFile));
        }
        public void SaveFileFromRepositoryTest()
        {
            GitFileStatusTracker.Init(tempFolder);
            File.WriteAllLines(tempFile, lines);

            GitFileStatusTracker tracker = new GitFileStatusTracker(tempFolder);

            tracker.StageFile(tempFile);
            tracker.Commit("test");

            tracker.SaveFileFromRepository(tempFile, tempFile + ".bk");
            var newlines = File.ReadAllLines(tempFile + ".bk");

            Assert.AreEqual(lines[0], newlines[0]);
            Assert.AreEqual(lines[1], newlines[1]);
            Assert.AreEqual(lines[2], newlines[2]);
        }
        public void AmendCommitTest()
        {
            GitFileStatusTracker.Init(tempFolder);
            File.WriteAllLines(tempFile, lines);

            GitFileStatusTracker tracker = new GitFileStatusTracker(tempFolder);

            tracker.StageFile(tempFile);

            tracker.Commit("中文 1čtestč");
            Assert.IsTrue(tracker.LastCommitMessage.StartsWith("中文 1čtestč"));

            File.WriteAllText(tempFile, "changed text");
            tracker.StageFile(tempFile);
            tracker.Commit("new message", true);
            Assert.IsTrue(tracker.LastCommitMessage.StartsWith("new message"));
        }
        internal void Show(GitFileStatusTracker tracker, string commitId1, string commitId2)
        {
            try
            {
                this.tracker = tracker;
                var repositoryGraph = tracker.RepositoryGraph;

                var msg1 = repositoryGraph.Commits
                    .Where(r => r.Id.StartsWith(commitId1))
                    .Select(r => string.Format("{0} ({1}, {2})", r.Message, r.CommitDateRelative, r.CommitterName))
                    .First().Replace("\r", "");

                var msg2 = repositoryGraph.Commits
                    .Where(r => r.Id.StartsWith(commitId2))
                    .Select(r => string.Format("{0} ({1}, {2})", r.Message, r.CommitDateRelative, r.CommitterName))
                    .First().Replace("\r", "");

                var names1 = repositoryGraph.Refs
                    .Where(r => r.Id.StartsWith(commitId1))
                    .Select(r => r.Name);

                var names2 = repositoryGraph.Refs
                    .Where(r => r.Id.StartsWith(commitId2))
                    .Select(r => r.Name);

                var name1 = names1.Count() == 0 ? commitId1 : string.Join(", ", names1.ToArray());
                var name2 = names2.Count() == 0 ? commitId2 : string.Join(", ", names2.ToArray());

                this.lblCommit.Content = string.Format("[{1}] {0}", msg1, name1);
                this.lblMessage.Content = string.Format("[{1}] {0}", msg2, name2);
                this.lblAuthor.Content = "";

                this.patchList.ItemsSource = repositoryGraph.GetChanges(commitId1, commitId2);
                this.radioShowChanges.IsChecked = true;
                this.radioShowFileTree.IsEnabled = false;
                this.toolWindow.ClearEditor();
                this.commitId1 = commitId1;
                this.commitId2 = commitId2;
                this.btnSwitch.Visibility = Visibility.Visible;
                this.txtFileName.Text = "";
            }
            catch(Exception ex)
            {
                this.lblCommit.Content = ex.Message + " Please try again.";
            }
        }
        internal void Show(GitFileStatusTracker tracker, string commitId1, string commitId2)
        {
            try
            {
                this.tracker = tracker;
                var repositoryGraph = tracker.RepositoryGraph;

                var msg1 = repositoryGraph.Commits
                           .Where(r => r.Id.StartsWith(commitId1))
                           .Select(r => string.Format("{0} ({1}, {2})", r.Message, r.CommitDateRelative, r.CommitterName))
                           .First().Replace("\r", "");

                var msg2 = repositoryGraph.Commits
                           .Where(r => r.Id.StartsWith(commitId2))
                           .Select(r => string.Format("{0} ({1}, {2})", r.Message, r.CommitDateRelative, r.CommitterName))
                           .First().Replace("\r", "");

                var names1 = repositoryGraph.Refs
                             .Where(r => r.Id.StartsWith(commitId1))
                             .Select(r => r.Name);

                var names2 = repositoryGraph.Refs
                             .Where(r => r.Id.StartsWith(commitId2))
                             .Select(r => r.Name);

                var name1 = names1.Count() == 0 ? commitId1 : string.Join(", ", names1.ToArray());
                var name2 = names2.Count() == 0 ? commitId2 : string.Join(", ", names2.ToArray());

                this.lblCommit.Content  = string.Format("[{1}] {0}", msg1, name1);
                this.lblMessage.Content = string.Format("[{1}] {0}", msg2, name2);
                this.lblAuthor.Content  = "";

                this.patchList.ItemsSource       = repositoryGraph.GetChanges(commitId1, commitId2);
                this.radioShowChanges.IsChecked  = true;
                this.radioShowFileTree.IsEnabled = false;
                this.toolWindow.ClearEditor();
                this.commitId1            = commitId1;
                this.commitId2            = commitId2;
                this.btnSwitch.Visibility = Visibility.Visible;
                this.txtFileName.Text     = "";
            }
            catch (Exception ex)
            {
                this.lblCommit.Content = ex.Message + " Please try again.";
            }
        }
        public void CheckOutFileTest()
        {
            GitFileStatusTracker.Init(tempFolder);
            File.WriteAllLines(tempFile, lines);

            GitFileStatusTracker tracker = new GitFileStatusTracker(tempFolder);

            tracker.StageFile(tempFile);
            tracker.Commit("test");

            File.WriteAllText(tempFile, "changed text");
            tracker.CheckOutFile(tempFile);
            var newlines = File.ReadAllLines(tempFile);

            Assert.AreEqual(lines[0], newlines[0]);
            Assert.AreEqual(lines[1], newlines[1]);
            Assert.AreEqual(lines[2], newlines[2]);
        }
예제 #23
0
        private static byte[] GetPreviousRevision(GitFileStatusTracker tracker, string fileName)
        {
            byte[] cachedBytes = tracker.GetFileContent(fileName);
            if (cachedBytes == null)
            {
                return(cachedBytes);
            }

            if (Environment.NewLine != "\r\n")
            {
                return(cachedBytes);
            }

            WorkingTreeOptions options = tracker.Repository.GetConfig().Get(WorkingTreeOptions.KEY);

            if (options.GetAutoCRLF() != CoreConfig.AutoCRLF.TRUE)
            {
                return(cachedBytes);
            }

            int lines = 0;

            for (int i = 0; i < cachedBytes.Length; i++)
            {
                if (cachedBytes[i] == '\n' && (i == 0 || cachedBytes[i - 1] != '\r'))
                {
                    lines++;
                }
            }

            byte[] result = new byte[cachedBytes.Length + lines];
            for (int i = 0, j = 0; i < cachedBytes.Length; i++)
            {
                byte current = cachedBytes[i];
                if (current == '\n' && (i == 0 || cachedBytes[i - 1] != '\r'))
                {
                    result[j++] = (byte)'\r';
                }

                result[j++] = current;
            }

            return(result);
        }
        public void GetBranchTest()
        {
            GitFileStatusTracker.Init(tempFolder);
            File.WriteAllLines(tempFile, lines);

            GitFileStatusTracker tracker = new GitFileStatusTracker(tempFolder);

            tracker.StageFile(tempFile);
            Assert.AreEqual("master", tracker.CurrentBranch);

            tracker.Commit("test message");
            Assert.AreEqual("master", tracker.CurrentBranch);

            tempFile = tempFile.Replace("test", "TEST");
            File.WriteAllText(tempFile, "changed text");

            tracker.CheckOutBranch("dev", true);
            Assert.AreEqual("dev", tracker.CurrentBranch);
        }
예제 #25
0
        public IEnumerable <HunkRangeInfo> GetGitDiffFor(ITextDocument textDocument, ITextSnapshot snapshot)
        {
            string fileName = textDocument.FilePath;
            GitFileStatusTracker tracker = new GitFileStatusTracker(Path.GetDirectoryName(fileName));

            if (!tracker.IsGit)
            {
                yield break;
            }

            GitFileStatus status = tracker.GetFileStatus(fileName);

            if (status == GitFileStatus.New || status == GitFileStatus.Added)
            {
                yield break;
            }

            HistogramDiff diff = new HistogramDiff();

            diff.SetFallbackAlgorithm(null);
            string currentText = snapshot.GetText();

            byte[] preamble = textDocument.Encoding.GetPreamble();
            byte[] content  = textDocument.Encoding.GetBytes(currentText);
            if (preamble.Length > 0)
            {
                byte[] completeContent = new byte[preamble.Length + content.Length];
                Buffer.BlockCopy(preamble, 0, completeContent, 0, preamble.Length);
                Buffer.BlockCopy(content, 0, completeContent, preamble.Length, content.Length);
                content = completeContent;
            }

            byte[]   previousContent = null; //GetPreviousRevision(tracker, fileName);
            RawText  b     = new RawText(content);
            RawText  a     = new RawText(previousContent ?? new byte[0]);
            EditList edits = diff.Diff(RawTextComparator.DEFAULT, a, b);

            foreach (Edit edit in edits)
            {
                yield return(new HunkRangeInfo(snapshot, edit, a, b));
            }
        }
예제 #26
0
        private void Window_Drop(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
            {
                this.Activate();

                var dropped = ((string[])e.Data.GetData(DataFormats.FileDrop, true))[0];

                if (!Directory.Exists(dropped))
                {
                    dropped = Path.GetDirectoryName(dropped);
                }
                var gitWorkingFolder = GitFileStatusTracker.GetRepositoryDirectory(dropped);
                if (Directory.Exists(dropped) && gitWorkingFolder != null &&
                    MessageBox.Show("Do you want to open Git repository from " + gitWorkingFolder,
                                    "Git repository found", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes)
                {
                    this.OpenRepository(dropped);
                }
            }
        }
        public void FileNameCaseTest()
        {
            GitFileStatusTracker.Init(tempFolder);
            File.WriteAllLines(tempFile, lines);

            GitFileStatusTracker tracker = new GitFileStatusTracker(tempFolder);

            tracker.StageFile(tempFile);

            tracker.Commit("test message");
            Assert.IsTrue(tracker.LastCommitMessage.StartsWith("test message"));
            tempFile = tempFile.Replace("test", "TEST");
            File.WriteAllText(tempFile, "changed text");
            tracker.Refresh();
            //This test fails all cases because status check uses ngit, never git.exe
            //Assert.AreEqual(GitFileStatus.Modified, tracker.GetFileStatus(tempFile));

            var file = tracker.ChangedFiles.First();

            Assert.AreEqual(GitFileStatus.Modified, file.Status);
        }
        internal void Open(string directory)
        {
            workingDirectory = directory;

            tracker = new GitFileStatusTracker(directory);
            if (tracker.HasGitRepository)
            {
                directory = tracker.GitWorkingDirectory;
            }

            if (Directory.Exists(directory))
            {
                fileSystemWatcher = new FileSystemWatcher(directory);
                fileSystemWatcher.IncludeSubdirectories = true;
                //fileSystemWatcher.Created += new FileSystemEventHandler(fileSystemWatcher_Changed);
                //fileSystemWatcher.Deleted += new FileSystemEventHandler(fileSystemWatcher_Changed);
                //fileSystemWatcher.Renamed += new FileSystemEventHandler(fileSystemWatcher_Changed);
                fileSystemWatcher.Changed            += new FileSystemEventHandler(fileSystemWatcher_Changed);
                fileSystemWatcher.EnableRaisingEvents = true;
            }
        }
        public void GetFileContentTest()
        {
            GitFileStatusTracker.Init(tempFolder);
            File.WriteAllLines(tempFile, lines);

            GitFileStatusTracker tracker = new GitFileStatusTracker(tempFolder);

            tracker.StageFile(tempFile);
            tracker.Commit("中文 1čtestč");

            var fileContent = tracker.GetFileContent(tempFile);

            using (var binWriter = new BinaryWriter(File.Open(tempFile + ".bk", System.IO.FileMode.Create)))
            {
                binWriter.Write(fileContent);
            }

            var newlines = File.ReadAllLines(tempFile + ".bk");

            Assert.AreEqual(lines[0], newlines[0]);
            Assert.AreEqual(lines[1], newlines[1]);
            Assert.AreEqual(lines[2], newlines[2]);
        }
        public void GetFileContentTestNegative()
        {
            GitFileStatusTracker tracker = new GitFileStatusTracker(tempFolder);
            var fileContent = tracker.GetFileContent(tempFile + ".bad");

            Assert.IsNull(fileContent);

            GitFileStatusTracker.Init(tempFolder);

            File.WriteAllLines(tempFile, lines);
            tracker     = new GitFileStatusTracker(tempFolder);
            fileContent = tracker.GetFileContent(tempFile + ".bad");
            Assert.IsNull(fileContent);

            tracker.StageFile(tempFile);
            fileContent = tracker.GetFileContent(tempFile + ".bad");
            Assert.IsNull(fileContent);

            tracker.Commit("中文 1čtestč");

            fileContent = tracker.GetFileContent(tempFile + ".bad");
            Assert.IsNull(fileContent);
        }
        public DiffUpdateBackgroundParser(ITextBuffer textBuffer, ITextBuffer documentBuffer, TaskScheduler taskScheduler, ITextDocumentFactoryService textDocumentFactoryService, IGitCommands commands)
            : base(textBuffer, taskScheduler, textDocumentFactoryService)
        {
            _documentBuffer = documentBuffer;
            _commands = commands;
            ReparseDelay = TimeSpan.FromMilliseconds(500);

            ITextDocument textDocument;
            if (TextDocumentFactoryService.TryGetTextDocument(TextBuffer, out textDocument))
            {
                GitFileStatusTracker tracker = new GitFileStatusTracker(Path.GetDirectoryName(textDocument.FilePath));
                if (tracker.HasGitRepository && tracker.Repository.Resolve(Constants.HEAD) != null)
                {
                    _watcher = new FileSystemWatcher(tracker.Repository.Directory.GetAbsolutePath());
                    _watcher.IncludeSubdirectories = true;
                    _watcher.Changed += HandleFileSystemChanged;
                    _watcher.Created += HandleFileSystemChanged;
                    _watcher.Deleted += HandleFileSystemChanged;
                    _watcher.Renamed += HandleFileSystemChanged;
                    _watcher.EnableRaisingEvents = true;
                }
            }
        }
        internal void Show(GitFileStatusTracker tracker, string commitId)
        {
            try
            {
                this.tracker = tracker;
                var repositoryGraph = tracker.RepositoryGraph;
                var commit          = repositoryGraph.GetCommit(commitId);
                if (commit == null)
                {
                    this.lblCommit.Content = "Cannot find commit: " + commit.Id;
                }
                else
                {
                    this.lblCommit.Content     = "Hash: " + commit.Id;
                    this.lblMessage.Content    = "Message: " + commit.Message;
                    this.lblAuthor.Content     = commit.CommitterName + " " + commit.CommitDateRelative;
                    this.fileTree.ItemsSource  = repositoryGraph.GetTree(commitId).Children;
                    this.patchList.ItemsSource = repositoryGraph.GetChanges(commitId);
                    //this.radioShowFileTree.IsChecked = true;
                    this.radioShowFileTree.IsEnabled = true;
                    this.toolWindow.ClearEditor();
                    this.commitId1            = commit.ParentIds.Count > 0 ? commit.ParentIds[0] : null;
                    this.commitId2            = commit.Id;
                    this.btnSwitch.Visibility = Visibility.Collapsed;
                    this.txtFileName.Text     = "";

                    this.radioShowChanges.IsChecked = true;
                    this.fileTree.Visibility        = Visibility.Collapsed;
                    this.patchList.Visibility       = Visibility.Visible;
                }
            }
            catch (Exception ex)
            {
                this.lblCommit.Content = ex.Message + " Please try again.";
            }
        }
예제 #33
0
        private void Window_Drop(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
            {
                this.Activate();

                var dropped = ((string[])e.Data.GetData(DataFormats.FileDrop, true))[0];

                if (!Directory.Exists(dropped))
                {
                    dropped = Path.GetDirectoryName(dropped);
                }
                var gitWorkingFolder = GitFileStatusTracker.GetRepositoryDirectory(dropped);
                if (Directory.Exists(dropped) && gitWorkingFolder != null &&
                    MessageBox.Show("Do you want to open Git repository from " + gitWorkingFolder,
                                    "Git repository found", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes)
                {
                    HistoryViewCommands.CloseCommitDetails.Execute(null, this);
                    HistoryViewCommands.CloseCommitDetails.Execute("PendingChanges", this);
                    this.gitViewModel.Open(dropped);
                    this.gitViewModel.Refresh(true);
                }
            }
        }
        public DiffUpdateBackgroundParser(ITextBuffer textBuffer, ITextBuffer documentBuffer, TaskScheduler taskScheduler, ITextDocumentFactoryService textDocumentFactoryService, IGitCommands commands)
            : base(textBuffer, taskScheduler, textDocumentFactoryService)
        {
            _documentBuffer = documentBuffer;
            _commands       = commands;
            ReparseDelay    = TimeSpan.FromMilliseconds(500);

            ITextDocument textDocument;

            if (TextDocumentFactoryService.TryGetTextDocument(TextBuffer, out textDocument))
            {
                GitFileStatusTracker tracker = new GitFileStatusTracker(Path.GetDirectoryName(textDocument.FilePath));
                if (tracker.IsGit)
                {
                    _watcher = new FileSystemWatcher(tracker.WorkingDirectory);
                    _watcher.IncludeSubdirectories = true;
                    _watcher.Changed            += HandleFileSystemChanged;
                    _watcher.Created            += HandleFileSystemChanged;
                    _watcher.Deleted            += HandleFileSystemChanged;
                    _watcher.Renamed            += HandleFileSystemChanged;
                    _watcher.EnableRaisingEvents = true;
                }
            }
        }
        public void GetChangedFilesTest()
        {
            GitFileStatusTracker.Init(tempFolder);

            File.WriteAllLines(tempFile, lines);

            GitFileStatusTracker tracker = new GitFileStatusTracker(tempFolder);

            Assert.AreEqual(GitFileStatus.New, tracker.ChangedFiles.ToList()[0].Status);

            tracker.StageFile(tempFile);
            Assert.AreEqual(GitFileStatus.Added, tracker.ChangedFiles.ToList()[0].Status);

            tracker.Commit("中文 1čtestč");

            Assert.AreEqual(0, tracker.ChangedFiles.Count());

            File.WriteAllText(tempFile, "a");
            tracker.Refresh();
            Assert.AreEqual(GitFileStatus.Modified, tracker.ChangedFiles.ToList()[0].Status);

            tracker.StageFile(tempFile);
            Assert.AreEqual(GitFileStatus.Staged, tracker.ChangedFiles.ToList()[0].Status);
        }
 /// <summary>
 /// Refreshes the pending changes.
 /// </summary>
 /// <param name="currentTracker">The tracker.</param>
 public void RefreshPendingChanges(GitFileStatusTracker currentTracker)
 {
     this.tracker = currentTracker;
     pendingChangesView.Refresh(currentTracker);
 }
        internal void Show(GitFileStatusTracker tracker)
        {
            canvasContainer.Children.Clear();

            this.tracker = tracker;
            if (tracker == null) return;

            loading.Visibility = Visibility.Visible;
            var dispatcher = Dispatcher.CurrentDispatcher;

            Action act = () =>
            {
                this.tracker.RepositoryGraph.IsSimplified = showSimplifiedGraph;

                var commits = tracker.RepositoryGraph.Nodes;
                if (commits.Count <= 0) return;

                maxX = commits.Count();
                maxY = commits.Max(c => c.X);

                for (int i = commits.Count() - 1; i >= 0; i--)
                {
                    var commit = commits[i];

                    #region Add commit box

                    var box = new CommitBox();
                    box.DataContext = new
                    {
                        Id = commit.Id,
                        ShortId = commit.Id.Substring(0, 5),
                        Comments = commit.Message,
                        Author = commit.CommitterName,
                        Date = commit.CommitDateRelative,
                    };

                    double left = GetScreenX(maxX - commit.Y);
                    double top = GetScreenY(commit.X);

                    Canvas.SetLeft(box, left);
                    Canvas.SetTop(box, top);
                    Canvas.SetZIndex(box, 10);

                    this.canvasContainer.Children.Add(box);

                    #endregion

                    #region Add Branches

                    var m = 0;
                    foreach (var name in commit.Refs.Where(r=> r.Type == RefTypes.Branch || r.Type == RefTypes.HEAD))
                    {
                        var control = new CommitHead
                        {
                            DataContext = new { Text = name },
                        };

                        Canvas.SetLeft(control, left + CommitBox.WIDTH + 4);
                        Canvas.SetTop(control, top + m++ * 30);

                        this.canvasContainer.Children.Add(control);
                    }
                    #endregion

                    #region Add Tags
                    m = 0;
                    foreach (var name in commit.Refs.Where(r => r.Type == RefTypes.Tag))
                    {
                        var control = new CommitTag
                        {
                            DataContext = new { Text = name },
                        };

                        Canvas.SetLeft(control, left + m++ * 100); // TODO: get width of the control
                        Canvas.SetTop(control, top - 24);

                        this.canvasContainer.Children.Add(control);
                    }

                    #endregion

                    #region Add Remote Branches
                    m = 0;
                    foreach (var name in commit.Refs.Where(r => r.Type == RefTypes.RemoteBranch))
                    {
                        var control = new CommitRemote
                        {
                            DataContext = new { Text = name },
                        };

                        Canvas.SetLeft(control, left + m++ * 100); // TODO: get width of the control
                        Canvas.SetTop(control, top + CommitBox.HEIGHT + 4);

                        this.canvasContainer.Children.Add(control);
                    }
                    #endregion
                }

                #region Add commit links

                var links = tracker.RepositoryGraph.Links;

                foreach (var link in links)
                {
                    // current node
                    double x1 = link.Y1;
                    double y1 = link.X1;

                    // parent node
                    double x2 = link.Y2;
                    double y2 = link.X2;

                    bool flip = links.Any(lnk => lnk.X1 == x2 && lnk.Y2 == y2 && lnk.X1 == lnk.X2);

                    x1 = GetScreenX(maxX - x1);
                    y1 = GetScreenY(y1) + CommitBox.HEIGHT / 2;
                    x2 = GetScreenX(maxX - x2) + CommitBox.WIDTH;
                    y2 = GetScreenY(y2) + CommitBox.HEIGHT / 2;

                    if (y1==y2)
                    {
                        var line = new Line
                        {
                            Stroke = new SolidColorBrush(Color.FromArgb(255, 153, 182, 209)),
                            StrokeThickness = 4,
                        };
                        line.X1 = x1;
                        line.Y1 = y1;
                        line.X2 = x2;
                        line.Y2 = y2;
                        this.canvasContainer.Children.Add(line);
                    }
                    else if (y1>y2 && !flip)
                    {
                        var x3 = x2 - CommitBox.WIDTH / 2;
                        var path = new Path
                        {
                            Stroke = new SolidColorBrush(Color.FromArgb(255, 153, 182, 209)),
                            StrokeThickness = 4,
                        };

                        PathSegmentCollection pscollection = new PathSegmentCollection();

                        pscollection.Add(new LineSegment(new Point(x2, y1), true));

                        BezierSegment curve = new BezierSegment(
                            new Point(x2, y1), new Point(x3, y1), new Point(x3, y2), true);
                        pscollection.Add(curve);

                        PathFigure pf = new PathFigure
                        {
                            StartPoint = new Point(x1, y1),
                            Segments = pscollection,
                        };
                        PathFigureCollection pfcollection = new PathFigureCollection();
                        pfcollection.Add(pf);
                        PathGeometry pathGeometry = new PathGeometry();
                        pathGeometry.Figures = pfcollection;
                        path.Data = pathGeometry;

                        this.canvasContainer.Children.Add(path);
                    }
                    else
                    {
                        var x3 = x1 + CommitBox.WIDTH / 2;
                        var path = new Path
                        {
                            Stroke = new SolidColorBrush(Color.FromArgb(255, 153, 182, 209)),
                            StrokeThickness = 4,
                        };

                        PathSegmentCollection pscollection = new PathSegmentCollection();

                        BezierSegment curve = new BezierSegment(
                            new Point(x3, y1), new Point(x3, y2), new Point(x1, y2), true);
                        pscollection.Add(curve);

                        pscollection.Add(new LineSegment(new Point(x2, y2), true));

                        PathFigure pf = new PathFigure
                        {
                            StartPoint = new Point(x3, y1),
                            Segments = pscollection,
                        };
                        PathFigureCollection pfcollection = new PathFigureCollection();
                        pfcollection.Add(pf);
                        PathGeometry pathGeometry = new PathGeometry();
                        pathGeometry.Figures = pfcollection;
                        path.Data = pathGeometry;

                        this.canvasContainer.Children.Add(path);
                    }
                }

                #endregion

                AdjustCanvasSize();

                this.scrollRoot.ScrollToRightEnd();

                loading.Visibility = Visibility.Collapsed;
            };
            dispatcher.BeginInvoke(act, DispatcherPriority.ApplicationIdle);
        }
예제 #38
0
        internal void Refresh(GitFileStatusTracker tracker)
        {
            this.label3.Content = "Changed files";

            this.tracker                = tracker;
            this.chkAmend.IsChecked     = false;
            this.chkSignOff.IsChecked   = false;
            this.chkNewBranch.IsChecked = false;

            if (tracker == null)
            {
                //service.NoRefresh = true;
                ClearUI();
                service.NoRefresh = false;
                return;
            }

            Action act = () =>
            {
                lblMessage.Content = "Commit to: " + tracker.CurrentBranch;
                service.NoRefresh  = true;
                ShowStatusMessage("Getting changed files ...");

                Stopwatch stopwatch = new Stopwatch();
                stopwatch.Start();

                var selectedFile  = GetSelectedFileName();
                var selectedFiles = this.dataGrid1.Items.Cast <GitFile>()
                                    .Where(i => i.IsSelected)
                                    .Select(i => i.FileName).ToList();

                this.dataGrid1.BeginInit();

                try
                {
                    this.dataGrid1.ItemsSource = tracker.ChangedFiles;

                    ICollectionView view = CollectionViewSource.GetDefaultView(this.dataGrid1.ItemsSource);
                    if (view != null)
                    {
                        view.SortDescriptions.Clear();
                        view.SortDescriptions.Add(new SortDescription(sortMemberPath, sortDirection));
                        view.Refresh();
                    }

                    this.dataGrid1.SelectedValue = selectedFile;
                    selectedFiles.ForEach(fn =>
                    {
                        var item = this.dataGrid1.Items.Cast <GitFile>()
                                   .Where(i => i.FileName == fn)
                                   .FirstOrDefault();
                        if (item != null)
                        {
                            item.IsSelected = true;
                        }
                    });

                    ShowStatusMessage("");

                    var changed = tracker.ChangedFiles;
                    this.label3.Content = string.Format("Changed files: ({0}) +{1} ~{2} -{3} !{4}", tracker.CurrentBranch,
                                                        changed.Where(f => f.Status == GitFileStatus.New || f.Status == GitFileStatus.Added).Count(),
                                                        changed.Where(f => f.Status == GitFileStatus.Modified || f.Status == GitFileStatus.Staged).Count(),
                                                        changed.Where(f => f.Status == GitFileStatus.Deleted || f.Status == GitFileStatus.Removed).Count(),
                                                        changed.Where(f => f.Status == GitFileStatus.Conflict).Count());
                }
                catch (Exception ex)
                {
                    ShowStatusMessage(ex.Message);
                }
                this.dataGrid1.EndInit();

                stopwatch.Stop();
                Debug.WriteLine("**** PendingChangesView Refresh: " + stopwatch.ElapsedMilliseconds);

                //if (!GitSccOptions.Current.DisableAutoRefresh && stopwatch.ElapsedMilliseconds > 1000)
                //    this.label4.Visibility = Visibility.Visible;
                //else
                //    this.label4.Visibility = Visibility.Collapsed;

                service.NoRefresh       = false;
                service.lastTimeRefresh = DateTime.Now; //important!!
            };

            this.Dispatcher.BeginInvoke(act, DispatcherPriority.ApplicationIdle);
        }
        internal void Show(GitFileStatusTracker tracker, bool scroll)
        {
            this.tracker = tracker;

            //loading.Visibility = Visibility.Visible;

            Action action = () =>
            {
                try
                {
                    IList<GraphNode> commits = null;
                    string hash = null;

                    if (tracker != null && tracker.HasGitRepository)
                    {
                        commits = tracker.RepositoryGraph.Nodes;
                        hash = GetHashCode(commits);
                    }

                    bool changed = lastHash == null ? hash != null : !lastHash.Equals(hash);

                    if (changed)
                    {
                        lastHash = hash;

                        canvasContainer.Children.Clear();
                        maxX = maxY = 0;

                        if (changed && commits != null && commits.Any())
                        {
                            maxX = commits.Count();
                            maxY = commits.Max(c => c.X);

                            for (int i = commits.Count() - 1; i >= 0; i--)
                            {
                                var commit = commits[i];

                                #region Add commit box

                                var box = new CommitBox();
                                box.DataContext = new
                                {
                                    Id = commit.Id,
                                    ShortId = commit.ShortId,
                                    Comments = commit.Message,
                                    Author = commit.AuthorName,
                                    Date = commit.AuthorDateRelative,
                                    Refs = commit.Refs
                                };

                                double left = GetScreenX(maxX - commit.Y);
                                double top = GetScreenY(commit.X);

                                Canvas.SetLeft(box, left);
                                Canvas.SetTop(box, top);
                                Canvas.SetZIndex(box, 10);

                                this.canvasContainer.Children.Add(box);

                                #endregion

                                #region Add Branches

                                var m = 0;
                                foreach (var head in commit.Refs.Where(r => r.Type == RefTypes.Branch || r.Type == RefTypes.HEAD))
                                {
                                    var control = new CommitHead
                                    {
                                        DataContext = head,
                                    };

                                    Canvas.SetLeft(control, left + CommitBox.WIDTH + 4);
                                    Canvas.SetTop(control, top + m++ * 30);

                                    this.canvasContainer.Children.Add(control);

                                }
                                #endregion

                                #region Add Tags
                                m = 0;
                                foreach (var tag in commit.Refs.Where(r => r.Type == RefTypes.Tag))
                                {
                                    var control = new CommitTag
                                    {
                                        DataContext = tag,
                                    };

                                    Canvas.SetLeft(control, left + m++ * 80); // TODO: get width of the control
                                    Canvas.SetTop(control, top - 24);

                                    this.canvasContainer.Children.Add(control);
                                }

                                #endregion

                                #region Add Remote Branches
                                m = 0;
                                foreach (var name in commit.Refs.Where(r => r.Type == RefTypes.RemoteBranch))
                                {
                                    var control = new CommitRemote
                                    {
                                        DataContext = new { Text = name },
                                    };

                                    Canvas.SetLeft(control, left + m++ * 100); // TODO: get width of the control
                                    Canvas.SetTop(control, top + CommitBox.HEIGHT + 4);

                                    this.canvasContainer.Children.Add(control);
                                }
                                #endregion
                            }

                            #region Add commit links

                            var links = tracker.RepositoryGraph.Links;

                            foreach (var link in links)
                            {
                                // current node
                                double x1 = link.Y1;
                                double y1 = link.X1;

                                // parent node
                                double x2 = link.Y2;
                                double y2 = link.X2;

                                bool flip = links.Any(lnk => lnk.X1 == x2 && lnk.Y2 == y2 && lnk.X1 == lnk.X2);

                                x1 = GetScreenX(maxX - x1);
                                y1 = GetScreenY(y1) + CommitBox.HEIGHT / 2;
                                x2 = GetScreenX(maxX - x2) + CommitBox.WIDTH;
                                y2 = GetScreenY(y2) + CommitBox.HEIGHT / 2;

                                if (y1 == y2)
                                {
                                    var line = new Line
                                    {
                                        Stroke = new SolidColorBrush(Color.FromArgb(255, 153, 182, 209)),
                                        StrokeThickness = 4,
                                    };
                                    line.X1 = x1;
                                    line.Y1 = y1;
                                    line.X2 = x2;
                                    line.Y2 = y2;
                                    this.canvasContainer.Children.Add(line);
                                }
                                else if (y1 > y2 && !flip)
                                {
                                    var x3 = x2 - CommitBox.WIDTH / 2;
                                    var path = new System.Windows.Shapes.Path
                                    {
                                        Stroke = new SolidColorBrush(Color.FromArgb(255, 153, 182, 209)),
                                        StrokeThickness = 4,
                                    };

                                    PathSegmentCollection pscollection = new PathSegmentCollection();

                                    pscollection.Add(new LineSegment(new Point(x2, y1), true));

                                    BezierSegment curve = new BezierSegment(
                                        new Point(x2, y1), new Point(x3, y1), new Point(x3, y2), true);
                                    pscollection.Add(curve);

                                    PathFigure pf = new PathFigure
                                    {
                                        StartPoint = new Point(x1, y1),
                                        Segments = pscollection,
                                    };
                                    PathFigureCollection pfcollection = new PathFigureCollection();
                                    pfcollection.Add(pf);
                                    PathGeometry pathGeometry = new PathGeometry();
                                    pathGeometry.Figures = pfcollection;
                                    path.Data = pathGeometry;

                                    this.canvasContainer.Children.Add(path);
                                }
                                else
                                {
                                    var x3 = x1 + CommitBox.WIDTH / 2;
                                    var path = new System.Windows.Shapes.Path
                                    {
                                        Stroke = new SolidColorBrush(Color.FromArgb(255, 153, 182, 209)),
                                        StrokeThickness = 4,
                                    };

                                    PathSegmentCollection pscollection = new PathSegmentCollection();

                                    BezierSegment curve = new BezierSegment(
                                        new Point(x3, y1), new Point(x3, y2), new Point(x1, y2), true);
                                    pscollection.Add(curve);

                                    pscollection.Add(new LineSegment(new Point(x2, y2), true));

                                    PathFigure pf = new PathFigure
                                    {
                                        StartPoint = new Point(x3, y1),
                                        Segments = pscollection,
                                    };
                                    PathFigureCollection pfcollection = new PathFigureCollection();
                                    pfcollection.Add(pf);
                                    PathGeometry pathGeometry = new PathGeometry();
                                    pathGeometry.Figures = pfcollection;
                                    path.Data = pathGeometry;

                                    this.canvasContainer.Children.Add(path);
                                }
                            }

                            #endregion
                        }

                        AdjustCanvasSize();
                    }

                    if (scroll)
                    {
                        //this.Scaler.ScaleX = this.Scaler.ScaleY = 1;
                        //AdjustCanvasSize();

                        this.zoomAndPanControl.ContentScale = 1;
                        this.canvasContainer.SetValue(Canvas.LeftProperty, 0.0);
                        this.canvasContainer.SetValue(Canvas.TopProperty, 0.0);
                        this.scrollRoot.ScrollToRightEnd();
                    }
                }
                catch (Exception ex)
                {
                    Log.WriteLine("History Graph Show: {0}", ex.ToString());
                }

                //loading.Visibility = Visibility.Collapsed;

                HistoryViewCommands.GraphLoaded.Execute(null, this);
            };

            this.Dispatcher.BeginInvoke(action, DispatcherPriority.Background);
        }
        internal void Show(GitFileStatusTracker tracker)
        {
            this.tracker = tracker;

            loading.Visibility = Visibility.Visible;

            var dispatcher = Dispatcher.CurrentDispatcher;
            Action act = () =>
            {
                Stopwatch stopwatch = new Stopwatch();
                stopwatch.Start();

                try
                {
                    IList<GraphNode> commits = null;
                    string hash = null;

                    if (tracker != null && tracker.HasGitRepository)
                    {
                        this.tracker.RepositoryGraph.IsSimplified = showSimplifiedGraph;
                        commits = tracker.RepositoryGraph.Nodes;
                        hash = GetHashCode(commits);
                    }

                    bool changed = lastHash == null ? hash != null : !lastHash.Equals(hash);

                    if (changed)
                    {
                        lastHash = hash;

                        canvasContainer.Children.Clear();
                        maxX = maxY = 0;

                        if (changed && commits != null && commits.Count > 0)
                        {
                            maxX = commits.Count();
                            maxY = commits.Max(c => c.X);

                            for (int i = commits.Count() - 1; i >= 0; i--)
                            {
                                var commit = commits[i];

                                #region Add commit box

                                var box = new CommitBox();
                                box.DataContext = new
                                {
                                    Id = commit.Id,
                                    ShortId = commit.Id.Substring(0, 7),
                                    Comments = commit.Message,
                                    Author = commit.CommitterName,
                                    Date = commit.CommitDateRelative,
                                };

                                double left = GetScreenX(maxX - commit.Y);
                                double top = GetScreenY(commit.X);

                                Canvas.SetLeft(box, left);
                                Canvas.SetTop(box, top);
                                Canvas.SetZIndex(box, 10);

                                this.canvasContainer.Children.Add(box);

                                #endregion

                                #region Add Branches

                                var m = 0;
                                foreach (var name in commit.Refs.Where(r => r.Type == RefTypes.Branch || r.Type == RefTypes.HEAD))
                                {
                                    var control = new CommitHead
                                    {
                                        DataContext = new { Text = name },
                                    };

                                    Canvas.SetLeft(control, left + CommitBox.WIDTH + 4);
                                    Canvas.SetTop(control, top + m++ * 30);

                                    this.canvasContainer.Children.Add(control);
                                }
                                #endregion

                                #region Add Tags
                                m = 0;
                                foreach (var name in commit.Refs.Where(r => r.Type == RefTypes.Tag))
                                {
                                    var control = new CommitTag
                                    {
                                        DataContext = new { Text = name },
                                    };

                                    Canvas.SetLeft(control, left + m++ * 100); // TODO: get width of the control
                                    Canvas.SetTop(control, top - 24);

                                    this.canvasContainer.Children.Add(control);
                                }

                                #endregion

                                #region Add Remote Branches
                                m = 0;
                                foreach (var name in commit.Refs.Where(r => r.Type == RefTypes.RemoteBranch))
                                {
                                    var control = new CommitRemote
                                    {
                                        DataContext = new { Text = name },
                                    };

                                    Canvas.SetLeft(control, left + m++ * 100); // TODO: get width of the control
                                    Canvas.SetTop(control, top + CommitBox.HEIGHT + 4);

                                    this.canvasContainer.Children.Add(control);
                                }
                                #endregion
                            }

                            #region Add commit links

                            var links = tracker.RepositoryGraph.Links;

                            foreach (var link in links)
                            {
                                // current node
                                double x1 = link.Y1;
                                double y1 = link.X1;

                                // parent node
                                double x2 = link.Y2;
                                double y2 = link.X2;

                                bool flip = links.Any(lnk => lnk.X1 == x2 && lnk.Y2 == y2 && lnk.X1 == lnk.X2);

                                x1 = GetScreenX(maxX - x1);
                                y1 = GetScreenY(y1) + CommitBox.HEIGHT / 2;
                                x2 = GetScreenX(maxX - x2) + CommitBox.WIDTH;
                                y2 = GetScreenY(y2) + CommitBox.HEIGHT / 2;

                                if (y1 == y2)
                                {
                                    var line = new Line
                                    {
                                        Stroke = new SolidColorBrush(Color.FromArgb(255, 153, 182, 209)),
                                        StrokeThickness = 4,
                                    };
                                    line.X1 = x1;
                                    line.Y1 = y1;
                                    line.X2 = x2;
                                    line.Y2 = y2;
                                    this.canvasContainer.Children.Add(line);
                                }
                                else if (y1 > y2 && !flip)
                                {
                                    var x3 = x2 - CommitBox.WIDTH / 2;
                                    var path = new System.Windows.Shapes.Path
                                    {
                                        Stroke = new SolidColorBrush(Color.FromArgb(255, 153, 182, 209)),
                                        StrokeThickness = 4,
                                    };

                                    PathSegmentCollection pscollection = new PathSegmentCollection();

                                    pscollection.Add(new LineSegment(new Point(x2, y1), true));

                                    BezierSegment curve = new BezierSegment(
                                        new Point(x2, y1), new Point(x3, y1), new Point(x3, y2), true);
                                    pscollection.Add(curve);

                                    PathFigure pf = new PathFigure
                                    {
                                        StartPoint = new Point(x1, y1),
                                        Segments = pscollection,
                                    };
                                    PathFigureCollection pfcollection = new PathFigureCollection();
                                    pfcollection.Add(pf);
                                    PathGeometry pathGeometry = new PathGeometry();
                                    pathGeometry.Figures = pfcollection;
                                    path.Data = pathGeometry;

                                    this.canvasContainer.Children.Add(path);
                                }
                                else
                                {
                                    var x3 = x1 + CommitBox.WIDTH / 2;
                                    var path = new System.Windows.Shapes.Path
                                    {
                                        Stroke = new SolidColorBrush(Color.FromArgb(255, 153, 182, 209)),
                                        StrokeThickness = 4,
                                    };

                                    PathSegmentCollection pscollection = new PathSegmentCollection();

                                    BezierSegment curve = new BezierSegment(
                                        new Point(x3, y1), new Point(x3, y2), new Point(x1, y2), true);
                                    pscollection.Add(curve);

                                    pscollection.Add(new LineSegment(new Point(x2, y2), true));

                                    PathFigure pf = new PathFigure
                                    {
                                        StartPoint = new Point(x3, y1),
                                        Segments = pscollection,
                                    };
                                    PathFigureCollection pfcollection = new PathFigureCollection();
                                    pfcollection.Add(pf);
                                    PathGeometry pathGeometry = new PathGeometry();
                                    pathGeometry.Figures = pfcollection;
                                    path.Data = pathGeometry;

                                    this.canvasContainer.Children.Add(path);
                                }
                            }

                            #endregion
                        }

                        AdjustCanvasSize(this.Scaler.ScaleX);
                    }

                }
                catch (Exception ex)
                {
                    Log.WriteLine("History Graph Show: {0}", ex.ToString());
                }

                loading.Visibility = Visibility.Collapsed;

                stopwatch.Stop();
                Debug.WriteLine("**** HistoryGraph Refresh: " + stopwatch.ElapsedMilliseconds);

                service.NoRefresh = false;
                service.lastTimeRefresh = DateTime.Now; //important!!

            };

            dispatcher.BeginInvoke(act, DispatcherPriority.ApplicationIdle);
        }