From c7a2e163b3eb45f7fa75286573368ea1aabca2a0 Mon Sep 17 00:00:00 2001 From: Hylke Bons Date: Mon, 4 Apr 2016 10:27:20 +0100 Subject: [PATCH] git: Pass auth info to objects that need it instead of global --- SparkleShare/Common/BaseController.cs | 9 +-- Sparkles/BaseFetcher.cs | 4 +- Sparkles/BaseRepository.cs | 49 ++++++------ Sparkles/Git/GitCommand.cs | 45 ++++++++--- Sparkles/Git/GitFetcher.cs | 9 ++- Sparkles/Git/GitRepository.cs | 103 ++++++++++++++------------ 6 files changed, 123 insertions(+), 96 deletions(-) diff --git a/SparkleShare/Common/BaseController.cs b/SparkleShare/Common/BaseController.cs index 866e612a..b22062ac 100644 --- a/SparkleShare/Common/BaseController.cs +++ b/SparkleShare/Common/BaseController.cs @@ -22,7 +22,6 @@ using System.Linq; using System.Threading; using Sparkles; -using Sparkles.Git; namespace SparkleShare { @@ -213,7 +212,7 @@ namespace SparkleShare { public virtual void Initialize () { Logger.LogInfo ("Environment", "SparkleShare " + InstallationInfo.Version); - Logger.LogInfo ("Environment", "Git " + GitCommand.GitVersion); + Logger.LogInfo ("Environment", "Git " + Sparkles.Git.GitCommand.GitVersion); Logger.LogInfo ("Environment", InstallationInfo.Platform + " (" + Environment.OSVersion + ")"); Preset.PresetsPath = PresetsPath; @@ -391,13 +390,13 @@ namespace SparkleShare { void AddRepository (string folder_path) { BaseRepository repo = null; - string folder_name = Path.GetFileName (folder_path); - string backend = Config.GetBackendForFolder (folder_name); + string folder_name = Path.GetFileName (folder_path); + string backend = Config.GetBackendForFolder (folder_name); try { repo = (BaseRepository) Activator.CreateInstance ( Type.GetType ("Sparkles." + backend + "." + backend + "Repository, Sparkles." + backend), - new object [] { folder_path, Config }); + new object [] { folder_path, Config, SSHAuthenticationInfo.DefaultAuthenticationInfo }); } catch (Exception e) { Logger.LogInfo ("Controller", "Failed to load backend '" + backend + "' for '" + folder_name + "': ", e); diff --git a/Sparkles/BaseFetcher.cs b/Sparkles/BaseFetcher.cs index 5f90c42d..fbb02bea 100644 --- a/Sparkles/BaseFetcher.cs +++ b/Sparkles/BaseFetcher.cs @@ -156,9 +156,7 @@ namespace Sparkles { Logger.LogInfo ("Fetcher", "Finished"); IsActive = false; - - bool repo_is_encrypted = (RemoteUrl.AbsolutePath.Contains ("-crypto") || - RemoteUrl.Host.Equals ("sparkleshare.net")); + bool repo_is_encrypted = RemoteUrl.AbsolutePath.Contains ("-crypto"); Finished (repo_is_encrypted, IsFetchedRepoEmpty, Warnings); diff --git a/Sparkles/BaseRepository.cs b/Sparkles/BaseRepository.cs index 15b668db..e27d418e 100644 --- a/Sparkles/BaseRepository.cs +++ b/Sparkles/BaseRepository.cs @@ -82,12 +82,12 @@ namespace Sparkles { public readonly string LocalPath; public readonly string Name; public readonly Uri RemoteUrl; - public List ChangeSets { get; private set; } - public SyncStatus Status { get; private set; } + public List ChangeSets { get; set; } + public SyncStatus Status { get; set; } public ErrorStatus Error { get; protected set; } - public bool IsBuffering { get; private set; } - public double ProgressPercentage { get; private set; } - public double ProgressSpeed { get; private set; } + public bool IsBuffering { get; set; } + public double ProgressPercentage { get; set; } + public double ProgressSpeed { get; set; } public DateTime LastSync { get { @@ -132,21 +132,20 @@ namespace Sparkles { protected Configuration local_config; + string identifier; + BaseListener listener; + Watcher watcher; + TimeSpan poll_interval = PollInterval.Short; + DateTime last_poll = DateTime.Now; + DateTime progress_last_change = DateTime.Now; + Timers.Timer remote_timer = new Timers.Timer () { Interval = 5000 }; + DisconnectReason last_disconnect_reason = DisconnectReason.None; - private string identifier; - private BaseListener listener; - private Watcher watcher; - private TimeSpan poll_interval = PollInterval.Short; - private DateTime last_poll = DateTime.Now; - private DateTime progress_last_change = DateTime.Now; - private Timers.Timer remote_timer = new Timers.Timer () { Interval = 5000 }; - private DisconnectReason last_disconnect_reason = DisconnectReason.None; - - private bool is_syncing { + bool is_syncing { get { return (Status == SyncStatus.SyncUp || Status == SyncStatus.SyncDown || IsBuffering); } } - private static class PollInterval { + static class PollInterval { public static readonly TimeSpan Short = new TimeSpan (0, 0, 5, 0); public static readonly TimeSpan Long = new TimeSpan (0, 0, 15, 0); } @@ -182,7 +181,7 @@ namespace Sparkles { } - private void RemoteTimerElapsedDelegate (object sender, EventArgs args) + void RemoteTimerElapsedDelegate (object sender, EventArgs args) { if (this.is_syncing || IsBuffering || Status == SyncStatus.Paused) return; @@ -239,7 +238,7 @@ namespace Sparkles { } - private Object buffer_lock = new Object (); + Object buffer_lock = new Object (); public void OnFileActivity (FileSystemEventArgs args) { @@ -355,7 +354,7 @@ namespace Sparkles { } - private void SyncUpBase () + void SyncUpBase () { if (!UseCustomWatcher) this.watcher.Disable (); @@ -411,7 +410,7 @@ namespace Sparkles { } - private void SyncDownBase () + void SyncDownBase () { if (!UseCustomWatcher) this.watcher.Disable (); @@ -484,7 +483,7 @@ namespace Sparkles { } - private void CreateListener () + void CreateListener () { this.listener = ListenerFactory.CreateListener (Name, Identifier); @@ -500,7 +499,7 @@ namespace Sparkles { } - private void ListenerConnectedDelegate () + void ListenerConnectedDelegate () { if (this.last_disconnect_reason == DisconnectReason.SystemSleep) { this.last_disconnect_reason = DisconnectReason.None; @@ -513,7 +512,7 @@ namespace Sparkles { } - private void ListenerDisconnectedDelegate (DisconnectReason reason) + void ListenerDisconnectedDelegate (DisconnectReason reason) { Logger.LogInfo (Name, "Falling back to regular polling"); this.poll_interval = PollInterval.Short; @@ -538,7 +537,7 @@ namespace Sparkles { } - private void ListenerAnnouncementReceivedDelegate (Announcement announcement) + void ListenerAnnouncementReceivedDelegate (Announcement announcement) { string identifier = Identifier; @@ -560,7 +559,7 @@ namespace Sparkles { // Recursively gets a folder's size in bytes - private long CalculateSize (DirectoryInfo parent) + long CalculateSize (DirectoryInfo parent) { if (ExcludePaths.Contains (parent.Name)) return 0; diff --git a/Sparkles/Git/GitCommand.cs b/Sparkles/Git/GitCommand.cs index 3e39d117..90cdfe73 100644 --- a/Sparkles/Git/GitCommand.cs +++ b/Sparkles/Git/GitCommand.cs @@ -13,6 +13,7 @@ // // You should have received a copy of the GNU General Public License // along with this program. If not, see . +using System; namespace Sparkles.Git { @@ -20,10 +21,25 @@ namespace Sparkles.Git { public class GitCommand : Command { public static string SSHPath; - public static string GitPath; public static string ExecPath; + static string git_path; + + public static string GitPath { + get { + if (git_path == null) + git_path = LocateCommand ("git"); + + return git_path; + } + + set { + git_path = value; + } + } + + public static string GitVersion { get { if (GitPath == null) @@ -35,27 +51,32 @@ namespace Sparkles.Git { } - public GitCommand (string path, string args) : base (path, args) + public GitCommand (string working_dir, string args) : this (working_dir, args, null) { - if (GitPath == null) - GitPath = LocateCommand ("git"); + } - StartInfo.FileName = GitPath; - StartInfo.WorkingDirectory = path; + + public GitCommand (string working_dir, string args, SSHAuthenticationInfo auth_info) : base (GitPath, args) + { + StartInfo.WorkingDirectory = working_dir; if (string.IsNullOrEmpty (SSHPath)) SSHPath = "ssh"; - string GIT_SSH_COMMAND = SSHPath + " " + - "-i \"" + SSHAuthenticationInfo.DefaultAuthenticationInfo.PrivateKeyFilePath + "\" " + - "-o UserKnownHostsFile=\"" + SSHAuthenticationInfo.DefaultAuthenticationInfo.KnownHostsFilePath + "\" " + - "-o PasswordAuthentication=no " + - "-F /dev/null"; // Ignore the environment's SSH config file + string GIT_SSH_COMMAND = SSHPath; + + if (auth_info != null) { + GIT_SSH_COMMAND = SSHPath + " " + + "-i \"" + auth_info.PrivateKeyFilePath + "\" " + + "-o UserKnownHostsFile=\"" + auth_info.KnownHostsFilePath + "\" " + + "-o PasswordAuthentication=no " + + "-F /dev/null"; // Ignore the environment's SSH config file + } if (ExecPath == null) SetEnvironmentVariable ("GIT_EXEC_PATH", ExecPath); - SetEnvironmentVariable ("GIT_SSH_COMMAND", GIT_SSH_COMMAND); + SetEnvironmentVariable ("GIT_SSH_COMMAND", GIT_SSH_COMMAND); SetEnvironmentVariable ("GIT_TERMINAL_PROMPT", "0"); SetEnvironmentVariable ("LANG", "en_US"); } diff --git a/Sparkles/Git/GitFetcher.cs b/Sparkles/Git/GitFetcher.cs index 08c34d08..643ca91f 100644 --- a/Sparkles/Git/GitFetcher.cs +++ b/Sparkles/Git/GitFetcher.cs @@ -25,6 +25,7 @@ namespace Sparkles.Git { public class GitFetcher : SSHFetcher { + SSHAuthenticationInfo auth_info; GitCommand git; Regex progress_regex = new Regex (@"([0-9]+)%", RegexOptions.Compiled); @@ -43,8 +44,10 @@ namespace Sparkles.Git { } - public GitFetcher (SparkleFetcherInfo info) : base (info) + public GitFetcher (SparkleFetcherInfo fetcher_info, SSHAuthenticationInfo auth_info) : base (fetcher_info) { + this.auth_info = auth_info; + if (RemoteUrl.ToString ().StartsWith ("ssh+")) RemoteUrl = new Uri ("ssh" + RemoteUrl.ToString ().Substring (RemoteUrl.ToString ().IndexOf ("://"))); @@ -92,11 +95,11 @@ namespace Sparkles.Git { if (FetchPriorHistory) { this.git = new GitCommand (Configuration.DefaultConfig.TmpPath, - "clone --progress --no-checkout \"" + RemoteUrl + "\" \"" + TargetFolder + "\""); + "clone --progress --no-checkout \"" + RemoteUrl + "\" \"" + TargetFolder + "\"", auth_info); } else { this.git = new GitCommand (Configuration.DefaultConfig.TmpPath, - "clone --progress --no-checkout --depth=1 \"" + RemoteUrl + "\" \"" + TargetFolder + "\""); + "clone --progress --no-checkout --depth=1 \"" + RemoteUrl + "\" \"" + TargetFolder + "\"", auth_info); } this.git.StartInfo.RedirectStandardError = true; diff --git a/Sparkles/Git/GitRepository.cs b/Sparkles/Git/GitRepository.cs index 53a3c4a8..b82dc1fe 100644 --- a/Sparkles/Git/GitRepository.cs +++ b/Sparkles/Git/GitRepository.cs @@ -27,33 +27,34 @@ namespace Sparkles.Git { public class GitRepository : BaseRepository { - private bool user_is_set; - private bool is_encrypted; + SSHAuthenticationInfo auth_info; + bool user_is_set; + bool is_encrypted; - private string cached_branch; + string cached_branch; - private Regex progress_regex = new Regex (@"([0-9]+)%", RegexOptions.Compiled); - private Regex speed_regex = new Regex (@"([0-9\.]+) ([KM])iB/s", RegexOptions.Compiled); + Regex progress_regex = new Regex (@"([0-9]+)%", RegexOptions.Compiled); + Regex speed_regex = new Regex (@"([0-9\.]+) ([KM])iB/s", RegexOptions.Compiled); - private Regex log_regex = new Regex (@"commit ([a-f0-9]{40})*\n" + + Regex log_regex = new Regex (@"commit ([a-f0-9]{40})*\n" + "Author: (.+) <(.+)>\n" + "Date: ([0-9]{4})-([0-9]{2})-([0-9]{2}) " + "([0-9]{2}):([0-9]{2}):([0-9]{2}) (.[0-9]{4})\n" + "*", RegexOptions.Compiled); - private Regex merge_regex = new Regex (@"commit ([a-f0-9]{40})\n" + + Regex merge_regex = new Regex (@"commit ([a-f0-9]{40})\n" + "Merge: [a-f0-9]{7} [a-f0-9]{7}\n" + "Author: (.+) <(.+)>\n" + "Date: ([0-9]{4})-([0-9]{2})-([0-9]{2}) " + "([0-9]{2}):([0-9]{2}):([0-9]{2}) (.[0-9]{4})\n" + "*", RegexOptions.Compiled); - private string branch { + string branch { get { if (!string.IsNullOrEmpty (this.cached_branch)) return this.cached_branch; - GitCommand git = new GitCommand (LocalPath, "config core.ignorecase true"); + var git = new GitCommand (LocalPath, "config core.ignorecase true"); git.StartAndWaitForExit (); while (this.in_merge && HasLocalChanges) { @@ -76,7 +77,7 @@ namespace Sparkles.Git { } - private bool in_merge { + bool in_merge { get { string merge_file_path = Path.Combine (LocalPath, ".git", "MERGE_HEAD"); return File.Exists (merge_file_path); @@ -84,9 +85,11 @@ namespace Sparkles.Git { } - public GitRepository (string path, Configuration config) : base (path, config) + public GitRepository (string path, Configuration config, SSHAuthenticationInfo auth_info) : base (path, config) { - GitCommand git = new GitCommand (LocalPath, "config core.ignorecase false"); + this.auth_info = auth_info; + + var git = new GitCommand (LocalPath, "config core.ignorecase false"); git.StartAndWaitForExit (); git = new GitCommand (LocalPath, "config remote.origin.url \"" + RemoteUrl + "\""); @@ -139,7 +142,7 @@ namespace Sparkles.Git { } - private void UpdateSizes () + void UpdateSizes () { double size = CalculateSizes (new DirectoryInfo (LocalPath)); double history_size = CalculateSizes (new DirectoryInfo (Path.Combine (LocalPath, ".git"))); @@ -154,13 +157,13 @@ namespace Sparkles.Git { public override string CurrentRevision { get { - GitCommand git = new GitCommand (LocalPath, "rev-parse HEAD"); + var git = new GitCommand (LocalPath, "rev-parse HEAD"); string output = git.StartAndReadStandardOutput (); if (git.ExitCode == 0) return output; - else - return null; + + return null; } } @@ -170,7 +173,9 @@ namespace Sparkles.Git { Logger.LogInfo ("Git", Name + " | Checking for remote changes..."); string current_revision = CurrentRevision; - GitCommand git = new GitCommand (LocalPath, "ls-remote --heads --exit-code \"" + RemoteUrl + "\" " + this.branch); + var git = new GitCommand (LocalPath, + "ls-remote --heads --exit-code \"" + RemoteUrl + "\" " + this.branch, auth_info); + string output = git.StartAndReadStandardOutput (); if (git.ExitCode != 0) @@ -216,7 +221,7 @@ namespace Sparkles.Git { if (message != null) Commit (message); - GitCommand git = new GitCommand (LocalPath, "push --progress \"" + RemoteUrl + "\" " + this.branch); + var git = new GitCommand (LocalPath, "push --progress \"" + RemoteUrl + "\" " + this.branch, auth_info); git.StartInfo.RedirectStandardError = true; git.Start (); @@ -287,7 +292,7 @@ namespace Sparkles.Git { public override bool SyncDown () { - GitCommand git = new GitCommand (LocalPath, "fetch --progress \"" + RemoteUrl + "\" " + this.branch); + var git = new GitCommand (LocalPath, "fetch --progress \"" + RemoteUrl + "\" " + this.branch, auth_info); git.StartInfo.RedirectStandardError = true; git.Start (); @@ -367,7 +372,7 @@ namespace Sparkles.Git { get { PrepareDirectories (LocalPath); - GitCommand git = new GitCommand (LocalPath, "status --porcelain"); + var git = new GitCommand (LocalPath, "status --porcelain"); string output = git.StartAndReadStandardOutput (); return !string.IsNullOrEmpty (output); @@ -393,9 +398,9 @@ namespace Sparkles.Git { // Stages the made changes - private bool Add () + bool Add () { - GitCommand git = new GitCommand (LocalPath, "add --all"); + var git = new GitCommand (LocalPath, "add --all"); git.StartAndWaitForExit (); return (git.ExitCode == 0); @@ -403,7 +408,7 @@ namespace Sparkles.Git { // Commits the made changes - private void Commit (string message) + void Commit (string message) { GitCommand git; @@ -425,7 +430,7 @@ namespace Sparkles.Git { // Merges the fetched changes - private bool Merge () + bool Merge () { string message = FormatCommitMessage (); @@ -493,7 +498,7 @@ namespace Sparkles.Git { } - private void ResolveConflict () + void ResolveConflict () { // This is a list of conflict status codes that Git uses, their // meaning, and how SparkleShare should handle them. @@ -507,7 +512,7 @@ namespace Sparkles.Git { // UU unmerged, both modified -> Use server's, save ours as a timestamped copy // ?? unmerged, new files -> Stage the new files - GitCommand git_status = new GitCommand (LocalPath, "status --porcelain"); + var git_status = new GitCommand (LocalPath, "status --porcelain"); string output = git_status.StartAndReadStandardOutput (); string [] lines = output.Split ("\n".ToCharArray ()); @@ -534,7 +539,7 @@ namespace Sparkles.Git { Logger.LogInfo ("Git", Name + " | Ignoring conflict in special file: " + conflicting_path); // Recover local version - GitCommand git_ours = new GitCommand (LocalPath, "checkout --ours \"" + conflicting_path + "\""); + var git_ours = new GitCommand (LocalPath, "checkout --ours \"" + conflicting_path + "\""); git_ours.StartAndWaitForExit (); string abs_conflicting_path = Path.Combine (LocalPath, conflicting_path); @@ -552,7 +557,7 @@ namespace Sparkles.Git { line.StartsWith ("AU") || line.StartsWith ("UA")) { // Recover local version - GitCommand git_ours = new GitCommand (LocalPath, "checkout --ours \"" + conflicting_path + "\""); + var git_ours = new GitCommand (LocalPath, "checkout --ours \"" + conflicting_path + "\""); git_ours.StartAndWaitForExit (); // Append a timestamp to local version. @@ -569,7 +574,7 @@ namespace Sparkles.Git { File.Move (abs_conflicting_path, abs_our_path); // Recover server version - GitCommand git_theirs = new GitCommand (LocalPath, "checkout --theirs \"" + conflicting_path + "\""); + var git_theirs = new GitCommand (LocalPath, "checkout --theirs \"" + conflicting_path + "\""); git_theirs.StartAndWaitForExit (); trigger_conflict_event = true; @@ -580,7 +585,7 @@ namespace Sparkles.Git { // The modified local version is already in the checkout, so it just needs to be added. // We need to specifically mention the file, so we can't reuse the Add () method - GitCommand git_add = new GitCommand (LocalPath, "add \"" + conflicting_path + "\""); + var git_add = new GitCommand (LocalPath, "add \"" + conflicting_path + "\""); git_add.StartAndWaitForExit (); @@ -588,7 +593,7 @@ namespace Sparkles.Git { } else if (line.StartsWith ("UD")) { // Recover server version - GitCommand git_theirs = new GitCommand (LocalPath, "checkout --theirs \"" + conflicting_path + "\""); + var git_theirs = new GitCommand (LocalPath, "checkout --theirs \"" + conflicting_path + "\""); git_theirs.StartAndWaitForExit (); @@ -607,7 +612,7 @@ namespace Sparkles.Git { Add (); - GitCommand git = new GitCommand (LocalPath, "commit --message \"Conflict resolution by SparkleShare\""); + var git = new GitCommand (LocalPath, "commit --message \"Conflict resolution by SparkleShare\""); git.StartInfo.RedirectStandardOutput = false; git.StartAndWaitForExit (); @@ -630,7 +635,7 @@ namespace Sparkles.Git { // files from the index. This is a suboptimal workaround but it does the job if (this.is_encrypted) { // Restore the older file... - GitCommand git = new GitCommand (LocalPath, "checkout " + revision + " \"" + path + "\""); + var git = new GitCommand (LocalPath, "checkout " + revision + " \"" + path + "\""); git.StartAndWaitForExit (); string local_file_path = Path.Combine (LocalPath, path); @@ -652,7 +657,7 @@ namespace Sparkles.Git { } else { path = path.Replace ("\"", "\\\""); - GitCommand git = new GitCommand (LocalPath, "show " + revision + ":\"" + path + "\""); + var git = new GitCommand (LocalPath, "show " + revision + ":\"" + path + "\""); git.Start (); FileStream stream = File.OpenWrite (target_file_path); @@ -667,7 +672,7 @@ namespace Sparkles.Git { } - private bool FindError (string line) + bool FindError (string line) { Error = ErrorStatus.None; @@ -722,9 +727,9 @@ namespace Sparkles.Git { return GetChangeSetsInternal (path); } - private List GetChangeSetsInternal (string path) + List GetChangeSetsInternal (string path) { - List change_sets = new List (); + var change_sets = new List (); GitCommand git; if (path == null) { @@ -939,7 +944,7 @@ namespace Sparkles.Git { } - private string EnsureSpecialCharacters (string path) + string EnsureSpecialCharacters (string path) { // The path is quoted if it contains special characters if (path.StartsWith ("\"")) @@ -949,7 +954,7 @@ namespace Sparkles.Git { } - private string ResolveSpecialChars (string s) + string ResolveSpecialChars (string s) { StringBuilder builder = new StringBuilder (s.Length); List codes = new List (); @@ -982,7 +987,7 @@ namespace Sparkles.Git { // // It also prevents git repositories from becoming // git submodules by renaming the .git/HEAD file - private void PrepareDirectories (string path) + void PrepareDirectories (string path) { try { foreach (string child_path in Directory.GetDirectories (path)) { @@ -1028,11 +1033,11 @@ namespace Sparkles.Git { - private List ParseStatus () + List ParseStatus () { List changes = new List (); - GitCommand git_status = new GitCommand (LocalPath, "status --porcelain"); + var git_status = new GitCommand (LocalPath, "status --porcelain"); git_status.Start (); while (!git_status.StandardOutput.EndOfStream) { @@ -1078,7 +1083,7 @@ namespace Sparkles.Git { // Creates a pretty commit message based on what has changed - private string FormatCommitMessage () + string FormatCommitMessage () { string message = ""; @@ -1088,14 +1093,16 @@ namespace Sparkles.Git { message += "> ‘" + EnsureSpecialCharacters (change.MovedToPath) + "’\n"; } else { - if (change.Type == ChangeType.Edited) { + switch (change.Type) { + case ChangeType.Edited: message += "/"; - - } else if (change.Type == ChangeType.Deleted) { + break; + case ChangeType.Deleted: message += "-"; - - } else if (change.Type == ChangeType.Added) { + break; + case ChangeType.Added: message += "+"; + break; } message += " ‘" + change.Path + "’\n";