From 646a80a3955c0b92ced618556755b349988fe7db Mon Sep 17 00:00:00 2001 From: leo Date: Thu, 23 Jul 2020 14:04:42 +0800 Subject: [PATCH] fix(Repository): separated git dir for submodules --- SourceGit/App.xaml.cs | 49 +++++--------- SourceGit/Git/Repository.cs | 92 +++++++++++++++++--------- SourceGit/UI/Dashboard.xaml.cs | 9 ++- SourceGit/UI/InteractiveRebase.xaml.cs | 18 +++-- SourceGit/UI/WorkingCopy.xaml.cs | 2 +- 5 files changed, 93 insertions(+), 77 deletions(-) diff --git a/SourceGit/App.xaml.cs b/SourceGit/App.xaml.cs index e0ebeac8..2ba3756d 100644 --- a/SourceGit/App.xaml.cs +++ b/SourceGit/App.xaml.cs @@ -28,22 +28,6 @@ namespace SourceGit { } } - /// - /// Interactive rebase sequence file. - /// - public static string InteractiveRebaseScript { - get; - private set; - } - - /// - /// TODO file for interactive rebase. - /// - public static string InteractiveRebaseTodo { - get; - private set; - } - /// /// Error handler. /// @@ -66,6 +50,22 @@ namespace SourceGit { /// /// private void OnAppStartup(object sender, StartupEventArgs e) { + // Use this app as a sequence editor? + var args = e.Args; + if (args.Length > 1) { + if (args[0] == "--interactive-rebase") { + if (args.Length < 3) { + Environment.Exit(1); + return; + } + + File.WriteAllText(args[2], File.ReadAllText(args[1])); + } + + Environment.Exit(0); + return; + } + // Try auto configure git via registry. if (!IsGitConfigured) { var root = RegistryKey.OpenBaseKey( @@ -81,23 +81,6 @@ namespace SourceGit { } } - // Files for interactive rebase. - InteractiveRebaseScript = Path.Combine( - Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), - "SourceGit", - "rebase.bat"); - InteractiveRebaseTodo = Path.Combine( - Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), - "SourceGit", - "REBASE_TODO"); - if (!File.Exists(InteractiveRebaseScript)) { - var folder = Path.GetDirectoryName(InteractiveRebaseScript); - if (!Directory.Exists(folder)) Directory.CreateDirectory(folder); - - File.WriteAllText(InteractiveRebaseScript, $"@echo off\ntype \"{InteractiveRebaseTodo}\" > .git\\rebase-merge\\git-rebase-todo"); - File.WriteAllText(InteractiveRebaseTodo, ""); - } - // Apply themes if (Preference.UIUseLightTheme) { foreach (var rs in Current.Resources.MergedDictionaries) { diff --git a/SourceGit/Git/Repository.cs b/SourceGit/Git/Repository.cs index 689a7edf..e549dd8e 100644 --- a/SourceGit/Git/Repository.cs +++ b/SourceGit/Git/Repository.cs @@ -59,11 +59,13 @@ namespace SourceGit.Git { #region PROPERTIES_RUNTIME [XmlIgnore] public Repository Parent = null; + [XmlIgnore] public string GitDir = null; private List cachedRemotes = new List(); private List cachedBranches = new List(); private List cachedTags = new List(); - private FileSystemWatcher watcher = null; + private FileSystemWatcher gitDirWatcher = null; + private FileSystemWatcher workingCopyWatcher = null; private DispatcherTimer timer = null; private bool isWatcherDisabled = false; private long nextUpdateTags = 0; @@ -276,16 +278,41 @@ namespace SourceGit.Git { LastOpenTime = DateTime.Now.ToFileTime(); isWatcherDisabled = false; - watcher = new FileSystemWatcher(); - watcher.Path = Path; - watcher.Filter = "*"; - watcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.DirectoryName | NotifyFilters.FileName; - watcher.IncludeSubdirectories = true; - watcher.Created += OnFSChanged; - watcher.Renamed += OnFSChanged; - watcher.Changed += OnFSChanged; - watcher.Deleted += OnFSChanged; - watcher.EnableRaisingEvents = true; + GitDir = ".git"; + RunCommand("rev-parse --git-dir", line => { + GitDir = line; + }); + if (!System.IO.Path.IsPathRooted(GitDir)) GitDir = System.IO.Path.Combine(Path, GitDir); + + var checkGitDir = new DirectoryInfo(GitDir); + if (!checkGitDir.Exists) { + App.RaiseError("GIT_DIR for this repository NOT FOUND!"); + return; + } else { + GitDir = checkGitDir.FullName; + } + + gitDirWatcher = new FileSystemWatcher(); + gitDirWatcher.Path = GitDir; + gitDirWatcher.Filter = "*"; + gitDirWatcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.DirectoryName | NotifyFilters.FileName; + gitDirWatcher.IncludeSubdirectories = true; + gitDirWatcher.Created += OnGitDirFSChanged; + gitDirWatcher.Renamed += OnGitDirFSChanged; + gitDirWatcher.Changed += OnGitDirFSChanged; + gitDirWatcher.Deleted += OnGitDirFSChanged; + gitDirWatcher.EnableRaisingEvents = true; + + workingCopyWatcher = new FileSystemWatcher(); + workingCopyWatcher.Path = Path; + workingCopyWatcher.Filter = "*"; + workingCopyWatcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.DirectoryName | NotifyFilters.FileName; + workingCopyWatcher.IncludeSubdirectories = true; + workingCopyWatcher.Created += OnWorkingCopyFSChanged; + workingCopyWatcher.Renamed += OnWorkingCopyFSChanged; + workingCopyWatcher.Changed += OnWorkingCopyFSChanged; + workingCopyWatcher.Deleted += OnWorkingCopyFSChanged; + workingCopyWatcher.EnableRaisingEvents = true; timer = new DispatcherTimer(); timer.Tick += Tick; @@ -315,11 +342,14 @@ namespace SourceGit.Git { cachedRemotes.Clear(); cachedTags.Clear(); - watcher.EnableRaisingEvents = false; - watcher.Dispose(); + gitDirWatcher.EnableRaisingEvents = false; + workingCopyWatcher.EnableRaisingEvents = false; + gitDirWatcher.Dispose(); + workingCopyWatcher.Dispose(); timer.Stop(); - watcher = null; + gitDirWatcher = null; + workingCopyWatcher = null; timer = null; featurePrefix = null; releasePrefix = null; @@ -367,27 +397,27 @@ namespace SourceGit.Git { } } - private void OnFSChanged(object sender, FileSystemEventArgs e) { + private void OnGitDirFSChanged(object sender, FileSystemEventArgs e) { if (string.IsNullOrEmpty(e.Name)) return; + if (e.Name.StartsWith("index")) return; - if (e.Name.StartsWith(".git", StringComparison.Ordinal)) { - if (e.Name.Equals(".git") || e.Name.StartsWith(".git\\index")) return; - - if (e.Name.Equals(".gitignore") || e.Name.Equals(".gitattributes")) { - nextUpdateLocalChanges = DateTime.Now.AddSeconds(1.5).ToFileTime(); - } else if (e.Name.StartsWith(".git\\refs\\tags", StringComparison.Ordinal)) { - nextUpdateTags = DateTime.Now.AddSeconds(.5).ToFileTime(); - } else if (e.Name.StartsWith(".git\\refs\\stash", StringComparison.Ordinal)) { - nextUpdateStashes = DateTime.Now.AddSeconds(.5).ToFileTime(); - } else if (e.Name.EndsWith("_HEAD", StringComparison.Ordinal) || - e.Name.StartsWith(".git\\refs\\heads", StringComparison.Ordinal) || - e.Name.StartsWith(".git\\refs\\remotes", StringComparison.Ordinal)) { - nextUpdateTree = DateTime.Now.AddSeconds(.5).ToFileTime(); - } - } else { - nextUpdateLocalChanges = DateTime.Now.AddSeconds(1.5).ToFileTime(); + if (e.Name.StartsWith("refs\\tags", StringComparison.Ordinal)) { + nextUpdateTags = DateTime.Now.AddSeconds(.5).ToFileTime(); + } else if (e.Name.StartsWith("refs\\stash", StringComparison.Ordinal)) { + nextUpdateStashes = DateTime.Now.AddSeconds(.5).ToFileTime(); + } else if (e.Name.EndsWith("_HEAD", StringComparison.Ordinal) || + e.Name.StartsWith("refs\\heads", StringComparison.Ordinal) || + e.Name.StartsWith("refs\\remotes", StringComparison.Ordinal)) { + nextUpdateTree = DateTime.Now.AddSeconds(.5).ToFileTime(); } } + + private void OnWorkingCopyFSChanged(object sender, FileSystemEventArgs e) { + if (string.IsNullOrEmpty(e.Name)) return; + if (e.Name == ".git" || e.Name.StartsWith(".git\\")) return; + + nextUpdateLocalChanges = DateTime.Now.AddSeconds(1.5).ToFileTime(); + } #endregion #region METHOD_GITCOMMANDS diff --git a/SourceGit/UI/Dashboard.xaml.cs b/SourceGit/UI/Dashboard.xaml.cs index 6c70dc87..965e75df 100644 --- a/SourceGit/UI/Dashboard.xaml.cs +++ b/SourceGit/UI/Dashboard.xaml.cs @@ -383,11 +383,10 @@ namespace SourceGit.UI { #region MERGE_ABORTS public void DetectMergeState() { - var gitDir = Path.Combine(repo.Path, ".git"); - var cherryPickMerge = Path.Combine(gitDir, "CHERRY_PICK_HEAD"); - var rebaseMerge = Path.Combine(gitDir, "REBASE_HEAD"); - var revertMerge = Path.Combine(gitDir, "REVERT_HEAD"); - var otherMerge = Path.Combine(gitDir, "MERGE_HEAD"); + var cherryPickMerge = Path.Combine(repo.GitDir, "CHERRY_PICK_HEAD"); + var rebaseMerge = Path.Combine(repo.GitDir, "REBASE_HEAD"); + var revertMerge = Path.Combine(repo.GitDir, "REVERT_HEAD"); + var otherMerge = Path.Combine(repo.GitDir, "MERGE_HEAD"); if (File.Exists(cherryPickMerge)) { abortCommand = "cherry-pick"; diff --git a/SourceGit/UI/InteractiveRebase.xaml.cs b/SourceGit/UI/InteractiveRebase.xaml.cs index 0187528c..60710604 100644 --- a/SourceGit/UI/InteractiveRebase.xaml.cs +++ b/SourceGit/UI/InteractiveRebase.xaml.cs @@ -1,6 +1,8 @@ +using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; +using System.Diagnostics; using System.IO; using System.Threading.Tasks; using System.Windows; @@ -255,7 +257,8 @@ namespace SourceGit.UI { } private void Start(object sender, RoutedEventArgs e) { - var stream = new FileStream(App.InteractiveRebaseTodo, FileMode.Create); + var temp = Path.GetTempFileName(); + var stream = new FileStream(temp, FileMode.Create); var writer = new StreamWriter(stream); for (int i = Items.Count - 1; i >= 0; i--) { @@ -263,19 +266,19 @@ namespace SourceGit.UI { switch ((InteractiveRebaseMode)item.Mode) { case InteractiveRebaseMode.Pick: - writer.WriteLine($"pick {item.Commit.ShortSHA} {item.Subject}"); + writer.WriteLine($"p {item.Commit.ShortSHA} {item.Subject}"); break; case InteractiveRebaseMode.Reword: - writer.WriteLine($"reword {item.Commit.ShortSHA} {item.Subject}"); + writer.WriteLine($"r {item.Commit.ShortSHA} {item.Subject}"); break; case InteractiveRebaseMode.Squash: - writer.WriteLine($"squash {item.Commit.ShortSHA} {item.Subject}"); + writer.WriteLine($"s {item.Commit.ShortSHA} {item.Subject}"); break; case InteractiveRebaseMode.Fixup: - writer.WriteLine($"fixup {item.Commit.ShortSHA} {item.Subject}"); + writer.WriteLine($"f {item.Commit.ShortSHA} {item.Subject}"); break; case InteractiveRebaseMode.Drop: - writer.WriteLine($"drop {item.Commit.ShortSHA} {item.Subject}"); + writer.WriteLine($"d {item.Commit.ShortSHA} {item.Subject}"); break; } } @@ -286,7 +289,8 @@ namespace SourceGit.UI { stream.Close(); repo.SetWatcherEnabled(false); - var errs = repo.RunCommand($"-c sequence.editor=\"\\\"{App.InteractiveRebaseScript}\\\"\" rebase -i {from}^", null); + var editor = Process.GetCurrentProcess().MainModule.FileName; + var errs = repo.RunCommand($"-c sequence.editor=\"\\\"{editor}\\\" --interactive-rebase \\\"{temp}\\\"\" rebase -i {from}^", null); repo.AssertCommand(errs); Close(); diff --git a/SourceGit/UI/WorkingCopy.xaml.cs b/SourceGit/UI/WorkingCopy.xaml.cs index 5c7b3a66..5e1e9fb4 100644 --- a/SourceGit/UI/WorkingCopy.xaml.cs +++ b/SourceGit/UI/WorkingCopy.xaml.cs @@ -96,7 +96,7 @@ namespace SourceGit.UI { /// public void LoadMergeMessage() { if (string.IsNullOrEmpty(txtCommitMsg.Text)) { - var mergeMsgFile = Path.Combine(Repo.Path, ".git", "MERGE_MSG"); + var mergeMsgFile = Path.Combine(Repo.GitDir, "MERGE_MSG"); if (!File.Exists(mergeMsgFile)) return; var content = File.ReadAllText(mergeMsgFile);