public bool Pull(bool pullRemoteObjects, string branchName, bool allBranches = false)
{
ReceivedData = false;
if (Workspace == null)
return false;
if (string.IsNullOrEmpty(RemoteDomain))
{
Printer.PrintError("#x#Error:##\n Remote vault is not yet initialized. Can't pull.");
return false;
}
try
{
List<string> branches = new List<string>();
BranchList branchList = null;
if (branchName == null && allBranches == false)
{
Printer.PrintMessage("Getting remote version information for branch \"{0}\"", Workspace.CurrentBranch.Name);
branches.Add(Workspace.CurrentBranch.ID.ToString());
}
else if (branchName == null && allBranches == true)
{
if (SharedInfo.CommunicationProtocol < SharedNetwork.Protocol.Versionr32)
{
Printer.PrintError("#e#Server does not support multi-branch queries.");
return false;
}
Printer.PrintMessage("Querying server for all branches...");
ProtoBuf.Serializer.SerializeWithLengthPrefix<NetCommand>(Connection.GetStream(), new NetCommand() { Type = NetCommandType.ListBranches }, ProtoBuf.PrefixStyle.Fixed32);
var queryResult = ProtoBuf.Serializer.DeserializeWithLengthPrefix<NetCommand>(Connection.GetStream(), ProtoBuf.PrefixStyle.Fixed32);
if (queryResult.Type == NetCommandType.Error)
{
Printer.PrintError("Couldn't get branch list - error: {0}", queryResult.AdditionalPayload);
return false;
}
BranchList list = Utilities.ReceiveEncrypted<BranchList>(SharedInfo);
foreach (var b in list.Branches)
{
if (b.Terminus.HasValue)
continue;
Printer.PrintMessage(" - {0} (#b#\"{1}\"##)", b.ShortID, b.Name);
branches.Add(b.ID.ToString());
}
branchList = list;
}
else
{
Printer.PrintMessage("Querying remote branch ID for \"{0}\"", branchName);
ProtoBuf.Serializer.SerializeWithLengthPrefix<NetCommand>(Connection.GetStream(), new NetCommand() { Type = NetCommandType.QueryBranchID, AdditionalPayload = branchName }, ProtoBuf.PrefixStyle.Fixed32);
var queryResult = ProtoBuf.Serializer.DeserializeWithLengthPrefix<NetCommand>(Connection.GetStream(), ProtoBuf.PrefixStyle.Fixed32);
if (queryResult.Type == NetCommandType.Error)
{
Printer.PrintError("Couldn't pull remote branch - error: {0}", queryResult.AdditionalPayload);
return false;
}
branches.Add(queryResult.AdditionalPayload);
Printer.PrintMessage(" - Matched query to remote branch ID {0}", queryResult.AdditionalPayload);
}
foreach (var branchID in branches)
{
if (branchList != null)
{
var remoteData = branchList.Branches.Where(x => x.ID.ToString() == branchID).FirstOrDefault();
if (remoteData != null)
{
Objects.Branch localData = Workspace.GetBranch(new Guid(branchID));
if (localData != null)
{
if (localData.Terminus.HasValue && remoteData.Terminus.HasValue && localData.Terminus.Value == remoteData.Terminus.Value)
continue;
bool skip = false;
if (branchList.Heads != null)
{
foreach (var x in branchList.Heads)
{
if (x.Key == localData.ID)
{
var localHeads = Workspace.GetBranchHeads(localData);
foreach (var y in localHeads)
{
if (y.Version == x.Value)
{
skip = true;
break;
}
}
break;
}
}
}
if (skip)
continue;
}
}
}
Printer.InteractivePrinter printer = Printer.CreateSpinnerPrinter(string.Empty, (object obj) =>
{
NetCommandType type = (NetCommandType)obj;
if (type == NetCommandType.PushObjectQuery)
return "Determining Missing Versions";
else if (type == NetCommandType.PushVersions)
return "Receiving Version Data";
else if (type == NetCommandType.PushBranch)
return "Receiving Branch Data";
else if (type == NetCommandType.SynchronizeRecords)
return "Processing";
return "Communicating";
});
if (allBranches)
{
string branchname = "";
if (branchList != null)
{
var remoteData = branchList.Branches.Where(x => x.ID.ToString() == branchID).FirstOrDefault();
if (remoteData != null)
branchname = "\"#b#" + remoteData.Name + "## ";
}
Printer.PrintMessage("Target branch: {1}#c#{0}##.", branchID, branchname);
}
ProtoBuf.Serializer.SerializeWithLengthPrefix<NetCommand>(Connection.GetStream(), new NetCommand() { Type = NetCommandType.PullVersions, AdditionalPayload = branchID }, ProtoBuf.PrefixStyle.Fixed32);
var command = ProtoBuf.Serializer.DeserializeWithLengthPrefix<NetCommand>(Connection.GetStream(), ProtoBuf.PrefixStyle.Fixed32);
if (command.Type == NetCommandType.Error)
throw new Exception("Remote error: " + command.AdditionalPayload);
while (true)
{
command = ProtoBuf.Serializer.DeserializeWithLengthPrefix<NetCommand>(Connection.GetStream(), ProtoBuf.PrefixStyle.Fixed32);
if (printer != null)
printer.Update(command.Type);
if (command.Type == NetCommandType.PushObjectQuery)
SharedNetwork.ProcesPushObjectQuery(SharedInfo);
else if (command.Type == NetCommandType.PushBranchJournal)
SharedNetwork.ReceiveBranchJournal(SharedInfo);
else if (command.Type == NetCommandType.PushBranch)
SharedNetwork.ReceiveBranches(SharedInfo);
else if (command.Type == NetCommandType.PushVersions)
SharedNetwork.ReceiveVersions(SharedInfo);
else if (command.Type == NetCommandType.SynchronizeRecords)
{
if (printer != null)
{
printer.End(command.Type);
printer = null;
}
Printer.PrintMessage("Received #b#{0}## versions from remote vault.", SharedInfo.PushedVersions.Count);
SharedNetwork.RequestRecordMetadata(SharedInfo);
if (pullRemoteObjects)
{
Printer.PrintDiagnostics("Requesting record data...");
SharedNetwork.RequestRecordData(SharedInfo);
}
bool gotData = false;
bool result = PullVersions(SharedInfo, out gotData);
ReceivedData = gotData;
ProtoBuf.Serializer.SerializeWithLengthPrefix<NetCommand>(Connection.GetStream(), new NetCommand() { Type = NetCommandType.Synchronized }, ProtoBuf.PrefixStyle.Fixed32);
if (result == false)
return result;
break;
}
}
}
return true;
}
catch (Exception e)
{
Printer.PrintError("Error: {0}", e);
Close();
return false;
}
}