Esempio n. 1
0
        public void changes()
        {
            while (true)
            {
                if (openDocument != null)
                {
                    List <Patch> patches;
                    Dictionary <int, List <Patch> > returnedPatches;
                    Object[] temp;

                    while (true)
                    {
                        try
                        {
                            if (hasLock == true)
                            {
                                Thread.Sleep(1000);
                                //Copies the document Textbox
                                // TextRange range = new TextRange(DocumentText.Document.ContentStart, DocumentText.Document.ContentEnd);
                                string myText2 = currentTextboxText;
                                patches = diffMatch.patch_make(diffMatch.diff_main(openDocument.FileContents, myText2));

                                temp = diffMatch.patch_apply(patches, openDocument.FileContents);

                                openDocument.FileContents = temp[0].ToString();

                                network.sendDocChanges(openDocument.FileName, patches, myInfo);
                                openDocument.SaveID = network.getLastPatchID(openDocument.FileName) + 1;
                            }
                            else
                            {
                                Thread.Sleep(1000);
                                returnedPatches = network.getDocChanges(openDocument.FileName, myInfo, openDocument.SaveID);

                                if (returnedPatches.Count > 0)
                                {
                                    foreach (List <Patch> item in returnedPatches.Values)
                                    {
                                        temp = diffMatch.patch_apply(item, openDocument.FileContents);

                                        openDocument.FileContents = temp[0].ToString();
                                        this.Dispatcher.Invoke(new Action(() => { DocumentText.Document.Blocks.Clear(); DocumentText.AppendText(openDocument.FileContents); }));
                                    }
                                    openDocument.SaveID = returnedPatches.Last().Key + 1;
                                }
                            }
                        }
                        catch (Exception)
                        {
                            //MessageBoxResult result = System.Windows.MessageBox.Show("Error: Connection to the server was lost. Would you like to reconnect?", "Error", MessageBoxButton.YesNo);
                            //if (result == MessageBoxResult.No)
                            //{
                            //    this.Close();
                            //    Environment.Exit(1);
                            //}
                        }
                    }
                }
            }
        }
Esempio n. 2
0
        private static string ApplyPatches(diff_match_patch googleDiff, string testInput, List <Patch> patches)
        {
            object[] results = googleDiff.patch_apply(patches, testInput, out List <Patch> effectivePatches);
            string   patched = (string)results[0];

            bool[] applied = (bool[])results[1];
            diff_match_patch.PatchResult[] resultCodes = (diff_match_patch.PatchResult[])results[2];
            for (int i = 0; i < applied.Length; i++)
            {
                if (!applied[i])
                {
                    throw new Exception($"failed to apply {effectivePatches[i]}: {resultCodes[i]}");
                }

                switch (resultCodes[i])
                {
                case diff_match_patch.PatchResult.UNKNOWN:
                    throw new Exception($"invalid result code from application of {effectivePatches[i]}");

                case diff_match_patch.PatchResult.APPLIED_PERFECT:
                    break;

                case diff_match_patch.PatchResult.APPLIED_IMPERFECT:
                    Debug.WriteLine("WARNING: patch imperfectly matched input, but was applied");
                    break;

                default:
                    throw new Exception(
                              $"patch should not have returned success with result code {resultCodes[i]}");
                }
            }

            return(patched);
        }
Esempio n. 3
0
        private bool[] GooglePatchApply(string source, List <Patch> patches, out string patched, out List <Patch> effectivePatches, out diff_match_patch.PatchResult[] resultCodes)
        {
            object[] results = _googleDiff.patch_apply(patches, source, out effectivePatches);
            if (results.Length != 3)
            {
                // something horrible has happened with out third party library call
                throw new Exception(
                          $"patch_apply in GoogleDiffMatchPatch returned incorrect number of results: {results.Length}; broken installation");
            }

            patched = (string)results[0];
            bool[] applied = (bool[])results[1];
            resultCodes = (diff_match_patch.PatchResult[])results[2];
            if (applied.Length != resultCodes.Length)
            {
                // something horrible has happened with out third party library call
                throw new Exception(
                          $"patch_apply in GoogleDiffMatchPatch returned unmatched result arrays; broken installation");
            }

            if (applied.Length != effectivePatches.Count)
            {
                // something horrible has happened with out third party library call
                throw new Exception(
                          $"patch_apply in GoogleDiffMatchPatch returned incorrect number of results {applied.Length} for {effectivePatches.Count} patches; broken installation");
            }

            return(applied);
        }
Esempio n. 4
0
        private void GeneratePatch(PatchResult f)
        {
            var newPath = MakeAbsolutePath(f.DestinationFile.Replace("\\destination\\", "\\patchedSource\\"));

            var d = Path.GetDirectoryName(newPath);

            if (!Directory.Exists(d))
            {
                Directory.CreateDirectory(d);
            }

            if (f.PatchResultType == PatchResultType.CopyFile)
            {
                File.Copy(MakeAbsolutePath(f.DestinationFile), newPath, true);
                return;
            }

            var content = File.ReadAllText(MakeAbsolutePath(f.SourceFile));

            var dmp = new diff_match_patch();
            var r   = dmp.patch_apply(f.PatchList, content);

            var newContent = r[0];

            File.WriteAllText(newPath, newContent.ToString());
        }
