diff --git a/SparkleShare/Common/SetupController.cs b/SparkleShare/Common/SetupController.cs index 75399def..ad6a2b6e 100644 --- a/SparkleShare/Common/SetupController.cs +++ b/SparkleShare/Common/SetupController.cs @@ -536,6 +536,7 @@ namespace SparkleShare { string folder_name = Path.GetFileName (PreviousPath); folder_name = folder_name.ReplaceUnderscoreWithSpace (); + // TODO: Open SparkleShare/$HOST SparkleShare.Controller.OpenSparkleShareFolder (folder_name); FinishPageCompleted (); } diff --git a/Sparkles/BaseFetcher.cs b/Sparkles/BaseFetcher.cs index 0ac5a69e..c2fd5317 100644 --- a/Sparkles/BaseFetcher.cs +++ b/Sparkles/BaseFetcher.cs @@ -56,7 +56,7 @@ namespace Sparkles { protected abstract bool IsFetchedRepoEmpty { get; } - protected StorageType FetchedRepoStorageType = StorageType.Unknown; + public StorageType FetchedRepoStorageType { get; protected set; } public abstract bool IsFetchedRepoPasswordCorrect (string password); public abstract void EnableFetchedRepoCrypto (string password); @@ -89,6 +89,8 @@ namespace Sparkles { protected BaseFetcher (SparkleFetcherInfo info) { + FetchedRepoStorageType = StorageType.Unknown; + AvailableStorageTypes.Add ( new StorageTypeInfo (StorageType.Plain, "Plain Storage", "Nothing fancy")); diff --git a/Sparkles/BaseRepository.cs b/Sparkles/BaseRepository.cs index 6988143a..e34b59a6 100644 --- a/Sparkles/BaseRepository.cs +++ b/Sparkles/BaseRepository.cs @@ -27,7 +27,7 @@ namespace Sparkles { public enum StorageType { Unknown, Plain, - Media, + LargeFiles, Encrypted } diff --git a/Sparkles/Git/GitCommand.cs b/Sparkles/Git/GitCommand.cs index b4e0c932..8f672a32 100644 --- a/Sparkles/Git/GitCommand.cs +++ b/Sparkles/Git/GitCommand.cs @@ -20,7 +20,7 @@ namespace Sparkles.Git { public class GitCommand : Command { - public static string SSHPath; + public static string SSHPath = "ssh"; public static string ExecPath; @@ -71,9 +71,6 @@ namespace Sparkles.Git { { StartInfo.WorkingDirectory = working_dir; - if (string.IsNullOrEmpty (SSHPath)) - SSHPath = "ssh"; - string GIT_SSH_COMMAND = SSHPath; if (auth_info != null) diff --git a/Sparkles/Git/GitFetcher.cs b/Sparkles/Git/GitFetcher.cs index a0932ccf..1d3e8165 100644 --- a/Sparkles/Git/GitFetcher.cs +++ b/Sparkles/Git/GitFetcher.cs @@ -57,7 +57,7 @@ namespace Sparkles.Git { RemoteUrl.Host.Equals ("gitlab.com")) { AvailableStorageTypes.Add ( - new StorageTypeInfo (StorageType.Media, "Large File Storage", + new StorageTypeInfo (StorageType.LargeFiles, "Large File Storage", "Trade off versioning for space;\ndoesn't keep a local history")); uri_builder.Scheme = "ssh"; @@ -96,7 +96,7 @@ namespace Sparkles.Git { string branch = line_parts [line_parts.Length - 1]; if (branch == "x-sparkleshare-lfs") - return StorageType.Media; + return StorageType.LargeFiles; string encrypted_storage_prefix = "x-sparkleshare-encrypted-"; @@ -127,7 +127,7 @@ namespace Sparkles.Git { if (!FetchPriorHistory) git_clone_command += " --depth=1"; - if (storage_type == StorageType.Media) + if (storage_type == StorageType.LargeFiles) git_clone_command = "lfs clone --progress --no-checkout"; var git_clone = new GitCommand (Configuration.DefaultConfiguration.TmpPath, @@ -231,11 +231,6 @@ namespace Sparkles.Git { OnProgressChanged (100, 0); - InstallConfiguration (); - InstallExcludeRules (); - InstallAttributeRules (); - InstallGitLFS (); - return true; } @@ -266,6 +261,12 @@ namespace Sparkles.Git { public override string Complete (StorageType selected_storage_type) { + InstallConfiguration (); + InstallGitLFS (); + + InstallAttributeRules (); + InstallExcludeRules (); + string identifier = base.Complete (selected_storage_type); string identifier_path = Path.Combine (TargetFolder, ".sparkleshare"); @@ -280,12 +281,9 @@ namespace Sparkles.Git { git_commit.StartAndWaitForExit (); // These branches will be pushed later by "git push --all" - if (selected_storage_type == StorageType.Media) { + if (selected_storage_type == StorageType.LargeFiles) { var git_branch = new GitCommand (TargetFolder, "branch x-sparkleshare-lfs", auth_info); git_branch.StartAndWaitForExit (); - - InstallGitLFS (); - EnableGitLFS (); } if (selected_storage_type == StorageType.Encrypted) { @@ -311,13 +309,7 @@ namespace Sparkles.Git { if (git_show_ref.ExitCode == 0) branch = prefered_branch; - GitCommand git_checkout; - - if (FetchedRepoStorageType == StorageType.Media) - git_checkout = new GitCommand (TargetFolder, "lfs checkout"); - else - git_checkout = new GitCommand (TargetFolder, "checkout --quiet --force " + branch); - + var git_checkout = new GitCommand (TargetFolder, string.Format ("checkout --quiet --force {0}", branch)); git_checkout.StartAndWaitForExit (); } @@ -369,11 +361,6 @@ namespace Sparkles.Git { git_config_smudge.StartAndWaitForExit (); git_config_clean.StartAndWaitForExit (); - // Pass all files through the encryption filter - // TODO: diff=encryption merge=encryption -text? - string git_attributes_file_path = Path.Combine (TargetFolder, ".git", "info", "attributes"); - File.WriteAllText (git_attributes_file_path, "* filter=encryption -diff merge=binary"); - // Store the password, TODO: 600 permissions string password_file_path = Path.Combine (TargetFolder, ".git", "info", "encryption_password"); File.WriteAllText (password_file_path, password.SHA256 (password_salt)); @@ -439,8 +426,19 @@ namespace Sparkles.Git { void InstallAttributeRules () { - string attribute_rules_file_path = Path.Combine (TargetFolder, ".git", "info", "attributes"); - TextWriter writer = new StreamWriter (attribute_rules_file_path); + string git_attributes_file_path = Path.Combine (TargetFolder, ".git", "info", "attributes"); + + if (FetchedRepoStorageType == StorageType.LargeFiles) { + File.WriteAllText (git_attributes_file_path, "* filter=lfs diff=lfs merge=lfs -text"); + return; + } + + if (FetchedRepoStorageType == StorageType.Encrypted) { + File.WriteAllText (git_attributes_file_path, "* filter=encryption -diff -delta merge=binary"); + return; + } + + TextWriter writer = new StreamWriter (git_attributes_file_path); // Treat all files as binary as we always want to keep both file versions on a conflict writer.WriteLine ("* merge=binary"); @@ -480,12 +478,5 @@ namespace Sparkles.Git { git_config_clean.StartAndWaitForExit (); git_config_smudge.StartAndWaitForExit (); } - - - void EnableGitLFS () - { - string git_attributes_file_path = Path.Combine (TargetFolder, ".gitattributes"); - File.WriteAllText (git_attributes_file_path, "* filter=lfs diff=lfs merge=lfs -text"); - } } } diff --git a/Sparkles/Git/GitRepository.cs b/Sparkles/Git/GitRepository.cs index eba0a8d8..272e7344 100644 --- a/Sparkles/Git/GitRepository.cs +++ b/Sparkles/Git/GitRepository.cs @@ -203,6 +203,7 @@ namespace Sparkles.Git { string pre_push_hook_path = Path.Combine (LocalPath, ".git", "hooks", "pre-push"); + // The pre-push hook may have been changed by Git LFS, overwrite it to use our own configuration string pre_push_hook_content = "#!/bin/sh" + Environment.NewLine + "env GIT_SSH_COMMAND='" + GitCommand.FormatGitSSHCommand (auth_info) + "' " + @@ -210,12 +211,6 @@ namespace Sparkles.Git { File.WriteAllText (pre_push_hook_path, pre_push_hook_content); - if (StorageType == StorageType.Media) { - // TODO: Progress reporting, error handling - var git_lfs_push = new GitCommand (LocalPath, "lfs push origin " + branch, auth_info); - git_lfs_push.StartAndWaitForExit (); - } - var git_push = new GitCommand (LocalPath, string.Format ("push --all --progress origin", RemoteUrl), auth_info); git_push.StartInfo.RedirectStandardError = true; git_push.Start (); @@ -224,9 +219,9 @@ namespace Sparkles.Git { // TODO: parse LFS progress while (!git_push.StandardError.EndOfStream) { - string line = git_push.StandardError.ReadLine (); - Match match = this.progress_regex.Match (line); - double speed = 0.0; + string line = git_push.StandardError.ReadLine (); + Match match = this.progress_regex.Match (line); + double speed = 0.0; double number = 0.0; if (match.Success) { @@ -276,6 +271,7 @@ namespace Sparkles.Git { } git_push.WaitForExit (); + UpdateSizes (); if (git_push.ExitCode == 0) @@ -288,6 +284,11 @@ namespace Sparkles.Git { public override bool SyncDown () { + string lfs_is_behind_file_path = Path.Combine (LocalPath, ".git", "lfs", "is_behind"); + + if (StorageType == StorageType.LargeFiles) + File.Create (lfs_is_behind_file_path); + var git = new GitCommand (LocalPath, "fetch --progress origin " + branch, auth_info); git.StartInfo.RedirectStandardError = true; @@ -350,18 +351,32 @@ namespace Sparkles.Git { } git.WaitForExit (); - UpdateSizes (); - if (git.ExitCode == 0) { - if (Merge ()) - return true; - else - return false; - - } else { + if (git.ExitCode != 0) { Error = ErrorStatus.HostUnreachable; return false; } + + if (Merge ()) { + if (StorageType == StorageType.LargeFiles) { + // Pull LFS files manually to benefit from concurrency + var git_lfs_pull = new GitCommand (LocalPath, "lfs pull origin", auth_info); + git_lfs_pull.StartAndWaitForExit (); + + if (git_lfs_pull.ExitCode != 0) { + Error = ErrorStatus.HostUnreachable; + return false; + } + + if (File.Exists (lfs_is_behind_file_path)) + File.Delete (lfs_is_behind_file_path); + } + + UpdateSizes (); + return true; + } + + return false; } @@ -379,6 +394,13 @@ namespace Sparkles.Git { public override bool HasUnsyncedChanges { get { + if (StorageType == StorageType.LargeFiles) { + string lfs_is_behind_file_path = Path.Combine (LocalPath, ".git", "lfs", "is_behind"); + + if (File.Exists (lfs_is_behind_file_path)) + return true; + } + string unsynced_file_path = Path.Combine (LocalPath, ".git", "has_unsynced_changes"); return File.Exists (unsynced_file_path); } @@ -994,7 +1016,7 @@ namespace Sparkles.Git { if (child_path.EndsWith (".git")) { if (child_path.Equals (Path.Combine (LocalPath, ".git"))) continue; - + string HEAD_file_path = Path.Combine (child_path, "HEAD"); if (File.Exists (HEAD_file_path)) {