Beispiel #1
0
 private static bool AcceptHeads(ClientStateInfo clientInfo, Area ws, out string errorData)
 {
     SharedNetwork.ImportBranches(clientInfo.SharedInfo);
     Dictionary<Guid, Head> temporaryHeads = new Dictionary<Guid, Head>();
     Dictionary<Guid, Guid> pendingMerges = new Dictionary<Guid, Guid>();
     Dictionary<Guid, HashSet<Guid>> headAncestry = new Dictionary<Guid, HashSet<Guid>>();
     foreach (var x in clientInfo.SharedInfo.PushedVersions)
     {
         Branch branch = ws.GetBranch(x.Version.Branch);
         Head head;
         if (!temporaryHeads.TryGetValue(branch.ID, out head))
         {
             var heads = ws.GetBranchHeads(branch);
             if (heads.Count == 0)
                 head = new Head() { Branch = branch.ID, Version = x.Version.ID };
             else if (heads.Count == 1)
                 head = heads[0];
             else
             {
                 // ???
                 Printer.PrintError("OMG 1");
                 errorData = string.Format("Multiple ({0}) heads for branch {1}", heads.Count, branch.ID);
                 return false;
             }
             temporaryHeads[branch.ID] = head;
         }
         if (head.Version != x.Version.ID)
         {
             HashSet<Guid> headAncestors = null;
             if (!headAncestry.TryGetValue(head.Version, out headAncestors))
             {
                 headAncestors = SharedNetwork.GetAncestry(head.Version, clientInfo.SharedInfo);
                 headAncestry[head.Version] = headAncestors;
             }
             if (headAncestors.Contains(x.Version.ID))
             {
                 // all best
             }
             else if (SharedNetwork.IsAncestor(head.Version, x.Version.ID, clientInfo.SharedInfo))
             {
                 headAncestry.Remove(head.Version);
                 pendingMerges[branch.ID] = Guid.Empty;
                 head.Version = x.Version.ID;
             }
             else if (!SharedNetwork.IsAncestor(x.Version.ID, head.Version, clientInfo.SharedInfo))
             {
                 headAncestry.Remove(head.Version);
                 pendingMerges[branch.ID] = head.Version;
                 head.Version = x.Version.ID;
             }
         }
     }
     foreach (var x in pendingMerges)
     {
         if (x.Value == Guid.Empty)
         {
             Printer.PrintDiagnostics("Uncontested head update for branch \"{0}\".", ws.GetBranch(x.Key).Name);
             Printer.PrintDiagnostics(" - Head updated to {0}", temporaryHeads[x.Key].Version);
             continue;
         }
         Branch branch = ws.GetBranch(x.Key);
         VersionInfo result;
         string error;
         result = ws.MergeRemote(ws.GetLocalOrRemoteVersion(x.Value, clientInfo.SharedInfo), temporaryHeads[x.Key].Version, clientInfo.SharedInfo, out error);
         if (result == null)
         {
             // safe merge?
             Printer.PrintError("OMG 2");
             errorData = string.Format("Can't automatically merge data - multiple heads in branch \'{0}\'.\nAttempted merge result: {1}", branch.Name, error);
             return false;
         }
         else
         {
             clientInfo.MergeVersions.Add(result);
             Printer.PrintMessage("Resolved incoming merge for branch \"{0}\".", branch.Name);
             Printer.PrintDiagnostics(" - Merge local input {0}", x.Value);
             Printer.PrintDiagnostics(" - Merge remote input {0}", temporaryHeads[x.Key].Version);
             Printer.PrintDiagnostics(" - Head updated to {0}", result.Version.ID);
             temporaryHeads[x.Key].Version = result.Version.ID;
         }
     }
     // theoretically best
     clientInfo.UpdatedHeads = temporaryHeads;
     errorData = string.Empty;
     return true;
 }