Esempio n. 5
0
 public void Edit(JObject editData)
 {
     var reader = new JsonSerializer();
     var jsonPatches = editData["Content"]["Patches"];
     var patches = jsonPatches.Select(p=> reader.Deserialize<Patch>(new JTokenReader(p))).ToList();
     var patcher = new diff_match_patch();
     _content = patcher.patch_apply(patches.ToList(), Content)[0] as string;
 }
Esempio n. 6
0
        public void ShouldApplyPatch()
        {
            var json =
                "[{\"diffs\":[[0,\"Welcome to Orchard!\"],[1,\"kk\"],[0,\"Welcome to Orchard!\"]],\"start1\":0,\"start2\":0,\"length1\":38,\"length2\":40}]";
            var patches = JsonConvert.DeserializeObject <List <PatchModel> >(json);


            var patchModelToPatchMapper = new PatchModelToPatchMapper();
            var patchesTranslated       = patches.Select(o => patchModelToPatchMapper.Map(o)).ToList();


            var sample = _diffMatchPatch.patch_make("Welcome to Orchard!", "Welcome to Orchard!l");

            Object[] results = _diffMatchPatch.patch_apply(sample, "Welcome to Orchard!");

            var patchesApplied = _diffMatchPatch.patch_apply(patchesTranslated, "Welcome to Orchard!");

            //Assert.That(patchesApplied);
        }
Esempio n. 7
0
        public static Result Merge(this diff_match_patch dmp, string originalText, string editedText_1, string editedText_2)
        {
            var res     = new Result();
            var patches = dmp.patch_make(originalText, editedText_1);

            res.rawResult   = dmp.patch_apply(patches, editedText_2);
            res.mergeResult = res.rawResult[0] as string;
            var patchResults = (res.rawResult[1] as IEnumerable <bool>);

            res.patches = patches.ToDictionary(patchResults);
            return(res);
        }
 public string GetPreviousVersion(int versionNumber)
 {
     var current = Current;
     var enumerator = PreviousVersions.GetEnumerator();
     for (int i = 0; i < versionNumber; i++)
     {
         enumerator.MoveNext();
         var patcher = new diff_match_patch();
         current = patcher.patch_apply(patcher.patch_fromText(enumerator.Current.Patch), current).Item1;
     }
     return current;
 }
Esempio n. 9
0
 //The patches are applied to the file contents and then written to file.
 public FailureType saveDocument()
 {
     for (int i = SaveID; i <= patches.Last().Key; i++)
     {
         //Applied the patches and gets the contents.
         Object[] temp = diffMatch.patch_apply(this.patches.ElementAt(i).Value, this.fileContents);
         fileContents = temp[0].ToString();
     }
     //Sets save id so the server and clients know when the last time the server saved was.
     this.SaveID = this.patches.Last().Key + 1;
     //Writes the Document to file.
     writeToFile();
     return(FailureType.Good);
 }
Esempio n. 10
0
        public void Diff()
        {
            var t1 = "ahoj jedna";
            var t2 = "ahoj jedna dva";
            var t3 = "ahoj tri dva";

            var           dmp             = new diff_match_patch();
            var           patchT2toT1     = dmp.patch_make(t2, t1);
            var           patchT2toT1text = dmp.patch_toText(patchT2toT1);//persist
            List <string> patches         = new List <string>();

            patches.Add(patchT2toT1text);
            var patchT3toT2     = dmp.patch_make(t3, t2);
            var patchT3toT2text = dmp.patch_toText(patchT3toT2);//persist

            patches.Add(patchT3toT2text);

            //restore
            var altT3ToT2Patch = dmp.patch_fromText(patchT3toT2text);
            var altT2          = dmp.patch_apply(altT3ToT2Patch, t3)[0].ToString();

            Assert.Equal(t2, altT2);

            var altT2ToT1Patch = dmp.patch_fromText(patchT2toT1text);
            var altT1          = dmp.patch_apply(altT2ToT1Patch, altT2)[0].ToString();

            Assert.Equal(t1, altT1);

            string restore = (string)t3.Clone();

            for (int i = patches.Count - 1; i >= 0; i--)
            {
                var restorePatch = dmp.patch_fromText(patches[i]);
                restore = dmp.patch_apply(restorePatch, restore)[0].ToString();
            }
            Assert.Equal(t1, restore);
        }
