Progress on LFS support
This commit is contained in:
parent
6376a5518a
commit
1e37ba0992
|
@ -480,9 +480,8 @@ namespace SparkleShare {
|
||||||
|
|
||||||
void StartupInviteScan ()
|
void StartupInviteScan ()
|
||||||
{
|
{
|
||||||
foreach (string invite in Directory.GetFiles (FoldersPath, "*.xml")) {
|
foreach (string invite in Directory.GetFiles (FoldersPath, "*.xml"))
|
||||||
HandleInvite (invite);
|
HandleInvite (invite);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -548,7 +547,14 @@ namespace SparkleShare {
|
||||||
OnIdle ();
|
OnIdle ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public List<StorageTypeInfo> FetcherAvailableStorageTypes {
|
||||||
|
get {
|
||||||
|
return this.fetcher.AvailableStorageTypes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public void StartFetcher (SparkleFetcherInfo info)
|
public void StartFetcher (SparkleFetcherInfo info)
|
||||||
{
|
{
|
||||||
string tmp_path = Config.TmpPath;
|
string tmp_path = Config.TmpPath;
|
||||||
|
@ -573,7 +579,7 @@ namespace SparkleShare {
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Logger.LogInfo ("Controller",
|
Logger.LogInfo ("Controller",
|
||||||
"Failed to load '" + backend + "' backend for '" + canonical_name + "' " + e.Message);
|
"Failed to load '" + backend + "' backend for '" + canonical_name + "' " + e.Message);
|
||||||
|
|
||||||
FolderFetchError (Path.Combine (info.Address, info.RemotePath).Replace (@"\", "/"),
|
FolderFetchError (Path.Combine (info.Address, info.RemotePath).Replace (@"\", "/"),
|
||||||
new string [] {"Failed to load \"" + backend + "\" backend for \"" + canonical_name + "\""});
|
new string [] {"Failed to load \"" + backend + "\" backend for \"" + canonical_name + "\""});
|
||||||
|
@ -581,38 +587,43 @@ namespace SparkleShare {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.fetcher.Finished += delegate (bool repo_is_encrypted, bool repo_is_empty, string [] warnings) {
|
this.fetcher.Finished += FetcherFinishedDelegate;
|
||||||
|
this.fetcher.Failed += FetcherFailedDelegate;
|
||||||
|
this.fetcher.ProgressChanged += FetcherProgressChangedDelgate;
|
||||||
|
|
||||||
if (repo_is_empty) {
|
|
||||||
ShowSetupWindow (PageType.StorageSetup);
|
|
||||||
}
|
|
||||||
|
|
||||||
return; // TODO
|
|
||||||
|
|
||||||
if (repo_is_encrypted && repo_is_empty) {
|
|
||||||
ShowSetupWindowEvent (PageType.CryptoSetup);
|
|
||||||
|
|
||||||
} else if (repo_is_encrypted) {
|
|
||||||
ShowSetupWindowEvent (PageType.CryptoPassword);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
FinishFetcher ();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
this.fetcher.Failed += delegate {
|
|
||||||
FolderFetchError (this.fetcher.RemoteUrl.ToString (), this.fetcher.Errors);
|
|
||||||
StopFetcher ();
|
|
||||||
};
|
|
||||||
|
|
||||||
this.fetcher.ProgressChanged += delegate (double percentage, double speed) {
|
|
||||||
FolderFetching (percentage, speed);
|
|
||||||
};
|
|
||||||
|
|
||||||
this.fetcher.Start ();
|
this.fetcher.Start ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FetcherFinishedDelegate (StorageType storage_type, string [] warnings)
|
||||||
|
{
|
||||||
|
if (storage_type == StorageType.Unknown) {
|
||||||
|
ShowSetupWindow (PageType.StorageSetup);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (storage_type == StorageType.Encrypted) {
|
||||||
|
ShowSetupWindowEvent (PageType.CryptoPassword);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
FinishFetcher ();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FetcherFailedDelegate ()
|
||||||
|
{
|
||||||
|
FolderFetchError (this.fetcher.RemoteUrl.ToString (), this.fetcher.Errors);
|
||||||
|
StopFetcher ();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FetcherProgressChangedDelgate (double percentage, double speed)
|
||||||
|
{
|
||||||
|
FolderFetching (percentage, speed);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public void StopFetcher ()
|
public void StopFetcher ()
|
||||||
{
|
{
|
||||||
this.fetcher.Stop ();
|
this.fetcher.Stop ();
|
||||||
|
@ -629,65 +640,27 @@ namespace SparkleShare {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void FinishFetcher (StorageType storage_type)
|
|
||||||
{
|
|
||||||
if (storage_type == StorageType.Media) {
|
|
||||||
FinishFetcher (); // TODO: enable large files
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
FinishFetcher ();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void FinishFetcher (StorageType storage_type, string password)
|
|
||||||
{
|
|
||||||
if (storage_type != StorageType.Encrypted)
|
|
||||||
return;
|
|
||||||
|
|
||||||
this.fetcher.EnableFetchedRepoCrypto (password);
|
|
||||||
FinishFetcher ();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void FinishFetcher ()
|
public void FinishFetcher ()
|
||||||
|
{
|
||||||
|
FinishFetcher (StorageType.Plain);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void FinishFetcher (StorageType storage_type, string password)
|
||||||
|
{
|
||||||
|
this.fetcher.EnableFetchedRepoCrypto (password);
|
||||||
|
FinishFetcher (StorageType.Encrypted);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void FinishFetcher (StorageType storage_type)
|
||||||
{
|
{
|
||||||
this.watcher.EnableRaisingEvents = false;
|
this.watcher.EnableRaisingEvents = false;
|
||||||
|
this.fetcher.Complete (storage_type);
|
||||||
this.fetcher.Complete ();
|
|
||||||
string canonical_name = Path.GetFileName (this.fetcher.RemoteUrl.AbsolutePath);
|
|
||||||
|
|
||||||
if (canonical_name.EndsWith (".git"))
|
|
||||||
canonical_name = canonical_name.Replace (".git", "");
|
|
||||||
|
|
||||||
canonical_name = canonical_name.Replace ("-crypto", "");
|
|
||||||
canonical_name = canonical_name.ReplaceUnderscoreWithSpace ();
|
|
||||||
canonical_name = canonical_name.Replace ("%20", " ");
|
|
||||||
|
|
||||||
bool target_folder_exists = Directory.Exists (
|
|
||||||
Path.Combine (Config.FoldersPath, canonical_name));
|
|
||||||
|
|
||||||
// Add a numbered suffix to the name if a folder with the same name
|
|
||||||
// already exists. Example: "Folder (2)"
|
|
||||||
int suffix = 1;
|
|
||||||
while (target_folder_exists) {
|
|
||||||
suffix++;
|
|
||||||
target_folder_exists = Directory.Exists (
|
|
||||||
Path.Combine (Config.FoldersPath, canonical_name + " (" + suffix + ")"));
|
|
||||||
}
|
|
||||||
|
|
||||||
string target_folder_name = canonical_name;
|
|
||||||
|
|
||||||
if (suffix > 1)
|
string target_folder_path = DetermineFolderPath ();
|
||||||
target_folder_name += " (" + suffix + ")";
|
string target_folder_name = Path.GetFileName (target_folder_path);
|
||||||
|
|
||||||
string group_folder_path = Path.Combine (Config.FoldersPath, this.fetcher.RemoteUrl.Host);
|
|
||||||
|
|
||||||
if (!Directory.Exists (group_folder_path))
|
|
||||||
Directory.CreateDirectory (group_folder_path);
|
|
||||||
|
|
||||||
string target_folder_path = Path.Combine (group_folder_path, target_folder_name);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Directory.Move (this.fetcher.TargetFolder, target_folder_path);
|
Directory.Move (this.fetcher.TargetFolder, target_folder_path);
|
||||||
|
|
||||||
|
@ -711,24 +684,48 @@ namespace SparkleShare {
|
||||||
string backend = BaseFetcher.GetBackend (this.fetcher.RemoteUrl.ToString ());
|
string backend = BaseFetcher.GetBackend (this.fetcher.RemoteUrl.ToString ());
|
||||||
|
|
||||||
Config.AddFolder (target_folder_name, this.fetcher.Identifier,
|
Config.AddFolder (target_folder_name, this.fetcher.Identifier,
|
||||||
this.fetcher.RemoteUrl.ToString (), backend);
|
this.fetcher.RemoteUrl.ToString (), backend);
|
||||||
|
|
||||||
|
if (storage_type != StorageType.Plain) {
|
||||||
|
Config.SetFolderOptionalAttribute (target_folder_name,
|
||||||
|
"storage_type", storage_type.ToString ());
|
||||||
|
}
|
||||||
|
|
||||||
if (this.fetcher.OriginalFetcherInfo.AnnouncementsUrl != null) {
|
if (this.fetcher.OriginalFetcherInfo.AnnouncementsUrl != null) {
|
||||||
Config.SetFolderOptionalAttribute (target_folder_name, "announcements_url",
|
Config.SetFolderOptionalAttribute (target_folder_name, "announcements_url",
|
||||||
this.fetcher.OriginalFetcherInfo.AnnouncementsUrl);
|
this.fetcher.OriginalFetcherInfo.AnnouncementsUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
RepositoriesLoaded = true;
|
|
||||||
FolderFetched (this.fetcher.RemoteUrl.ToString (), this.fetcher.Warnings.ToArray ());
|
|
||||||
|
|
||||||
AddRepository (target_folder_path);
|
AddRepository (target_folder_path);
|
||||||
|
RepositoriesLoaded = true;
|
||||||
|
|
||||||
FolderListChanged ();
|
FolderListChanged ();
|
||||||
|
FolderFetched (this.fetcher.RemoteUrl.ToString (), this.fetcher.Warnings.ToArray ());
|
||||||
|
|
||||||
this.fetcher.Dispose ();
|
this.fetcher.Dispose ();
|
||||||
this.fetcher = null;
|
this.fetcher = null;
|
||||||
|
|
||||||
this.watcher.EnableRaisingEvents = true;
|
this.watcher.EnableRaisingEvents = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
string DetermineFolderPath ()
|
||||||
|
{
|
||||||
|
string folder_name = this.fetcher.FormatName ();
|
||||||
|
string folder_group_path = Path.Combine (Config.FoldersPath, this.fetcher.RemoteUrl.Host);
|
||||||
|
string folder_path = Path.Combine (Config.FoldersPath, folder_group_path, folder_name);
|
||||||
|
|
||||||
|
if (!Directory.Exists (folder_path)) {
|
||||||
|
if (!Directory.Exists (folder_group_path))
|
||||||
|
Directory.CreateDirectory (folder_group_path);
|
||||||
|
|
||||||
|
return folder_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add a number suffix when needed, e.g. "Folder (3)"
|
||||||
|
int suffix = 2 + Directory.GetDirectories (folder_group_path, folder_name + " (*").Length;
|
||||||
|
return string.Format ("{0} ({1})", folder_path, suffix);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public virtual void Quit ()
|
public virtual void Quit ()
|
||||||
|
|
|
@ -23,13 +23,16 @@ using System.Threading;
|
||||||
namespace Sparkles {
|
namespace Sparkles {
|
||||||
|
|
||||||
public class SparkleFetcherInfo {
|
public class SparkleFetcherInfo {
|
||||||
public string Address;
|
public string Address; // TODO: Uri object
|
||||||
public string RemotePath;
|
public string RemotePath;
|
||||||
public string Backend;
|
|
||||||
public string Fingerprint;
|
public string Fingerprint;
|
||||||
|
|
||||||
|
public string Backend;
|
||||||
public string TargetDirectory;
|
public string TargetDirectory;
|
||||||
public string AnnouncementsUrl;
|
|
||||||
public bool FetchPriorHistory;
|
public bool FetchPriorHistory;
|
||||||
|
|
||||||
|
public string AnnouncementsUrl; // TODO: Uri object
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -39,7 +42,7 @@ namespace Sparkles {
|
||||||
public event Action Failed = delegate { };
|
public event Action Failed = delegate { };
|
||||||
|
|
||||||
public event FinishedEventHandler Finished = delegate { };
|
public event FinishedEventHandler Finished = delegate { };
|
||||||
public delegate void FinishedEventHandler (bool repo_is_encrypted, bool repo_is_empty, string [] warnings);
|
public delegate void FinishedEventHandler (StorageType storage_type, string [] warnings);
|
||||||
|
|
||||||
public event ProgressChangedEventHandler ProgressChanged = delegate { };
|
public event ProgressChangedEventHandler ProgressChanged = delegate { };
|
||||||
public delegate void ProgressChangedEventHandler (double percentage, double speed);
|
public delegate void ProgressChangedEventHandler (double percentage, double speed);
|
||||||
|
@ -47,23 +50,30 @@ namespace Sparkles {
|
||||||
|
|
||||||
public abstract bool Fetch ();
|
public abstract bool Fetch ();
|
||||||
public abstract void Stop ();
|
public abstract void Stop ();
|
||||||
public abstract bool IsFetchedRepoEmpty { get; }
|
public bool IsActive { get; protected set; }
|
||||||
|
public double ProgressPercentage { get; private set; }
|
||||||
|
public double ProgressSpeed { get; private set; }
|
||||||
|
|
||||||
|
|
||||||
|
protected abstract bool IsFetchedRepoEmpty { get; }
|
||||||
|
protected StorageType FetchedRepoStorageType = StorageType.Unknown;
|
||||||
public abstract bool IsFetchedRepoPasswordCorrect (string password);
|
public abstract bool IsFetchedRepoPasswordCorrect (string password);
|
||||||
public abstract void EnableFetchedRepoCrypto (string password);
|
public abstract void EnableFetchedRepoCrypto (string password);
|
||||||
|
|
||||||
protected readonly List<StorageTypeInfo> AvailableStorageTypes = new List<StorageTypeInfo> ();
|
public readonly List<StorageTypeInfo> AvailableStorageTypes = new List<StorageTypeInfo> ();
|
||||||
|
|
||||||
public double ProgressPercentage { get; private set; }
|
|
||||||
public double ProgressSpeed { get; private set; }
|
|
||||||
|
|
||||||
public Uri RemoteUrl { get; protected set; }
|
public Uri RemoteUrl { get; protected set; }
|
||||||
public string RequiredFingerprint { get; protected set; }
|
public string RequiredFingerprint { get; protected set; }
|
||||||
public readonly bool FetchPriorHistory;
|
public readonly bool FetchPriorHistory;
|
||||||
public string TargetFolder { get; protected set; }
|
public string TargetFolder { get; protected set; }
|
||||||
public bool IsActive { get; protected set; }
|
|
||||||
public string Identifier;
|
public string Identifier;
|
||||||
public SparkleFetcherInfo OriginalFetcherInfo;
|
public SparkleFetcherInfo OriginalFetcherInfo;
|
||||||
|
|
||||||
|
|
||||||
|
protected List<string> warnings = new List<string> ();
|
||||||
|
protected List<string> errors = new List<string> ();
|
||||||
|
|
||||||
public string [] Warnings {
|
public string [] Warnings {
|
||||||
get {
|
get {
|
||||||
return warnings.ToArray ();
|
return warnings.ToArray ();
|
||||||
|
@ -77,18 +87,11 @@ namespace Sparkles {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected List<string> warnings = new List<string> ();
|
|
||||||
protected List<string> errors = new List<string> ();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Thread thread;
|
|
||||||
|
|
||||||
|
|
||||||
protected BaseFetcher (SparkleFetcherInfo info)
|
protected BaseFetcher (SparkleFetcherInfo info)
|
||||||
{
|
{
|
||||||
AvailableStorageTypes.Add (
|
AvailableStorageTypes.Add (
|
||||||
new StorageTypeInfo (StorageType.Plain, "Plain Storage", "Nothing fancy."));
|
new StorageTypeInfo (StorageType.Plain, "Plain Storage", "Nothing fancy"));
|
||||||
|
|
||||||
OriginalFetcherInfo = info;
|
OriginalFetcherInfo = info;
|
||||||
RequiredFingerprint = info.Fingerprint;
|
RequiredFingerprint = info.Fingerprint;
|
||||||
|
@ -112,6 +115,8 @@ namespace Sparkles {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Thread thread;
|
||||||
|
|
||||||
public void Start ()
|
public void Start ()
|
||||||
{
|
{
|
||||||
IsActive = true;
|
IsActive = true;
|
||||||
|
@ -136,9 +141,7 @@ namespace Sparkles {
|
||||||
Logger.LogInfo ("Fetcher", "Finished");
|
Logger.LogInfo ("Fetcher", "Finished");
|
||||||
|
|
||||||
IsActive = false;
|
IsActive = false;
|
||||||
bool repo_is_encrypted = RemoteUrl.AbsolutePath.Contains ("-crypto");
|
Finished (FetchedRepoStorageType, Warnings);
|
||||||
|
|
||||||
Finished (repo_is_encrypted, IsFetchedRepoEmpty, Warnings);
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
Thread.Sleep (500);
|
Thread.Sleep (500);
|
||||||
|
@ -159,7 +162,18 @@ namespace Sparkles {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public virtual void Complete ()
|
public void Complete ()
|
||||||
|
{
|
||||||
|
if (FetchedRepoStorageType == StorageType.Unknown) {
|
||||||
|
Complete (StorageType.Plain);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Complete (FetchedRepoStorageType);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public virtual void Complete (StorageType storage_type)
|
||||||
{
|
{
|
||||||
string identifier_path = Path.Combine (TargetFolder, ".sparkleshare");
|
string identifier_path = Path.Combine (TargetFolder, ".sparkleshare");
|
||||||
|
|
||||||
|
@ -203,7 +217,7 @@ namespace Sparkles {
|
||||||
n +
|
n +
|
||||||
"Have fun! :)" + n;
|
"Have fun! :)" + n;
|
||||||
|
|
||||||
if (RemoteUrl.AbsolutePath.Contains ("-crypto") || RemoteUrl.Host.Equals ("sparkleshare.net"))
|
if (FetchedRepoStorageType == StorageType.Encrypted)
|
||||||
text = text.Replace ("a SparkleShare repository", "an encrypted SparkleShare repository");
|
text = text.Replace ("a SparkleShare repository", "an encrypted SparkleShare repository");
|
||||||
|
|
||||||
File.WriteAllText (file_path, text);
|
File.WriteAllText (file_path, text);
|
||||||
|
@ -216,13 +230,6 @@ namespace Sparkles {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void Dispose ()
|
|
||||||
{
|
|
||||||
if (thread != null)
|
|
||||||
thread.Abort ();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
protected void OnProgressChanged (double percentage, double speed) {
|
protected void OnProgressChanged (double percentage, double speed) {
|
||||||
ProgressChanged (percentage, speed);
|
ProgressChanged (percentage, speed);
|
||||||
}
|
}
|
||||||
|
@ -241,6 +248,19 @@ namespace Sparkles {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public virtual string FormatName ()
|
||||||
|
{
|
||||||
|
return Path.GetFileName (RemoteUrl.AbsolutePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void Dispose ()
|
||||||
|
{
|
||||||
|
if (thread != null)
|
||||||
|
thread.Abort ();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
protected string [] ExcludeRules = {
|
protected string [] ExcludeRules = {
|
||||||
"*.autosave", // Various autosaving apps
|
"*.autosave", // Various autosaving apps
|
||||||
"*~", // gedit and emacs
|
"*~", // gedit and emacs
|
||||||
|
|
|
@ -191,6 +191,11 @@ namespace Sparkles {
|
||||||
this.identifier = Identifier;
|
this.identifier = Identifier;
|
||||||
ChangeSets = GetChangeSets ();
|
ChangeSets = GetChangeSets ();
|
||||||
|
|
||||||
|
string storage_type = this.local_config.GetFolderOptionalAttribute (Name, "storage_type");
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty (storage_type))
|
||||||
|
StorageType = (StorageType) Enum.Parse(typeof(StorageType), storage_type);
|
||||||
|
|
||||||
string is_paused = this.local_config.GetFolderOptionalAttribute (Name, "paused");
|
string is_paused = this.local_config.GetFolderOptionalAttribute (Name, "paused");
|
||||||
if (is_paused != null && is_paused.Equals (bool.TrueString))
|
if (is_paused != null && is_paused.Equals (bool.TrueString))
|
||||||
Status = SyncStatus.Paused;
|
Status = SyncStatus.Paused;
|
||||||
|
|
|
@ -27,7 +27,7 @@ namespace Sparkles {
|
||||||
bool write_output;
|
bool write_output;
|
||||||
|
|
||||||
|
|
||||||
public Command (string path, string args) : this (path, args, false)
|
public Command (string path, string args) : this (path, args, true)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -95,12 +95,12 @@ namespace Sparkles {
|
||||||
|
|
||||||
} else if (day_diff < 31) {
|
} else if (day_diff < 31) {
|
||||||
if (day_diff < 14)
|
if (day_diff < 14)
|
||||||
return "last week";
|
return "a week ago";
|
||||||
else
|
else
|
||||||
return string.Format ("{0} weeks ago", Math.Ceiling ((double) day_diff / 7));
|
return string.Format ("{0} weeks ago", Math.Ceiling ((double) day_diff / 7));
|
||||||
|
|
||||||
} else if (day_diff < 62) {
|
} else if (day_diff < 62) {
|
||||||
return "last month";
|
return "a month ago";
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
return string.Format ("{0} months ago", Math.Ceiling ((double) day_diff / 31));
|
return string.Format ("{0} months ago", Math.Ceiling ((double) day_diff / 31));
|
||||||
|
|
|
@ -45,7 +45,7 @@ namespace Sparkles.Git {
|
||||||
if (GitPath == null)
|
if (GitPath == null)
|
||||||
GitPath = LocateCommand ("git");
|
GitPath = LocateCommand ("git");
|
||||||
|
|
||||||
string git_version = new Command (GitPath, "--version").StartAndReadStandardOutput ();
|
string git_version = new Command (GitPath, "--version", false).StartAndReadStandardOutput ();
|
||||||
return git_version.Replace ("git version ", "");
|
return git_version.Replace ("git version ", "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,7 +56,7 @@ namespace Sparkles.Git {
|
||||||
if (GitPath == null)
|
if (GitPath == null)
|
||||||
GitPath = LocateCommand ("git");
|
GitPath = LocateCommand ("git");
|
||||||
|
|
||||||
string git_lfs_version = new Command (GitPath, "lfs version").StartAndReadStandardOutput ();
|
string git_lfs_version = new Command (GitPath, "lfs version", false).StartAndReadStandardOutput ();
|
||||||
return git_lfs_version.Replace ("git-lfs/", "").Split (' ') [0];
|
return git_lfs_version.Replace ("git-lfs/", "").Split (' ') [0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ namespace Sparkles.Git {
|
||||||
string password_salt = "662282447f6bbb8c8e15fb32dd09e3e708c32bc8";
|
string password_salt = "662282447f6bbb8c8e15fb32dd09e3e708c32bc8";
|
||||||
|
|
||||||
|
|
||||||
public override bool IsFetchedRepoEmpty {
|
protected override bool IsFetchedRepoEmpty {
|
||||||
get {
|
get {
|
||||||
var git_rev_parse = new GitCommand (TargetFolder, "rev-parse HEAD");
|
var git_rev_parse = new GitCommand (TargetFolder, "rev-parse HEAD");
|
||||||
git_rev_parse.StartAndWaitForExit ();
|
git_rev_parse.StartAndWaitForExit ();
|
||||||
|
@ -46,10 +46,6 @@ namespace Sparkles.Git {
|
||||||
|
|
||||||
public GitFetcher (SparkleFetcherInfo fetcher_info, SSHAuthenticationInfo auth_info) : base (fetcher_info)
|
public GitFetcher (SparkleFetcherInfo fetcher_info, SSHAuthenticationInfo auth_info) : base (fetcher_info)
|
||||||
{
|
{
|
||||||
AvailableStorageTypes.Add (
|
|
||||||
new StorageTypeInfo (StorageType.Encrypted, "Encrypted Storage",
|
|
||||||
"Trade off efficiency for privacy; encrypt files before storing them."));
|
|
||||||
|
|
||||||
this.auth_info = auth_info;
|
this.auth_info = auth_info;
|
||||||
var uri_builder = new UriBuilder (RemoteUrl);
|
var uri_builder = new UriBuilder (RemoteUrl);
|
||||||
|
|
||||||
|
@ -60,8 +56,8 @@ namespace Sparkles.Git {
|
||||||
RemoteUrl.Host.Equals ("gitlab.com")) {
|
RemoteUrl.Host.Equals ("gitlab.com")) {
|
||||||
|
|
||||||
AvailableStorageTypes.Add (
|
AvailableStorageTypes.Add (
|
||||||
new StorageTypeInfo (StorageType.Media, "Media Storage",
|
new StorageTypeInfo (StorageType.Media, "Large File Storage",
|
||||||
"Trade off versioning for space; don't keep a history locally."));
|
"Trade off versioning for space;\ndoesn't keep a local history"));
|
||||||
|
|
||||||
uri_builder.Scheme = "ssh";
|
uri_builder.Scheme = "ssh";
|
||||||
uri_builder.UserName = "git";
|
uri_builder.UserName = "git";
|
||||||
|
@ -74,6 +70,35 @@ namespace Sparkles.Git {
|
||||||
}
|
}
|
||||||
|
|
||||||
RemoteUrl = uri_builder.Uri;
|
RemoteUrl = uri_builder.Uri;
|
||||||
|
|
||||||
|
AvailableStorageTypes.Add (
|
||||||
|
new StorageTypeInfo (StorageType.Encrypted, "Encrypted Storage",
|
||||||
|
"Trade off efficiency for privacy;\nencrypts before storing files on the host"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
StorageType? DetermineStorageType ()
|
||||||
|
{
|
||||||
|
var git_ls_remote = new GitCommand (Configuration.DefaultConfiguration.TmpPath,
|
||||||
|
string.Format ("ls-remote --heads \"{0}\"", RemoteUrl), auth_info);
|
||||||
|
|
||||||
|
string output = git_ls_remote.StartAndReadStandardOutput ();
|
||||||
|
|
||||||
|
if (git_ls_remote.ExitCode != 0)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace (output))
|
||||||
|
return StorageType.Unknown;
|
||||||
|
|
||||||
|
foreach (string line in output.Split ("\n".ToCharArray ())) {
|
||||||
|
if (line.Contains ("x-sparkleshare-lfs"))
|
||||||
|
return StorageType.Media;
|
||||||
|
|
||||||
|
if (line.Contains ("x-sparkleshare-encrypted"))
|
||||||
|
return StorageType.Encrypted;
|
||||||
|
}
|
||||||
|
|
||||||
|
return StorageType.Plain;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -82,14 +107,24 @@ namespace Sparkles.Git {
|
||||||
if (!base.Fetch ())
|
if (!base.Fetch ())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (FetchPriorHistory) {
|
StorageType? storage_type = DetermineStorageType ();
|
||||||
git_clone = new GitCommand (Configuration.DefaultConfiguration.TmpPath,
|
|
||||||
"clone --progress --no-checkout \"" + RemoteUrl + "\" \"" + TargetFolder + "\"", auth_info);
|
|
||||||
|
|
||||||
} else {
|
if (storage_type == null)
|
||||||
git_clone = new GitCommand (Configuration.DefaultConfiguration.TmpPath,
|
return false;
|
||||||
"clone --progress --no-checkout --depth=1 \"" + RemoteUrl + "\" \"" + TargetFolder + "\"", auth_info);
|
|
||||||
}
|
FetchedRepoStorageType = (StorageType) storage_type;
|
||||||
|
|
||||||
|
string git_clone_command = "clone --progress --no-checkout";
|
||||||
|
|
||||||
|
if (FetchPriorHistory)
|
||||||
|
git_clone_command += " --depth=1";
|
||||||
|
|
||||||
|
if (storage_type == StorageType.Media)
|
||||||
|
git_clone_command = "lfs " + git_clone_command;
|
||||||
|
|
||||||
|
var git_clone = new GitCommand (Configuration.DefaultConfiguration.TmpPath,
|
||||||
|
string.Format ("{0} \"{1}\" \"{2}\"", git_clone_command, RemoteUrl, TargetFolder),
|
||||||
|
auth_info);
|
||||||
|
|
||||||
git_clone.StartInfo.RedirectStandardError = true;
|
git_clone.StartInfo.RedirectStandardError = true;
|
||||||
git_clone.Start ();
|
git_clone.Start ();
|
||||||
|
@ -192,7 +227,6 @@ namespace Sparkles.Git {
|
||||||
InstallExcludeRules ();
|
InstallExcludeRules ();
|
||||||
InstallAttributeRules ();
|
InstallAttributeRules ();
|
||||||
InstallGitLFS ();
|
InstallGitLFS ();
|
||||||
EnableGitLFS (); // TODO
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -222,14 +256,36 @@ namespace Sparkles.Git {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public override void Complete ()
|
public override void Complete (StorageType selected_storage_type)
|
||||||
{
|
{
|
||||||
if (!IsFetchedRepoEmpty) {
|
if (IsFetchedRepoEmpty) {
|
||||||
|
var git_commit = new GitCommand (TargetFolder,
|
||||||
|
"commit --allow-empty --mesage=\"Initial commit by SparkleShare\"");
|
||||||
|
|
||||||
|
git_commit.StartAndWaitForExit ();
|
||||||
|
|
||||||
|
// These branches will be pushed later by "git push --all"
|
||||||
|
if (selected_storage_type == StorageType.Media) {
|
||||||
|
var git_branch = new GitCommand (TargetFolder, "branch x-sparkleshare-lfs", auth_info);
|
||||||
|
git_branch.StartAndWaitForExit ();
|
||||||
|
|
||||||
|
InstallGitLFS ();
|
||||||
|
EnableGitLFS ();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selected_storage_type == StorageType.Encrypted) {
|
||||||
|
var git_branch = new GitCommand (TargetFolder, "branch x-sparkleshare-encrypted", auth_info);
|
||||||
|
git_branch.StartAndWaitForExit ();
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
string branch = "HEAD";
|
string branch = "HEAD";
|
||||||
string prefered_branch = "SparkleShare";
|
string prefered_branch = "SparkleShare";
|
||||||
|
|
||||||
// Prefer the "SparkleShare" branch if it exists
|
// Prefer the "SparkleShare" branch if it exists
|
||||||
var git_show_ref = new GitCommand (TargetFolder, "show-ref --verify --quiet refs/heads/" + prefered_branch);
|
var git_show_ref = new GitCommand (TargetFolder,
|
||||||
|
"show-ref --verify --quiet refs/heads/" + prefered_branch);
|
||||||
|
|
||||||
git_show_ref.StartAndWaitForExit ();
|
git_show_ref.StartAndWaitForExit ();
|
||||||
|
|
||||||
if (git_show_ref.ExitCode == 0)
|
if (git_show_ref.ExitCode == 0)
|
||||||
|
@ -239,7 +295,7 @@ namespace Sparkles.Git {
|
||||||
git_checkout.StartAndWaitForExit ();
|
git_checkout.StartAndWaitForExit ();
|
||||||
}
|
}
|
||||||
|
|
||||||
base.Complete ();
|
base.Complete (selected_storage_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -331,6 +387,18 @@ namespace Sparkles.Git {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public override string FormatName ()
|
||||||
|
{
|
||||||
|
string name = Path.GetFileName (RemoteUrl.AbsolutePath);
|
||||||
|
name = name.ReplaceUnderscoreWithSpace ();
|
||||||
|
|
||||||
|
if (name.EndsWith (".git"))
|
||||||
|
name = name.Replace (".git", "");
|
||||||
|
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void InstallExcludeRules ()
|
void InstallExcludeRules ()
|
||||||
{
|
{
|
||||||
string git_info_path = Path.Combine (TargetFolder, ".git", "info");
|
string git_info_path = Path.Combine (TargetFolder, ".git", "info");
|
||||||
|
@ -373,13 +441,15 @@ namespace Sparkles.Git {
|
||||||
void InstallGitLFS ()
|
void InstallGitLFS ()
|
||||||
{
|
{
|
||||||
var git_config_required = new GitCommand (TargetFolder, "config filter.lfs.required true");
|
var git_config_required = new GitCommand (TargetFolder, "config filter.lfs.required true");
|
||||||
var git_config_clean = new GitCommand (TargetFolder, "config filter.lfs.clean 'git-lfs clean %f'");
|
|
||||||
|
|
||||||
string GIT_SSH_COMMAND = GitCommand.FormatGitSSHCommand (auth_info);
|
string GIT_SSH_COMMAND = GitCommand.FormatGitSSHCommand (auth_info);
|
||||||
string smudge_command = "env GIT_SSH_COMMAND='" + GIT_SSH_COMMAND + "' git-lfs smudge %f";
|
string smudge_command = "env GIT_SSH_COMMAND='" + GIT_SSH_COMMAND + "' git-lfs smudge %f";
|
||||||
|
|
||||||
var git_config_smudge = new GitCommand (TargetFolder,
|
var git_config_smudge = new GitCommand (TargetFolder,
|
||||||
"config filter.lfs.smudge \"" + smudge_command + "\"");
|
"config filter.lfs.smudge \"" + smudge_command + "\"");
|
||||||
|
|
||||||
|
var git_config_clean = new GitCommand (TargetFolder,
|
||||||
|
"config filter.lfs.clean 'git-lfs clean %f'");
|
||||||
|
|
||||||
git_config_required.StartAndWaitForExit ();
|
git_config_required.StartAndWaitForExit ();
|
||||||
git_config_clean.StartAndWaitForExit ();
|
git_config_clean.StartAndWaitForExit ();
|
||||||
|
|
|
@ -57,6 +57,7 @@ namespace Sparkles.Git {
|
||||||
var git = new GitCommand (LocalPath, "config core.ignorecase true");
|
var git = new GitCommand (LocalPath, "config core.ignorecase true");
|
||||||
git.StartAndWaitForExit ();
|
git.StartAndWaitForExit ();
|
||||||
|
|
||||||
|
// TODO: ugly
|
||||||
while (this.in_merge && HasLocalChanges) {
|
while (this.in_merge && HasLocalChanges) {
|
||||||
try {
|
try {
|
||||||
ResolveConflict ();
|
ResolveConflict ();
|
||||||
|
@ -223,10 +224,12 @@ namespace Sparkles.Git {
|
||||||
|
|
||||||
string pre_push_hook_path = Path.Combine (LocalPath, ".git", "hooks", "pre-push");
|
string pre_push_hook_path = Path.Combine (LocalPath, ".git", "hooks", "pre-push");
|
||||||
|
|
||||||
// We start "git lfs push" manually, so remove the
|
string pre_push_hook_content =
|
||||||
// hook automatically created by the clean/smudge filters
|
"#!/bin/sh" + Environment.NewLine +
|
||||||
if (File.Exists (pre_push_hook_path))
|
"env GIT_SSH_COMMAND='" + GitCommand.FormatGitSSHCommand (auth_info) + "' " +
|
||||||
File.Delete (pre_push_hook_path);
|
"git-lfs pre-push \"$@\"";
|
||||||
|
|
||||||
|
File.WriteAllText (pre_push_hook_path, pre_push_hook_content);
|
||||||
|
|
||||||
if (StorageType == StorageType.Media) {
|
if (StorageType == StorageType.Media) {
|
||||||
// TODO: Progress reporting, error handling
|
// TODO: Progress reporting, error handling
|
||||||
|
@ -234,12 +237,13 @@ namespace Sparkles.Git {
|
||||||
git_lfs_push.StartAndWaitForExit ();
|
git_lfs_push.StartAndWaitForExit ();
|
||||||
}
|
}
|
||||||
|
|
||||||
var git_push = new GitCommand (LocalPath, "push --progress \"" + RemoteUrl + "\" " + this.branch, auth_info);
|
var git_push = new GitCommand (LocalPath, string.Format ("push --all --progress \"{0}\"", RemoteUrl), auth_info);
|
||||||
git_push.StartInfo.RedirectStandardError = true;
|
git_push.StartInfo.RedirectStandardError = true;
|
||||||
git_push.Start ();
|
git_push.Start ();
|
||||||
|
|
||||||
double percentage = 1.0;
|
double percentage = 1.0;
|
||||||
|
|
||||||
|
// TODO: parse LFS progress
|
||||||
while (!git_push.StandardError.EndOfStream) {
|
while (!git_push.StandardError.EndOfStream) {
|
||||||
string line = git_push.StandardError.ReadLine ();
|
string line = git_push.StandardError.ReadLine ();
|
||||||
Match match = this.progress_regex.Match (line);
|
Match match = this.progress_regex.Match (line);
|
||||||
|
@ -305,18 +309,14 @@ namespace Sparkles.Git {
|
||||||
|
|
||||||
public override bool SyncDown ()
|
public override bool SyncDown ()
|
||||||
{
|
{
|
||||||
if (StorageType == StorageType.Media) {
|
var git = new GitCommand (LocalPath, "fetch --progress \"" + RemoteUrl + "\" " + branch, auth_info);
|
||||||
var git_lfs_pull = new GitCommand (LocalPath, "lfs pull", auth_info);
|
|
||||||
git_lfs_pull.StartAndWaitForExit ();
|
|
||||||
}
|
|
||||||
|
|
||||||
var git = new GitCommand (LocalPath, "fetch --progress \"" + RemoteUrl + "\" " + this.branch, auth_info);
|
|
||||||
|
|
||||||
git.StartInfo.RedirectStandardError = true;
|
git.StartInfo.RedirectStandardError = true;
|
||||||
git.Start ();
|
git.Start ();
|
||||||
|
|
||||||
double percentage = 1.0;
|
double percentage = 1.0;
|
||||||
|
|
||||||
|
// TODO: parse LFS progress
|
||||||
while (!git.StandardError.EndOfStream) {
|
while (!git.StandardError.EndOfStream) {
|
||||||
string line = git.StandardError.ReadLine ();
|
string line = git.StandardError.ReadLine ();
|
||||||
Match match = this.progress_regex.Match (line);
|
Match match = this.progress_regex.Match (line);
|
||||||
|
@ -751,20 +751,20 @@ namespace Sparkles.Git {
|
||||||
GitCommand git;
|
GitCommand git;
|
||||||
|
|
||||||
if (path == null) {
|
if (path == null) {
|
||||||
git = new GitCommand (LocalPath, "log --since=1.month --raw --find-renames --date=iso " +
|
git = new GitCommand (LocalPath, "--no-pager log --since=1.month --raw --find-renames --date=iso " +
|
||||||
"--format=medium --no-color --no-merges");
|
"--format=medium --no-color --no-merges");
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
path = path.Replace ("\\", "/");
|
path = path.Replace ("\\", "/");
|
||||||
|
|
||||||
git = new GitCommand (LocalPath, "log --raw --find-renames --date=iso " +
|
git = new GitCommand (LocalPath, "--no-pager log --raw --find-renames --date=iso " +
|
||||||
"--format=medium --no-color --no-merges -- \"" + path + "\"");
|
"--format=medium --no-color --no-merges -- \"" + path + "\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
string output = git.StartAndReadStandardOutput ();
|
string output = git.StartAndReadStandardOutput ();
|
||||||
|
|
||||||
if (path == null && string.IsNullOrWhiteSpace (output)) {
|
if (path == null && string.IsNullOrWhiteSpace (output)) {
|
||||||
git = new GitCommand (LocalPath, "log -n 75 --raw --find-renames --date=iso " +
|
git = new GitCommand (LocalPath, "--no-pager log -n 75 --raw --find-renames --date=iso " +
|
||||||
"--format=medium --no-color --no-merges");
|
"--format=medium --no-color --no-merges");
|
||||||
|
|
||||||
output = git.StartAndReadStandardOutput ();
|
output = git.StartAndReadStandardOutput ();
|
||||||
|
|
Loading…
Reference in a new issue