private static PushObjectResponse ProcessPushObjectQuery(SharedNetworkInfo sharedInfo, PushObjectQuery query) { PushObjectResponse response = new PushObjectResponse() { Recognized = new bool[query.IDs == null ? 0 : query.IDs.Length] }; if (query.IDs != null) { if (query.Type == ObjectType.Branch) { for (int i = 0; i < query.IDs.Length; i++) { if (sharedInfo.Workspace.GetBranch(new Guid(query.IDs[i])) != null) response.Recognized[i] = true; else response.Recognized[i] = false; } } else if (query.Type == ObjectType.Version) { for (int i = 0; i < query.IDs.Length; i++) { if (sharedInfo.Workspace.GetVersion(new Guid(query.IDs[i])) != null) response.Recognized[i] = true; else response.Recognized[i] = false; } } else throw new Exception("Unrecognized object type for push object query."); } return response; }
static bool GetVersionListInternal(SharedNetworkInfo info, Objects.Version version, Stack<Branch> branchesToSend, Stack<Objects.Version> versionsToSend) { try { if (info.RemoteCheckedVersions.Contains(version.ID)) return true; Printer.PrintDiagnostics("Sending remote vault local version information."); Objects.Version currentVersion = version; while (true) { Objects.Version testedVersion = currentVersion; List<Objects.Version> versionsToCheck = new List<Objects.Version>(); List<Objects.Version> partialHistory = info.Workspace.GetHistory(currentVersion, 64); foreach (var x in partialHistory) { if (!info.RemoteCheckedVersions.Contains(x.ID)) { info.RemoteCheckedVersions.Add(x.ID); currentVersion = x; versionsToCheck.Add(x); } } if (versionsToCheck.Count > 0) { PushObjectQuery query = new PushObjectQuery(); query.Type = ObjectType.Version; query.IDs = versionsToCheck.Select(x => x.ID.ToString()).ToArray(); ProtoBuf.Serializer.SerializeWithLengthPrefix<NetCommand>(info.Stream, new NetCommand() { Type = NetCommandType.PushObjectQuery }, ProtoBuf.PrefixStyle.Fixed32); Utilities.SendEncrypted<PushObjectQuery>(info, query); PushObjectResponse response = Utilities.ReceiveEncrypted<PushObjectResponse>(info); if (response.Recognized.Length != query.IDs.Length) throw new Exception("Invalid response!"); int recognized = 0; for (int i = 0; i < response.Recognized.Length; i++) { Printer.PrintDiagnostics(" - Version ID: {0}", query.IDs[i]); if (!response.Recognized[i]) { versionsToSend.Push(versionsToCheck[i]); Printer.PrintDiagnostics(" (not recognized on remote vault)"); } else { recognized++; Printer.PrintDiagnostics(" (version already on remote vault)"); } } for (int i = 0; i < response.Recognized.Length; i++) { if (!response.Recognized[i]) { if (!QueryBranch(info, branchesToSend, info.Workspace.GetBranch(versionsToCheck[i].Branch))) return false; var mergeInfo = info.Workspace.GetMergeInfo(versionsToCheck[i].ID); foreach (var x in mergeInfo) { var srcVersion = info.Workspace.GetVersion(x.SourceVersion); if (srcVersion != null) { if (!GetVersionListInternal(info, srcVersion, branchesToSend, versionsToSend)) { Printer.PrintDiagnostics("Sending merge data for: {0}", srcVersion.ID); } } } } } if (recognized != 0) // we found a common parent somewhere break; } else if (testedVersion == currentVersion) break; } return true; } catch (Exception e) { Printer.PrintError("Error: {0}", e); return false; } }
private static bool QueryBranch(SharedNetworkInfo info, Stack<Branch> branchesToSend, Branch branch) { try { if (info.RemoteCheckedBranches.Contains(branch.ID)) return true; Printer.PrintDiagnostics("Sending remote vault local branch information."); Branch currentBranch = branch; while (true) { int branchesPerBlock = 16; List<Objects.Branch> branchIDs = new List<Objects.Branch>(); while (branchesPerBlock > 0) { if (info.RemoteCheckedBranches.Contains(currentBranch.ID)) break; info.RemoteCheckedBranches.Add(currentBranch.ID); branchesPerBlock--; branchIDs.Add(currentBranch); if (currentBranch.Parent.HasValue) currentBranch = info.Workspace.GetBranch(currentBranch.Parent.Value); else { currentBranch = null; break; } } if (branchIDs.Count > 0) { PushObjectQuery query = new PushObjectQuery(); query.Type = ObjectType.Branch; query.IDs = branchIDs.Select(x => x.ID.ToString()).ToArray(); ProtoBuf.Serializer.SerializeWithLengthPrefix<NetCommand>(info.Stream, new NetCommand() { Type = NetCommandType.PushObjectQuery }, ProtoBuf.PrefixStyle.Fixed32); Utilities.SendEncrypted<PushObjectQuery>(info, query); PushObjectResponse response = Utilities.ReceiveEncrypted<PushObjectResponse>(info); if (response.Recognized.Length != query.IDs.Length) throw new Exception("Invalid response!"); int recognized = 0; for (int i = 0; i < response.Recognized.Length; i++) { Printer.PrintDiagnostics(" - Branch ID: {0}", query.IDs[i]); if (!response.Recognized[i]) { branchesToSend.Push(branchIDs[i]); Printer.PrintDiagnostics(" (not recognized on remote vault)"); } else { info.RemoteCheckedBranches.Add(branchIDs[i].ID); recognized++; Printer.PrintDiagnostics(" (branch already on remote vault)"); } } if (recognized != 0) // we found a common parent somewhere break; } else if (info.RemoteCheckedBranches.Count > 0) break; } return true; } catch (Exception e) { Printer.PrintError("Error: {0}", e); return false; } }