Esempio n. 11
0
        private void ProcessAureliaPatch(PatchResult f, int templateId, string sourcePath)
        {
            var dRoot = Path.Combine(ContentRootPath, $"Content\\{templateId}\\destination");

            var sRel = $"\\content\\{templateId}\\source\\";
            var dRel = $"\\content\\{templateId}\\destination\\";

            var fromPath = CLICFileUtils.GetTemplatePath(ContentRootPath, templateId.ToString(), TemplatePathType.Destination) + f.DestinationFile.Replace(dRel, "");

            var mappedSourceFile = tfm.MapSourceFile(f.SourceFile);
            var toPath           = Path.Combine(sourcePath, mappedSourceFile.Replace(sRel, ""));//need to map the sourcepath file (which can be of a different name) to the destination (patched) file: Eg/ MyProject1.sln > Site.sln

            var d = Path.GetDirectoryName(toPath);

            if (!Directory.Exists(d))
            {
                Directory.CreateDirectory(d);
            }

            if (f.PatchResultType == PatchResultType.CopyFile && (!File.Exists(toPath)))
            {
                File.Copy(fromPath, toPath, true);
                Console.WriteLine($"Copying: {toPath}");
                return;
            }

            if (f.PatchResultType == PatchResultType.Identical)
            {
                return;
            }

            if (f.PatchList == null)
            {
                return;
            }

            var content = File.ReadAllText(toPath);

            var dmp = new diff_match_patch();
            var r   = dmp.patch_apply(f.PatchList, content);

            //Apply any text transforms

            var newContent = r[0];

            File.WriteAllText(toPath, newContent.ToString());
            Console.WriteLine($"Patched: {toPath}");
        }
        public string GenerateEditedContent()
        {
            if(RevisionsConflict && RevisionChosenForResolution == null)
                throw  new ConflictException(_patchResult);

            if (RevisionChosenForResolution != null)
                return RevisionChosenForResolution.GenerateEditedContent();

            var dmp = new diff_match_patch { Match_Distance = 200, Match_Threshold = 0.2f };

            var patches = dmp.patch_make(PreviousRevisionAppliedTo.GenerateEditedContent(), RevisionsToMerge.ElementAt(0).GenerateEditedContent());

            var patchResult = dmp.patch_apply(patches, RevisionsToMerge.ElementAt(1).GenerateEditedContent());

            return patchResult[0] as string;
        }
Esempio n. 13
0
        public bool TryUpdateModel <TModel>(TModel model, string prefix, string[] includeProperties, string[] excludeProperties) where TModel : class
        {
            if (!prefix.Equals(_prefix))
            {
                return(false);
            }

            var currentValue = model.GetType().GetProperty(_elementWithoutPrefix).GetValue(model, null) as string;

            var diffMatchPatch = new diff_match_patch();
            var obj            = diffMatchPatch.patch_apply(_patches, currentValue);

            model.GetType().GetProperty(_elementWithoutPrefix).SetValue(model, obj[0], null);

            return(true);
        }
Esempio n. 14
0
        /// <summary>
        /// Merges the text editor content based on:
        /// - the content at the time of last sync between Google Docs (save or content download)
        /// - the current editor content
        /// - the content that's coming from Google Docs
        /// </summary>
        /// <param name="editorLastSync">Editor content at the time of last sync.</param>
        /// <param name="editorNow">Editor content now.</param>
        /// <param name="contentComingFromGoogleDocs">New content coming from Google Docs</param>
        /// <returns>Merged content.</returns>
        public static string MergeText(string editorLastSync, string editorNow, string contentComingFromGoogleDocs)
        {
            var dmp = new diff_match_patch
            {
                Match_Distance        = 1000,
                Match_Threshold       = 0.5f,
                Patch_DeleteThreshold = 0.5f
            };

            // let's create patches based on editorContent on last sync and the new text from Google Docs
            var patches = dmp.patch_make(editorLastSync, contentComingFromGoogleDocs);

            Debug.WriteLine("SyncContentUpdated > Patches: \t\t\t\t\t" + dmp.patch_toText(patches));

            // let's apply those patches to the current editor text
            var results = dmp.patch_apply(patches, editorNow);

            // and return results
            return(results[0].ToString());
        }
Esempio n. 15
0
        private static void TestBrokenImperfectMatch()
        {
            // this is a test that fails on the master version of this library
            // and is fixed in my fork (reported to master repo)
            string           referenceInput  = "diff matching patching";
            string           referenceOutput = "diff match patch";
            string           imperfectInput  = "diff matching pthing";
            diff_match_patch googleDiff      = new diff_match_patch();
            List <Diff>      diffs           = googleDiff.diff_main(referenceInput, referenceOutput);

            googleDiff.diff_cleanupSemantic(diffs);
            List <Patch> patches = googleDiff.patch_make(diffs);

            Debug.WriteLine(googleDiff.patch_toText(patches));
            string patched = (string)googleDiff.patch_apply(patches, imperfectInput, out List <Patch> effectivePatches)[0];

            Debug.WriteLine(effectivePatches.Count);
            Debug.WriteLine(patched);
            Debug.Assert(patched == "diff match pth");
        }
        private void CheckForConflicts()
        {
            var dmp = new diff_match_patch {Match_Distance = 200, Match_Threshold = 0.2f};

            var patches = dmp.patch_make(RevisionsToMerge[0].PreviousRevisionAppliedTo.GenerateEditedContent(), RevisionsToMerge[0].GenerateEditedContent());

            _patchResult = dmp.patch_apply(patches, RevisionsToMerge.ElementAt(1).GenerateEditedContent());
            var patchSucessIndicators = (bool[])_patchResult[1];

            if (patchSucessIndicators.Any(sucess => !sucess))
                RevisionsConflict = true;
        }
Esempio n. 17
0
        /// <summary>
        /// Updates the application.
        /// </summary>
        public void Update(Action <UpdateStatus, object> callback)
        {
            callback(UpdateStatus.Starting, null);
            diff_match_patch dmf    = new diff_match_patch();
            WebClient        client = new WebClient();

            callback(UpdateStatus.RetrievingFileList, null);
            string state = client.DownloadString(this.m_UpdateUri + "/initial");

            string[] lines = state.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries);
            callback(UpdateStatus.RetrievedFileList, lines.Length);
            int opers = 0;

            foreach (string line in lines)
            {
                Hash   hash = Hash.FromString(line.Split(new char[] { ' ' }, 2)[0]);
                string file = line.Split(new char[] { ' ' }, 2)[1];
                callback(UpdateStatus.DeterminingOperation, file);

                // See if file already exists.
                if (File.Exists(Path.Combine(this.m_LocalPath, file)) || hash == Hash.Empty)
                {
                    if (hash == Hash.Empty)
                    {
                        // Delete the local file if it exists.
                        if (File.Exists(Path.Combine(this.m_LocalPath, file)))
                        {
                            callback(UpdateStatus.DeletionStart, file);
                            File.Delete(Path.Combine(this.m_LocalPath, file));
                            callback(UpdateStatus.DeletionFinish, file);
                            opers++;
                        }
                    }
                    else
                    {
                        // Compare hashes, ignore if same.
                        Hash current = Hash.FromFile(Path.Combine(this.m_LocalPath, file));
                        if (current == hash)
                        {
                            continue;
                        }

                        // Download patch.
                        string patchstream;
                        try
                        {
                            patchstream = client.DownloadString(this.m_UpdateUri + "/patch/" + current + "/" + hash + "/" + file);
                            callback(UpdateStatus.PatchStart, file);
                            int a = 1;
                            using (StringReader reader = new StringReader(patchstream))
                            {
                                while (true)
                                {
                                    string header = reader.ReadLine();
                                    if (header == "--- END OF PATCHES ---")
                                    {
                                        break;
                                    }
                                    else if (header.StartsWith("--- NEXT PATCH ("))
                                    {
                                        int    count = Convert.ToInt32(header.Substring("--- NEXT PATCH (".Length, header.Length - "--- NEXT PATCH () ---".Length));
                                        char[] data  = new char[count];
                                        reader.ReadBlock(data, 0, count);
                                        List <Patch> patches = dmf.patch_fromText(new string(data));
                                        string       newText;
                                        using (StreamReader stream = new StreamReader(Path.Combine(this.m_LocalPath, file)))
                                        {
                                            newText = (string)dmf.patch_apply(patches, stream.ReadToEnd())[0];
                                        }
                                        using (StreamWriter stream = new StreamWriter(Path.Combine(this.m_LocalPath, file)))
                                        {
                                            stream.Write(newText);
                                        }
                                        callback(UpdateStatus.PatchApplied, a);
                                        a++;
                                        // Read the empty terminator line.
                                        reader.ReadLine();
                                    }
                                    else
                                    {
                                        throw new DataMisalignedException();
                                    }
                                }
                            }
                            callback(UpdateStatus.PatchFinish, file);
                            opers++;
                        }
                        catch (WebException)
                        {
                            // There's no patch list for this file, redownload.
                            string[]      coms = file.Split('/');
                            DirectoryInfo di   = new DirectoryInfo(this.m_LocalPath);
                            for (int i = 0; i < coms.Length - 1; i++)
                            {
                                DirectoryInfo[] dis = di.GetDirectories(coms[i]);
                                if (dis.Length == 0)
                                {
                                    di = di.CreateSubdirectory(coms[i]);
                                }
                                else
                                {
                                    di = dis[0];
                                }
                            }
                            callback(UpdateStatus.DownloadFreshStart, file);
                            client.DownloadFile(this.m_UpdateUri + "/file/" + file, Path.Combine(this.m_LocalPath, file));
                            callback(UpdateStatus.DownloadFreshFinish, file);
                            opers++;
                        }
                    }
                }
                else
                {
                    // File does not exist, download fresh.
                    string[]      coms = file.Split('/');
                    DirectoryInfo di   = new DirectoryInfo(this.m_LocalPath);
                    for (int i = 0; i < coms.Length - 1; i++)
                    {
                        DirectoryInfo[] dis = di.GetDirectories(coms[i]);
                        if (dis.Length == 0)
                        {
                            di = di.CreateSubdirectory(coms[i]);
                        }
                        else
                        {
                            di = dis[0];
                        }
                    }
                    callback(UpdateStatus.DownloadNewStart, file);
                    client.DownloadFile(this.m_UpdateUri + "/file/" + file, Path.Combine(this.m_LocalPath, file));
                    callback(UpdateStatus.DownloadNewFinish, file);
                    opers++;
                }
            }
            callback(UpdateStatus.Complete, opers);

            return;
        }
Esempio n. 18
0
File: Tools.cs Progetto: mikkoj/nocs
        /// <summary>
        /// Merges the text editor content based on:
        /// - the content at the time of last sync between Google Docs (save or content download)
        /// - the current editor content
        /// - the content that's coming from Google Docs
        /// </summary>
        /// <param name="editorLastSync">Editor content at the time of last sync.</param>
        /// <param name="editorNow">Editor content now.</param>
        /// <param name="contentComingFromGoogleDocs">New content coming from Google Docs</param>
        /// <returns>Merged content.</returns>
        public static string MergeText(string editorLastSync, string editorNow, string contentComingFromGoogleDocs)
        {
            var dmp = new diff_match_patch
            {
                Match_Distance = 1000,
                Match_Threshold = 0.5f,
                Patch_DeleteThreshold = 0.5f
            };

            // let's create patches based on editorContent on last sync and the new text from Google Docs
            var patches = dmp.patch_make(editorLastSync, contentComingFromGoogleDocs);
            Debug.WriteLine("SyncContentUpdated > Patches: \t\t\t\t\t" + dmp.patch_toText(patches));

            // let's apply those patches to the current editor text
            var results = dmp.patch_apply(patches, editorNow);

            // and return results
            return results[0].ToString();
        }
Esempio n. 19
0
        private void CreatePatchForUpdate(Document document, UpdateDto updateDto)
        {
            var currentRevision = document.GetCurrentRevision();
            var lastUpdate      = currentRevision.UpdateDto;
            //non existing revision - used as null object
            var secondLastUpdate = new UpdateDto {
                NewRevisionId = -1
            };

            if (document.CurrentRevisionId > FIRST_VALID_REVISON_ID)
            {
                secondLastUpdate = document.GetRevision(document.CurrentRevisionId - 1).UpdateDto;
            }

            bool creationSucessfull = false;

            //update is either based on current version
            //or on previous version where
            //   - the member which initialised the previous version was the owner itself
            //   - or a member with a lower member name (and thus the given update will be applied afterwards)
            //)
            if (IsFirstPreviousOfSecond(lastUpdate, updateDto) ||
                (IsFirstPreviousOfSecond(secondLastUpdate, updateDto) &&
                 MemberOfFirstUpdateIsOwnerOrLowerMember(lastUpdate, updateDto)
                )
                )
            {
                var result = _diffMatchPatch.patch_apply(updateDto.Patch, document.Content);
                if (result.Item2.All(x => x))
                {
                    document.Content   = result.Item1;
                    creationSucessfull = true;
                }
                else
                {
                    HandleErrorOnUpdate(updateDto);
                }
            }
            else
            {
                var revision = document.GetRevision(updateDto.PreviousRevisionId);
                if (revision.Id + SUPPORTED_NUM_OF_REACTIVE_UPDATES >= currentRevision.Id)
                {
                    var nextRevision = document.GetRevision(revision.Id + 1);
                    //move to next revision as long as
                    while (
                        nextRevision.UpdateDto.PreviousHash.SequenceEqual(updateDto.PreviousHash) &&
                        MemberOfFirstUpdateIsNotOwnerAndHigherMember(updateDto, nextRevision.UpdateDto) &&
                        nextRevision.Id < currentRevision.Id)
                    {
                        revision     = nextRevision;
                        nextRevision = document.GetRevision(nextRevision.Id + 1);
                    }

                    var content     = revision.Content;
                    var tmpRevision = revision;
                    var patch       = updateDto.Patch;

                    //apply all patches on top of the found revision
                    while (tmpRevision.Id <= currentRevision.Id)
                    {
                        var result = _diffMatchPatch.patch_apply(patch, content);
                        if (result.Item2.All(x => x))
                        {
                            content = result.Item1;
                            if (tmpRevision.Id == currentRevision.Id)
                            {
                                break;
                            }
                            tmpRevision = document.GetRevision(tmpRevision.Id + 1);
                            patch       = tmpRevision.UpdateDto.Patch;
                        }
                        else
                        {
                            HandleErrorOnUpdate(updateDto);
                        }
                    }
                    document.Content   = content;
                    updateDto.Patch    = _diffMatchPatch.patch_make(currentRevision.Content, content);
                    creationSucessfull = true;
                }
            }

            if (creationSucessfull)
            {
                document.CurrentRevisionId = currentRevision.Id + 1;
                document.CurrentHash       = GetHash(document.Content);
                updateDto.NewRevisionId    = document.CurrentRevisionId;
                updateDto.NewHash          = document.CurrentHash;
                document.AddRevision(new Revision
                {
                    Id        = document.CurrentRevisionId,
                    Content   = document.Content,
                    UpdateDto = updateDto
                });

                if (IsNotOwnUpdate(updateDto))
                {
                    _editor.UpdateText(updateDto.DocumentId, document.Content);

                    var acknowledgeDto = new AcknowledgeDto
                    {
                        PreviousRevisionId = updateDto.PreviousRevisionId,
                        PreviousHash       = updateDto.PreviousHash,
                        NewRevisionId      = updateDto.NewRevisionId,
                        NewHash            = updateDto.NewHash,
                        DocumentId         = document.Id
                    };

                    _communication.AckRequest(updateDto.MemberHost, acknowledgeDto);
                }

                var newUpdateDto = new UpdateDto
                {
                    DocumentId         = document.Id,
                    MemberName         = updateDto.MemberName,
                    MemberHost         = _serverHost,
                    PreviousRevisionId = updateDto.PreviousRevisionId,
                    PreviousHash       = updateDto.PreviousHash,
                    NewRevisionId      = updateDto.NewRevisionId,
                    NewHash            = updateDto.NewHash,
                    Patch       = updateDto.Patch,
                    EditorCount = document.EditorCount
                };

                foreach (var editorHost in document.Editors().Values)
                {
                    if (updateDto.MemberHost != editorHost)
                    {
                        try
                        {
                            _communication.UpdateRequest(editorHost, newUpdateDto);
                        }
                        catch (EndpointNotFoundException)
                        {
                            document.Editors().Remove(editorHost);
                        }
                    }
                }
            }
            else if (IsNotOwnUpdate(updateDto))
            {
                HandleErrorOnUpdate(updateDto);
            }
        }
        public string Patch(string sourceConfigPath, string destConfigPath)
        {
            string patchedFile = null;

            if (!(File.Exists(sourceConfigPath) && File.Exists(destConfigPath)))
            {
                Console.WriteLine("Config Patch error - could not find source or destination files");
                return(patchedFile);
            }

            string sourceData = File.ReadAllText(sourceConfigPath);
            string destData   = File.ReadAllText(destConfigPath);

            List <string> luaConfigs = new List <string>();
            int           openBraces = 0;

            foreach (string l in File.ReadAllLines(destConfigPath))
            {
                if (l.Contains('{'))
                {
                    ++openBraces;
                }
                if (l.Contains('}'))
                {
                    --openBraces;
                }

                if (l.Contains('=') && openBraces == 0)
                {
                    string def = l.Substring(0, l.IndexOf('='));
                    def = def.Trim().Trim('\t').Trim('\r').Trim('\n');
                    luaConfigs.Add(def);
                }
            }

            diff_match_patch dmp  = new diff_match_patch();
            List <Diff>      diff = dmp.diff_main(sourceData, destData);

            dmp.diff_cleanupSemantic(diff);

            List <Patch> patches = dmp.patch_make(sourceData, diff);

            List <Patch> filteredPatches = new List <Patch>();

            foreach (Patch p in patches)
            {
                bool foundPatch = false;
                foreach (Diff d in p.diffs)
                {
                    if (d.operation == Operation.INSERT || d.operation == Operation.DELETE)
                    {
                        foreach (string f in luaConfigs)
                        {
                            if (d.text.IndexOf(f) >= 0)
                            {
                                filteredPatches.Add(p);
                                foundPatch = true;
                                break;
                            }
                        }
                    }

                    if (foundPatch)
                    {
                        break;
                    }
                }
            }

            Console.WriteLine("Applying the following patches: ");
            foreach (Patch p in filteredPatches)
            {
                Console.WriteLine(p);
            }

            object[] v = dmp.patch_apply(filteredPatches, sourceData);

            return(Convert.ToString(v[0]));
        }
        /// <summary>
        /// Unpatch a JSON object
        /// </summary>
        /// <param name="right">Patched JSON object</param>
        /// <param name="patch">JSON Patch Document</param>
        /// <returns>Unpatched JSON object</returns>
        /// <exception cref="System.IO.InvalidDataException">Thrown if the patch document is invalid</exception>
        public JToken Unpatch(JToken right, JToken patch)
        {
            if (patch == null)
            {
                return(right);
            }

            if (patch.Type == JTokenType.Object)
            {
                var       patchObj        = (JObject)patch;
                JProperty arrayDiffCanary = patchObj.Property("_t");

                if (right != null &&
                    right.Type == JTokenType.Array &&
                    arrayDiffCanary != null &&
                    arrayDiffCanary.Value.Type == JTokenType.String &&
                    arrayDiffCanary.Value.ToObject <string>() == "a")
                {
                    return(ArrayUnpatch((JArray)right, patchObj));
                }

                return(ObjectUnpatch(right as JObject, patchObj));
            }

            if (patch.Type == JTokenType.Array)
            {
                var patchArray = (JArray)patch;

                if (patchArray.Count == 1)                      // Add (we need to remove the property)
                {
                    return(null);
                }

                if (patchArray.Count == 2)                      // Replace
                {
                    return(patchArray[0]);
                }

                if (patchArray.Count == 3)                      // Delete, Move or TextDiff
                {
                    if (patchArray[2].Type != JTokenType.Integer)
                    {
                        throw new InvalidDataException("Invalid patch object");
                    }

                    int op = patchArray[2].Value <int>();

                    if (op == 0)
                    {
                        return(patchArray[0]);
                    }
                    if (op == 2)
                    {
                        if (right.Type != JTokenType.String)
                        {
                            throw new InvalidDataException("Invalid patch object");
                        }

                        var          dmp     = new diff_match_patch();
                        List <Patch> patches = dmp.patch_fromText(patchArray[0].ToObject <string>());

                        if (!patches.Any())
                        {
                            throw new InvalidDataException("Invalid textline");
                        }

                        var unpatches = new List <Patch>();
                        for (int i = patches.Count - 1; i >= 0; --i)
                        {
                            Patch p = patches[i];
                            var   u = new Patch
                            {
                                length1 = p.length1,
                                length2 = p.length2,
                                start1  = p.start1,
                                start2  = p.start2
                            };

                            foreach (Diff d in p.diffs)
                            {
                                if (d.operation == Operation.DELETE)
                                {
                                    u.diffs.Add(new Diff(Operation.INSERT, d.text));
                                }
                                else if (d.operation == Operation.INSERT)
                                {
                                    u.diffs.Add(new Diff(Operation.DELETE, d.text));
                                }
                                else
                                {
                                    u.diffs.Add(d);
                                }
                            }
                            unpatches.Add(u);
                        }

                        object[] result         = dmp.patch_apply(unpatches, right.Value <string>());
                        var      unpatchResults = (bool[])result[1];
                        if (unpatchResults.Any(x => !x))
                        {
                            throw new InvalidDataException("Text patch failed");
                        }

                        string left = (string)result[0];
                        return(left);
                    }
                    throw new InvalidDataException("Invalid patch object");
                }

                throw new InvalidDataException("Invalid patch object");
            }

            return(null);
        }
        /// <summary>
        /// Patch a JSON object
        /// </summary>
        /// <param name="left">Unpatched JSON object</param>
        /// <param name="patch">JSON Patch Document</param>
        /// <returns>Patched JSON object</returns>
        /// <exception cref="System.IO.InvalidDataException">Thrown if the patch document is invalid</exception>
        public JToken Patch(JToken left, JToken patch)
        {
            if (patch == null)
            {
                return(left);
            }

            if (patch.Type == JTokenType.Object)
            {
                var       patchObj        = (JObject)patch;
                JProperty arrayDiffCanary = patchObj.Property("_t");

                if (left != null &&
                    left.Type == JTokenType.Array &&
                    arrayDiffCanary != null &&
                    arrayDiffCanary.Value.Type == JTokenType.String &&
                    arrayDiffCanary.Value.ToObject <string>() == "a")
                {
                    return(ArrayPatch((JArray)left, patchObj));
                }

                return(ObjectPatch(left as JObject, patchObj));
            }

            if (patch.Type == JTokenType.Array)
            {
                var patchArray = (JArray)patch;

                if (patchArray.Count == 1)                      // Add
                {
                    return(patchArray[0]);
                }

                if (patchArray.Count == 2)                      // Replace
                {
                    return(patchArray[1]);
                }

                if (patchArray.Count == 3)                      // Delete, Move or TextDiff
                {
                    if (patchArray[2].Type != JTokenType.Integer)
                    {
                        throw new InvalidDataException("Invalid patch object");
                    }

                    int op = patchArray[2].Value <int>();

                    if (op == 0)
                    {
                        return(null);
                    }

                    if (op == 2)
                    {
                        if (left.Type != JTokenType.String)
                        {
                            throw new InvalidDataException("Invalid patch object");
                        }

                        var          dmp     = new diff_match_patch();
                        List <Patch> patches = dmp.patch_fromText(patchArray[0].ToObject <string>());

                        if (!patches.Any())
                        {
                            throw new InvalidDataException("Invalid textline");
                        }

                        object[] result       = dmp.patch_apply(patches, left.Value <string>());
                        var      patchResults = (bool[])result[1];
                        if (patchResults.Any(x => !x))
                        {
                            throw new InvalidDataException("Text patch failed");
                        }

                        string right = (string)result[0];
                        return(right);
                    }

                    throw new InvalidDataException("Invalid patch object");
                }

                throw new InvalidDataException("Invalid patch object");
            }

            return(null);
        }
Esempio n. 23
0
        /// <summary>
        /// Updates the application.
        /// </summary>
        public void Update(Action<UpdateStatus, object> callback)
        {
            callback(UpdateStatus.Starting, null);
            diff_match_patch dmf = new diff_match_patch();
            WebClient client = new WebClient();
            callback(UpdateStatus.RetrievingFileList, null);
            string state = client.DownloadString(this.m_UpdateUri + "/initial");
            string[] lines = state.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries);
            callback(UpdateStatus.RetrievedFileList, lines.Length);
            int opers = 0;
            foreach (string line in lines)
            {
                Hash hash = Hash.FromString(line.Split(new char[] { ' ' }, 2)[0]);
                string file = line.Split(new char[] { ' ' }, 2)[1];
                callback(UpdateStatus.DeterminingOperation, file);

                // See if file already exists.
                if (File.Exists(Path.Combine(this.m_LocalPath, file)) || hash == Hash.Empty)
                {
                    if (hash == Hash.Empty)
                    {
                        // Delete the local file if it exists.
                        if (File.Exists(Path.Combine(this.m_LocalPath, file)))
                        {
                            callback(UpdateStatus.DeletionStart, file);
                            File.Delete(Path.Combine(this.m_LocalPath, file));
                            callback(UpdateStatus.DeletionFinish, file);
                            opers++;
                        }
                    }
                    else
                    {
                        // Compare hashes, ignore if same.
                        Hash current = Hash.FromFile(Path.Combine(this.m_LocalPath, file));
                        if (current == hash)
                            continue;

                        // Download patch.
                        string patchstream;
                        try
                        {
                            patchstream = client.DownloadString(this.m_UpdateUri + "/patch/" + current + "/" + hash + "/" + file);
                            callback(UpdateStatus.PatchStart, file);
                            int a = 1;
                            using (StringReader reader = new StringReader(patchstream))
                            {
                                while (true)
                                {
                                    string header = reader.ReadLine();
                                    if (header == "--- END OF PATCHES ---")
                                        break;
                                    else if (header.StartsWith("--- NEXT PATCH ("))
                                    {
                                        int count = Convert.ToInt32(header.Substring("--- NEXT PATCH (".Length, header.Length - "--- NEXT PATCH () ---".Length));
                                        char[] data = new char[count];
                                        reader.ReadBlock(data, 0, count);
                                        List<Patch> patches = dmf.patch_fromText(new string(data));
                                        string newText;
                                        using (StreamReader stream = new StreamReader(Path.Combine(this.m_LocalPath, file)))
                                        {
                                            newText = (string)dmf.patch_apply(patches, stream.ReadToEnd())[0];
                                        }
                                        using (StreamWriter stream = new StreamWriter(Path.Combine(this.m_LocalPath, file)))
                                        {
                                            stream.Write(newText);
                                        }
                                        callback(UpdateStatus.PatchApplied, a);
                                        a++;
                                        // Read the empty terminator line.
                                        reader.ReadLine();
                                    }
                                    else
                                        throw new DataMisalignedException();
                                }
                            }
                            callback(UpdateStatus.PatchFinish, file);
                            opers++;
                        }
                        catch (WebException)
                        {
                            // There's no patch list for this file, redownload.
                            string[] coms = file.Split('/');
                            DirectoryInfo di = new DirectoryInfo(this.m_LocalPath);
                            for (int i = 0; i < coms.Length - 1; i++)
                            {
                                DirectoryInfo[] dis = di.GetDirectories(coms[i]);
                                if (dis.Length == 0)
                                    di = di.CreateSubdirectory(coms[i]);
                                else
                                    di = dis[0];
                            }
                            callback(UpdateStatus.DownloadFreshStart, file);
                            client.DownloadFile(this.m_UpdateUri + "/file/" + file, Path.Combine(this.m_LocalPath, file));
                            callback(UpdateStatus.DownloadFreshFinish, file);
                            opers++;
                        }
                    }
                }
                else
                {
                    // File does not exist, download fresh.
                    string[] coms = file.Split('/');
                    DirectoryInfo di = new DirectoryInfo(this.m_LocalPath);
                    for (int i = 0; i < coms.Length - 1; i++)
                    {
                        DirectoryInfo[] dis = di.GetDirectories(coms[i]);
                        if (dis.Length == 0)
                            di = di.CreateSubdirectory(coms[i]);
                        else
                            di = dis[0];
                    }
                    callback(UpdateStatus.DownloadNewStart, file);
                    client.DownloadFile(this.m_UpdateUri + "/file/" + file, Path.Combine(this.m_LocalPath, file));
                    callback(UpdateStatus.DownloadNewFinish, file);
                    opers++;
                }
            }
            callback(UpdateStatus.Complete, opers);

            return;
        }