Пример #1
0
        public void ApplyPatch(Patch patch)
        {
            patch.FileTextB = "";
            patch.Rate = 100;

            if (patch.Type == Patch.PatchType.DeleteFile)
            {
                handleDeletePatchType(patch);
                return;
            }

            if (patch.Text == null)
                return;

            string[] patchLines = patch.Text.Split('\n');

            if (patch.Type == Patch.PatchType.NewFile)
            {
                handleNewFilePatchType(patch, patchLines);
                return;
            }

            if (patch.Type == Patch.PatchType.ChangeFile)
            {
                handleChangeFilePatchType(patch, patchLines);
                return;
            }
        }
Пример #2
0
        private void StashedSelectedIndexChanged(object sender, EventArgs e)
        {
            GitStash      gitStash    = Stashes.SelectedItem as GitStash;
            GitItemStatus stashedItem = Stashed.SelectedItem;

            Cursor.Current = Cursors.WaitCursor;

            if (stashedItem != null &&
                gitStash == currentWorkingDirStashItem) //current working dir
            {
                View.ViewCurrentChanges(stashedItem.Name, stashedItem.OldName, stashedItem.IsStaged);
            }
            else
            if (stashedItem != null)
            {
                string   extraDiffArguments = View.GetExtraDiffArguments();
                Encoding encoding           = this.View.Encoding;
                View.ViewPatch(() =>
                {
                    PatchApply.Patch patch = Settings.Module.GetSingleDiff(gitStash.Name, gitStash.Name + "^", stashedItem.Name, stashedItem.OldName, extraDiffArguments, encoding);
                    if (patch == null)
                    {
                        return(String.Empty);
                    }
                    return(patch.Text);
                });
            }
            else
            {
                View.ViewText(string.Empty, string.Empty);
            }
            Cursor.Current = Cursors.Default;
        }
Пример #3
0
        public void TestLoadPatch()
        {
            PatchManager manager = new PatchManager();

            PatchApply.Patch expectedPatch = new PatchApply.Patch();
            expectedPatch.Type = PatchApply.Patch.PatchType.ChangeFile;
            expectedPatch.Apply = true;
            expectedPatch.PatchHeader = "diff --git a/thisisatest.txt b/thisisatest.txt";
            expectedPatch.PatchIndex = "index 5e4dce2..5eb1e6f 100644";
            expectedPatch.FileNameA = "thisisatest.txt";
            expectedPatch.FileNameB = "thisisatest.txt";
            expectedPatch.AppendTextLine(expectedPatch.PatchHeader);
            expectedPatch.AppendTextLine(expectedPatch.PatchIndex);
            expectedPatch.AppendTextLine("--- a/thisisatest.txt");
            expectedPatch.AppendTextLine("+++ b/thisisatest.txt");
            expectedPatch.AppendTextLine("@@ -1,2 +1,2 @@");
            expectedPatch.AppendTextLine("iiiiii");
            expectedPatch.AppendTextLine("-asdkjaldskjlaksd");
            expectedPatch.AppendTextLine("+changed again");

            manager.LoadPatch(expectedPatch.Text, false, Encoding.Default);

            PatchApply.Patch createdPatch = manager.Patches.First();
            Assert.AreEqual(expectedPatch.Text, createdPatch.Text);
        }
Пример #4
0
        private void GridChangedFiles_SelectionChanged(object sender, EventArgs e)
        {
            if (GridChangedFiles.SelectedRows.Count == 0) return;

            var patch = (Patch)GridChangedFiles.SelectedRows[0].DataBoundItem;
            CurrentPatch = patch;

            if (patch == null) return;

            ChangesList.ViewPatch(patch);
        }
Пример #5
0
        public void TestCorrectlyLoadReversePatch()
        {
            PatchManager manager       = NewManager();
            TestPatch    expectedPatch = CreateSmallPatchExample(true);

            manager.LoadPatch(expectedPatch.PatchOutput.ToString(), false, Encoding.UTF8);

            PatchApply.Patch createdPatch = manager.Patches.First();

            Assert.AreEqual(expectedPatch.Patch.PatchHeader, createdPatch.PatchHeader, "header");
            Assert.AreEqual(expectedPatch.Patch.FileNameB, createdPatch.FileNameA, "fileA");
            Assert.AreEqual(expectedPatch.Patch.PatchIndex, createdPatch.PatchIndex);
            Assert.AreEqual(expectedPatch.Patch.Rate, createdPatch.Rate);
            Assert.AreEqual(expectedPatch.Patch.Type, createdPatch.Type);
            Assert.AreEqual(expectedPatch.Patch.Text, createdPatch.Text);
        }
Пример #6
0
        private static bool SetPatchType(string input, Patch patch)
        {
            if (input.StartsWith("new file mode "))
                patch.Type = Patch.PatchType.NewFile;
            else if (input.StartsWith("deleted file mode "))
                patch.Type = Patch.PatchType.DeleteFile;
            else if (input.StartsWith("old mode "))
                patch.Type = Patch.PatchType.ChangeFileMode;
            else
                return false;

            return true;
        }
Пример #7
0
        private void ValidateHeader(ref string input, Patch patch)
        {
            //--- /dev/null
            //means there is no old file, so this should be a new file
            if (IsOldFileMissing(input))
            {
                if (patch.Type != Patch.PatchType.NewFile)
                    throw new FormatException("Change not parsed correct: " + input);
            }
            //line starts with --- means, old file name
            else if (input.StartsWith("--- "))
            {
                input = GitModule.UnquoteFileName(input);
                Match regexMatch = Regex.Match(input, "[-]{3} [\\\"]?[aiwco12]/(.*)[\\\"]?");

                if (regexMatch.Success)
                    patch.FileNameA = regexMatch.Groups[1].Value.Trim();
                else
                    throw new FormatException("Old filename not parsed correct: " + input);
            }
            else if (IsNewFileMissing(input))
            {
                if (patch.Type != Patch.PatchType.DeleteFile)
                    throw new FormatException("Change not parsed correct: " + input);
            }
            //line starts with +++ means, new file name
            //we expect a new file now!
            else if (input.StartsWith("+++ "))
            {
                input = GitModule.UnquoteFileName(input);
                Match regexMatch = Regex.Match(input, "[+]{3} [\\\"]?[biwco12]/(.*)[\\\"]?");

                if (regexMatch.Success)
                    patch.FileNameB = regexMatch.Groups[1].Value.Trim();
                else
                    throw new FormatException("New filename not parsed correct: " + input);
            }
        }
Пример #8
0
        private static void ExtractPatchFilenames(Patch patch)
        {
            if (!patch.CombinedDiff)
            {
                Match match = Regex.Match(patch.PatchHeader,
                                          " [\\\"]?[aiwco12]/(.*)[\\\"]? [\\\"]?[biwco12]/(.*)[\\\"]?");

                patch.FileNameA = match.Groups[1].Value.Trim();
                patch.FileNameB = match.Groups[2].Value.Trim();
            }
            else
            {
                Match match = Regex.Match(patch.PatchHeader,
                                          "--cc [\\\"]?(.*)[\\\"]?");

                patch.FileNameA = match.Groups[1].Value.Trim();
            }
        }
Пример #9
0
        private void ValidateInput(ref string input, Patch patch, PatchProcessorState state)
        {
            if (state == PatchProcessorState.InHeader)
            {
                //--- /dev/null
                //means there is no old file, so this should be a new file
                if (IsOldFileMissing(input))
                {
                    if (patch.Type != Patch.PatchType.NewFile)
                        throw new FormatException("Change not parsed correct: " + input);
                }
                //line starts with --- means, old file name
                else if (input.StartsWith("--- "))
                {
                    input = GitCommandHelpers.UnquoteFileName(input);
                    Match regexMatch = Regex.Match(input, "[-]{3}[ ][\\\"]{0,1}[a]/(.*)[\\\"]{0,1}");

                    if (!regexMatch.Success || patch.FileNameA != (regexMatch.Groups[1].Value.Trim()))
                        throw new FormatException("Old filename not parsed correct: " + input);
                }
                else if (IsNewFileMissing(input))
                {
                    if (patch.Type != Patch.PatchType.DeleteFile)
                        throw new FormatException("Change not parsed correct: " + input);
                }

                //line starts with +++ means, new file name
                //we expect a new file now!
                else if (input.StartsWith("+++ "))
                {
                    input = GitCommandHelpers.UnquoteFileName(input);
                    Match regexMatch = Regex.Match(input, "[+]{3}[ ][\\\"]{0,1}[b]/(.*)[\\\"]{0,1}");

                    if (!regexMatch.Success || patch.FileNameB != (regexMatch.Groups[1].Value.Trim()))
                        throw new FormatException("New filename not parsed correct: " + input);
                }
            }
            else
            {
                if (input.StartsWithAny(new string[] { " ", "-", "+", "@" }))
                    //diff content
                    input = GitCommandHelpers.ReEncodeStringFromLossless(input, FilesContentEncoding);
                else
                    //warnings, messages ...
                    input = GitCommandHelpers.ReEncodeStringFromLossless(input, Settings.SystemEncoding);
            }
        }
Пример #10
0
        /// <summary>
        /// Diff part of patch is printed verbatim, everything else (header, warnings, ...) is printed in git encoding (Settings.SystemEncoding) 
        /// Since patch may contain diff for more than one file, it would be nice to obtaining encoding for each of file
        /// from .gitattributes, for now there is used one encoding, common for every file in repo (Settings.FilesEncoding)
        /// File path can be quoted see core.quotepath, it is unquoted by GitCommandHelpers.ReEncodeFileNameFromLossless
        /// </summary>
        /// <param name="textReader"></param>
        /// <returns></returns>
        public List<Patch> CreatePatchesFromString(String patchText)
        {
            var patches = new List<Patch>();
            Patch patch = null;
            bool validate;
            string input;
            PatchProcessorState state = PatchProcessorState.OutsidePatch;
            string[] lines = patchText.Split('\n');
            for(int i = 0; i < lines.Length; i++)
            {
                input = lines[i];
                validate = true;
                if (IsStartOfANewPatch(input))
                {
                    state = PatchProcessorState.InHeader;
                    validate = false;
                    patch = new Patch();
                    patches.Add(patch);
                    input = GitCommandHelpers.ReEncodeFileNameFromLossless(input);
                    patch.PatchHeader = input;
                    patch.Type = Patch.PatchType.ChangeFile;
                    ExtractPatchFilenames(patch);
                }
                else if (state == PatchProcessorState.InHeader)
                {
                    if (IsChunkHeader(input))
                        state = PatchProcessorState.InBody;
                    else
                    {
                        //header lines are encoded in Settings.SystemEncoding
                        input = GitCommandHelpers.ReEncodeStringFromLossless(input, Settings.SystemEncoding);
                        if (IsIndexLine(input))
                        {
                            validate = false;
                            patch.PatchIndex = input;
                        }
                        else
                        {
                            if (SetPatchType(input, patch))
                            { }
                            else if (IsUnlistedBinaryFileDelete(input))
                            {
                                if (patch.Type != Patch.PatchType.DeleteFile)
                                    throw new FormatException("Change not parsed correct: " + input);

                                patch.File = Patch.FileType.Binary;
                                patch = null;
                                state = PatchProcessorState.OutsidePatch;
                            }
                            else if (IsUnlistedBinaryNewFile(input))
                            {
                                if (patch.Type != Patch.PatchType.NewFile)
                                    throw new FormatException("Change not parsed correct: " + input);

                                patch.File = Patch.FileType.Binary;
                                //TODO: NOT SUPPORTED!
                                patch.Apply = false;
                                patch = null;
                                state = PatchProcessorState.OutsidePatch;
                            }
                            else if (IsBinaryPatch(input))
                            {
                                patch.File = Patch.FileType.Binary;

                                //TODO: NOT SUPPORTED!
                                patch.Apply = false;
                                patch = null;
                                state = PatchProcessorState.OutsidePatch;
                            }
                        }
                    }
                }

                if (state != PatchProcessorState.OutsidePatch)
                {
                    if (validate)
                        ValidateInput(ref input, patch, state);
                    patch.AppendTextLine(input);
                }
            }

            return patches;
        }
Пример #11
0
 public void ViewPatch(Patch patch)
 {
     string text = patch != null ? patch.Text : "";
     ViewPatch(text);
 }
Пример #12
0
        /// <summary>
        /// Diff part of patch is printed verbatim, everything else (header, warnings, ...) is printed in git encoding (GitModule.SystemEncoding)
        /// Since patch may contain diff for more than one file, it would be nice to obtaining encoding for each of file
        /// from .gitattributes, for now there is used one encoding, common for every file in repo (Settings.FilesEncoding)
        /// File path can be quoted see core.quotepath, it is unquoted by GitCommandHelpers.ReEncodeFileNameFromLossless
        /// </summary>
        /// <param name="textReader"></param>
        /// <returns></returns>
        public List <Patch> CreatePatchesFromString(String patchText)
        {
            var   patches             = new List <Patch>();
            Patch patch               = null;
            PatchProcessorState state = PatchProcessorState.OutsidePatch;

            string[] lines = patchText.Split('\n');
            for (int i = 0; i < lines.Length; i++)
            {
                string input    = lines[i];
                bool   validate = true;
                bool   combinedDiff;
                if (IsStartOfANewPatch(input, out combinedDiff))
                {
                    state    = PatchProcessorState.InHeader;
                    validate = false;
                    patch    = new Patch();
                    patches.Add(patch);
                    input              = GitModule.ReEncodeFileNameFromLossless(input);
                    patch.PatchHeader  = input;
                    patch.Type         = Patch.PatchType.ChangeFile;
                    patch.CombinedDiff = combinedDiff;
                    if (!combinedDiff)
                    {
                        ExtractPatchFilenames(patch);
                    }
                }
                else if (state == PatchProcessorState.InHeader)
                {
                    if (IsChunkHeader(input))
                    {
                        state = PatchProcessorState.InBody;
                    }
                    else
                    {
                        //header lines are encoded in GitModule.SystemEncoding
                        input = GitModule.ReEncodeStringFromLossless(input, GitModule.SystemEncoding);
                        if (IsIndexLine(input))
                        {
                            validate         = false;
                            patch.PatchIndex = input;
                        }
                        else
                        {
                            if (SetPatchType(input, patch))
                            {
                            }
                            else if (IsUnlistedBinaryFileDelete(input))
                            {
                                if (patch.Type != Patch.PatchType.DeleteFile)
                                {
                                    throw new FormatException("Change not parsed correct: " + input);
                                }

                                patch.File = Patch.FileType.Binary;
                                patch      = null;
                                state      = PatchProcessorState.OutsidePatch;
                            }
                            else if (IsUnlistedBinaryNewFile(input))
                            {
                                if (patch.Type != Patch.PatchType.NewFile)
                                {
                                    throw new FormatException("Change not parsed correct: " + input);
                                }

                                patch.File = Patch.FileType.Binary;
                                //TODO: NOT SUPPORTED!
                                patch.Apply = false;
                                patch       = null;
                                state       = PatchProcessorState.OutsidePatch;
                            }
                            else if (IsBinaryPatch(input))
                            {
                                patch.File = Patch.FileType.Binary;

                                //TODO: NOT SUPPORTED!
                                patch.Apply = false;
                                patch       = null;
                                state       = PatchProcessorState.OutsidePatch;
                            }
                        }
                    }
                }

                if (state != PatchProcessorState.OutsidePatch)
                {
                    if (validate)
                    {
                        ValidateInput(ref input, patch, state);
                    }
                    patch.AppendText(input);
                    if (i < lines.Length - 1)
                    {
                        patch.AppendText("\n");
                    }
                }
            }

            return(patches);
        }
Пример #13
0
        public void ApplyPatch(Patch patch)
        {
            patch.FileTextB = "";
            patch.Rate = 100;

            if (patch.Type == Patch.PatchType.DeleteFile)
            {
                patch.FileTextB = "";
                patch.Rate = 100;

                if (!File.Exists(DirToPatch + patch.FileNameA))
                {
                    patch.Rate -= 40;
                    patch.Apply = false;
                }

                return;
            }

            if (patch.Text == null) return;

            string [] patchLines = patch.Text.Split('\n');

            if (patch.Type == Patch.PatchType.NewFile)
            {
                foreach (string line in patchLines)
                {
                    if (line.Length > 0 && line.StartsWith("+"))
                    {
                        if (line.Length > 4 && line.StartsWith("+"))
                            patch.Text += line.Substring(4);
                        else
                        if (line.Length > 1)
                            patch.FileTextB += line.Substring(1);

                        patch.FileTextB += "\n";
                    }
                }
                if (patch.FileTextB.Length > 0 && patch.FileTextB[patch.FileTextB.Length - 1] == '\n')
                    patch.FileTextB = patch.FileTextB.Remove(patch.FileTextB.Length - 1, 1);
                patch.Rate = 100;

                if (File.Exists(DirToPatch + patch.FileNameB))
                {
                    patch.Rate -= 40;
                    patch.Apply = false;
                }

                return;
            }

            if (patch.Type == Patch.PatchType.ChangeFile)
            {
                List<string> fileLines = new List<string>();
                foreach (string s in LoadFile(patch.FileNameA).Split('\n'))
                {
                    fileLines.Add(s);
                }

                int lineNumber = 0;
                foreach (string line in patchLines)
                {
                    //Parse fist line
                    //@@ -1,4 +1,4 @@
                    if (line.StartsWith("@@") && line.LastIndexOf("@@") > 0)
                    {
                        string pos = line.Substring(3, line.LastIndexOf("@@") - 3).Trim();
                        string [] addrem = pos.Split('+', '-');
                        string[] oldLines = addrem[1].Split(',');
                        string[] newLines = addrem[2].Split(',');

                        lineNumber = Int32.Parse(oldLines[0])-1;

                        //line = line.Substring(line.LastIndexOf("@@") + 3));
                        continue;
                    }

                    if (line.StartsWith(" "))
                    {
                        //Do some extra checks
                        if (line.Length > 0)
                        {
                            if (fileLines.Count > lineNumber && fileLines[lineNumber].CompareTo(line.Substring(1)) != 0)
                                patch.Rate -= 20;
                        }
                        else
                        {
                            if (fileLines.Count > lineNumber && fileLines[lineNumber] != "")
                                patch.Rate -= 20;
                        }

                        lineNumber++;
                    } else
                    if (line.StartsWith("-"))
                    {
                        if (line.Length > 0)
                        {
                            if (fileLines.Count > lineNumber && fileLines[lineNumber].CompareTo(line.Substring(1)) != 0)
                                patch.Rate -= 20;
                        } else
                        {
                            if (fileLines.Count > lineNumber && fileLines[lineNumber] != "")
                                patch.Rate -= 20;
                        }

                        patch.BookMarks.Add(lineNumber);

                        if (fileLines.Count > lineNumber)
                            fileLines.RemoveAt(lineNumber);
                        else
                            patch.Rate -= 20;

                        //lineNumber++;
                    } else
                    if (line.StartsWith("+"))
                    {
                        string insertLine = "";
                        if (line.Length > 1)
                            insertLine = line.Substring(1);

                        //Is the patch allready applied?
                        if (fileLines.Count > lineNumber && fileLines[lineNumber].CompareTo(insertLine) == 0)
                        {
                            patch.Rate -= 20;
                        }

                        fileLines.Insert(lineNumber, insertLine);
                        patch.BookMarks.Add(lineNumber);

                        lineNumber++;
                    }
                }
                foreach (string patchedLine in fileLines)
                {
                    patch.FileTextB += patchedLine + "\n";
                }
                if (patch.FileTextB.Length > 0 && patch.FileTextB[patch.FileTextB.Length - 1] == '\n')
                    patch.FileTextB = patch.FileTextB.Remove(patch.FileTextB.Length - 1, 1);

                if (patch.Rate != 100)
                    patch.Apply = false;

                return;
            }
        }
Пример #14
0
 public TestPatch()
 {
     Patch       = new PatchApply.Patch();
     PatchOutput = new StringBuilder();
 }
Пример #15
0
        /// <summary>
        /// Diff part of patch is printed verbatim, everything else (header, warnings, ...) is printed in git encoding (GitModule.SystemEncoding)
        /// Since patch may contain diff for more than one file, it would be nice to obtaining encoding for each of file
        /// from .gitattributes, for now there is used one encoding, common for every file in repo (Settings.FilesEncoding)
        /// File path can be quoted see core.quotepath, it is unquoted by GitCommandHelpers.ReEncodeFileNameFromLossless
        /// </summary>
        /// <param name="lines">patch lines</param>
        /// <param name="lineIndex">start index</param>
        /// <returns></returns>
        public Patch CreatePatchFromString(string[] lines, ref int lineIndex)
        {
            if (lineIndex >= lines.Length)
                return null;

            string input = lines[lineIndex];
            bool combinedDiff;
            if (!IsStartOfANewPatch(input, out combinedDiff))
                return null;

            PatchProcessorState state = PatchProcessorState.InHeader;
            Patch patch = new Patch();
            input = GitModule.ReEncodeFileNameFromLossless(input);
            patch.PatchHeader = input;
            patch.Type = Patch.PatchType.ChangeFile;
            patch.CombinedDiff = combinedDiff;
            ExtractPatchFilenames(patch);
            patch.AppendText(input);
            if (lineIndex < lines.Length - 1)
                patch.AppendText("\n");

            int i = lineIndex + 1;
            for (; i < lines.Length; i++)
            {
                input = lines[i];

                if (IsStartOfANewPatch(input))
                {
                    lineIndex = i - 1;
                    return patch;
                }

                if (IsChunkHeader(input))
                {
                    state = PatchProcessorState.InBody;
                    break;
                }

                //header lines are encoded in GitModule.SystemEncoding
                input = GitModule.ReEncodeStringFromLossless(input, GitModule.SystemEncoding);
                if (IsIndexLine(input))
                {
                    patch.PatchIndex = input;
                    if (i < lines.Length - 1)
                        input += "\n";
                    patch.AppendText(input);
                    continue;
                }

                if (SetPatchType(input, patch))
                {

                }
                else if (IsUnlistedBinaryFileDelete(input))
                {
                    if (patch.Type != Patch.PatchType.DeleteFile)
                        throw new FormatException("Change not parsed correct: " + input);

                    patch.File = Patch.FileType.Binary;
                    state = PatchProcessorState.OutsidePatch;
                    break;
                }
                else if (IsUnlistedBinaryNewFile(input))
                {
                    if (patch.Type != Patch.PatchType.NewFile)
                        throw new FormatException("Change not parsed correct: " + input);

                    patch.File = Patch.FileType.Binary;
                    //TODO: NOT SUPPORTED!
                    patch.Apply = false;
                    state = PatchProcessorState.OutsidePatch;
                    break;
                }
                else if (IsBinaryPatch(input))
                {
                    patch.File = Patch.FileType.Binary;

                    //TODO: NOT SUPPORTED!
                    patch.Apply = false;
                    state = PatchProcessorState.OutsidePatch;
                    break;
                }
                ValidateHeader(ref input, patch);
                if (i < lines.Length - 1)
                    input += "\n";
                patch.AppendText(input);
            }

            // process patch body
            for (; i < lines.Length; i++)
            {
                input = lines[i];

                if (IsStartOfANewPatch(input, out combinedDiff))
                {
                    lineIndex = i - 1;
                    return patch;
                }

                if (state == PatchProcessorState.InBody && input.StartsWithAny(new[] { " ", "-", "+", "@" }))
                {
                    //diff content
                    input = GitModule.ReEncodeStringFromLossless(input, FilesContentEncoding);
                }
                else
                {
                    //warnings, messages ...
                    input = GitModule.ReEncodeStringFromLossless(input, GitModule.SystemEncoding);
                }
                if (i < lines.Length - 1)
                    input += "\n";
                patch.AppendText(input);
            }

            lineIndex = i - 1;
            return patch;
        }
Пример #16
0
        public List <Patch> CreatePatchesFromReader(TextReader textReader)
        {
            var    patches  = new List <Patch>();
            Patch  patch    = null;
            bool   gitPatch = false;
            string input;

            while ((input = textReader.ReadLine()) != null)
            {
                if (IsStartOfANewPatch(input))
                {
                    gitPatch          = true;
                    patch             = new Patch();
                    patch.PatchHeader = input;
                    patch.AppendTextLine(patch.PatchHeader);
                    patches.Add(patch);
                    input = GitCommandHelpers.ReEncodeFileName(input);
                    ExtractPatchFilenames(input, patch);
                    if ((input = textReader.ReadLine()) != null)
                    {
                        if (IsStartOfANewPatch(input))
                        {
                            continue;
                        }

                        SetPatchType(input, patch);

                        if (!IsIndexLine(input))
                        {
                            if (textReader.ReadLine() == null)
                            {
                                break;
                            }
                        }
                        else
                        {
                            patch.PatchIndex = input;
                            patch.AppendTextLine(patch.PatchIndex);
                        }
                    }

                    if ((input = textReader.ReadLine()) != null)
                    {
                        input = GitCommandHelpers.ReEncodeFileName(input);
                        if (IsUnlistedBinaryFileDelete(input))
                        {
                            patch.File = Patch.FileType.Binary;

                            if (patch.Type != Patch.PatchType.DeleteFile)
                            {
                                throw new FormatException("Change not parsed correct: " + input);
                            }

                            patch = null;
                            continue;
                        }

                        if (IsUnlistedBinaryNewFile(input))
                        {
                            patch.File = Patch.FileType.Binary;

                            if (patch.Type != Patch.PatchType.NewFile)
                            {
                                throw new FormatException("Change not parsed correct: " + input);
                            }

                            //TODO: NOT SUPPORTED!
                            patch.Apply = false;

                            patch = null;

                            continue;
                        }

                        if (IsBinaryPatch(input))
                        {
                            patch.File = Patch.FileType.Binary;

                            //TODO: NOT SUPPORTED!
                            patch.Apply = false;

                            patch = null;

                            continue;
                        }
                    }

                    //continue;
                }

                if (!gitPatch || patch != null)
                {
                    ValidateInput(ref input, patch, gitPatch);
                }

                if (patch != null)
                {
                    patch.AppendTextLine(input);
                }
            }

            return(patches);
        }
Пример #17
0
 public void TestConstructor()
 {
     Patch patch = new Patch();
     Assert.IsNotNull(patch);
 }
Пример #18
0
        public List<Patch> CreatePatchesFromReader(TextReader textReader)
        {
            var patches = new List<Patch>();
            Patch patch = null;
            bool gitPatch = false;
            string input;
            while ((input = textReader.ReadLine()) != null)
            {
                if (IsStartOfANewPatch(input))
                {
                    gitPatch = true;
                    patch = new Patch();
                    patch.PatchHeader = input;
                    patch.AppendTextLine(patch.PatchHeader);
                    patches.Add(patch);
                    input = GitCommandHelpers.ReEncodeFileName(input);
                    ExtractPatchFilenames(input, patch);
                    if ((input = textReader.ReadLine()) != null)
                    {
                        if (IsStartOfANewPatch(input))
                        {
                            continue;
                        }

                        SetPatchType(input, patch);

                        if (!IsIndexLine(input))
                        {
                            if (textReader.ReadLine() == null)
                            {
                                break;
                            }
                        }
                        else
                        {
                            patch.PatchIndex = input;
                            patch.AppendTextLine(patch.PatchIndex);
                        }
                    }

                    if ((input = textReader.ReadLine()) != null)
                    {
                       input = GitCommandHelpers.ReEncodeFileName(input);
                       if (IsUnlistedBinaryFileDelete(input))
                        {
                            patch.File = Patch.FileType.Binary;

                            if (patch.Type != Patch.PatchType.DeleteFile)
                                throw new FormatException("Change not parsed correct: " + input);

                            patch = null;
                            continue;
                        }

                        if (IsUnlistedBinaryNewFile(input))
                        {
                            patch.File = Patch.FileType.Binary;

                            if (patch.Type != Patch.PatchType.NewFile)
                                throw new FormatException("Change not parsed correct: " + input);

                            //TODO: NOT SUPPORTED!
                            patch.Apply = false;

                            patch = null;

                            continue;
                        }

                        if (IsBinaryPatch(input))
                        {
                            patch.File = Patch.FileType.Binary;

                            //TODO: NOT SUPPORTED!
                            patch.Apply = false;

                            patch = null;

                            continue;
                        }
                    }

                    //continue;
                }

                if (!gitPatch || patch != null)
                {
                    ValidateInput(ref input, patch, gitPatch);
                }

                if (patch != null)
                    patch.AppendTextLine(input);
            }

            return patches;
        }
Пример #19
0
        /// <summary>
        /// Diff part of patch is printed verbatim, everything else (header, warnings, ...) is printed in git encoding (GitModule.SystemEncoding)
        /// Since patch may contain diff for more than one file, it would be nice to obtaining encoding for each of file
        /// from .gitattributes, for now there is used one encoding, common for every file in repo (Settings.FilesEncoding)
        /// File path can be quoted see core.quotepath, it is unquoted by GitCommandHelpers.ReEncodeFileNameFromLossless
        /// </summary>
        /// <param name="lines">patch lines</param>
        /// <param name="lineIndex">start index</param>
        /// <returns></returns>
        public Patch CreatePatchFromString(string[] lines, ref int lineIndex)
        {
            if (lineIndex >= lines.Length)
            {
                return(null);
            }

            string input = lines[lineIndex];
            bool   combinedDiff;

            if (!IsStartOfANewPatch(input, out combinedDiff))
            {
                return(null);
            }

            PatchProcessorState state = PatchProcessorState.InHeader;
            Patch patch = new Patch();

            input              = GitModule.ReEncodeFileNameFromLossless(input);
            patch.PatchHeader  = input;
            patch.Type         = Patch.PatchType.ChangeFile;
            patch.CombinedDiff = combinedDiff;
            ExtractPatchFilenames(patch);
            patch.AppendText(input);
            if (lineIndex < lines.Length - 1)
            {
                patch.AppendText("\n");
            }

            int i = lineIndex + 1;

            for (; i < lines.Length; i++)
            {
                input = lines[i];

                if (IsStartOfANewPatch(input))
                {
                    lineIndex = i - 1;
                    return(patch);
                }

                if (IsChunkHeader(input))
                {
                    state = PatchProcessorState.InBody;
                    break;
                }

                //header lines are encoded in GitModule.SystemEncoding
                input = GitModule.ReEncodeStringFromLossless(input, GitModule.SystemEncoding);
                if (IsIndexLine(input))
                {
                    patch.PatchIndex = input;
                    if (i < lines.Length - 1)
                    {
                        input += "\n";
                    }
                    patch.AppendText(input);
                    continue;
                }

                if (SetPatchType(input, patch))
                {
                }
                else if (IsUnlistedBinaryFileDelete(input))
                {
                    if (patch.Type != Patch.PatchType.DeleteFile)
                    {
                        throw new FormatException("Change not parsed correct: " + input);
                    }

                    patch.File = Patch.FileType.Binary;
                    state      = PatchProcessorState.OutsidePatch;
                    break;
                }
                else if (IsUnlistedBinaryNewFile(input))
                {
                    if (patch.Type != Patch.PatchType.NewFile)
                    {
                        throw new FormatException("Change not parsed correct: " + input);
                    }

                    patch.File = Patch.FileType.Binary;
                    //TODO: NOT SUPPORTED!
                    patch.Apply = false;
                    state       = PatchProcessorState.OutsidePatch;
                    break;
                }
                else if (IsBinaryPatch(input))
                {
                    patch.File = Patch.FileType.Binary;

                    //TODO: NOT SUPPORTED!
                    patch.Apply = false;
                    state       = PatchProcessorState.OutsidePatch;
                    break;
                }
                ValidateHeader(ref input, patch);
                if (i < lines.Length - 1)
                {
                    input += "\n";
                }
                patch.AppendText(input);
            }

            // process patch body
            for (; i < lines.Length; i++)
            {
                input = lines[i];

                if (IsStartOfANewPatch(input, out combinedDiff))
                {
                    lineIndex = i - 1;
                    return(patch);
                }

                if (state == PatchProcessorState.InBody && input.StartsWithAny(new[] { " ", "-", "+", "@" }))
                {
                    //diff content
                    input = GitModule.ReEncodeStringFromLossless(input, FilesContentEncoding);
                }
                else
                {
                    //warnings, messages ...
                    input = GitModule.ReEncodeStringFromLossless(input, GitModule.SystemEncoding);
                }
                if (i < lines.Length - 1)
                {
                    input += "\n";
                }
                patch.AppendText(input);
            }

            lineIndex = i - 1;
            return(patch);
        }
Пример #20
0
        private static void ValidateInput(ref string input, Patch patch, bool gitPatch)
        {
            //The previous check checked only if the file was binary
            //--- /dev/null
            //means there is no old file, so this should be a new file
            if (IsOldFileMissing(input))
            {
                if (gitPatch && patch.Type != Patch.PatchType.NewFile)
                    throw new FormatException("Change not parsed correct: " + input);
            }

            //line starts with --- means, old file name
            if (HasOldFileName(input))
            {
                input = GitCommandHelpers.ReEncodeFileName(input);
                if (gitPatch && patch.FileNameA != (input.Substring(6).Trim()))
                    throw new FormatException("Old filename not parsed correct: " + input);
            }

            if (IsNewFileMissing(input))
            {
                if (gitPatch && patch.Type != Patch.PatchType.DeleteFile)
                    throw new FormatException("Change not parsed correct: " + input);
            }

            //line starts with +++ means, new file name
            //we expect a new file now!
            if (input.StartsWith("+++ ") && !IsNewFileMissing(input))
            {
                input = GitCommandHelpers.ReEncodeFileName(input);
                Match regexMatch = Regex.Match(input, "[+]{3}[ ][\\\"]{0,1}[b]/(.*)[\\\"]{0,1}");

                if (gitPatch && patch.FileNameB != (regexMatch.Groups[1].Value.Trim()))
                    throw new FormatException("New filename not parsed correct: " + input);
            }
        }
Пример #21
0
 private static void SetPatchType(string input, Patch patch)
 {
     if (input.StartsWith("new file mode "))
         patch.Type = Patch.PatchType.NewFile;
     else if (input.StartsWith("deleted file mode "))
         patch.Type = Patch.PatchType.DeleteFile;
     else
         patch.Type = Patch.PatchType.ChangeFile;
 }
Пример #22
0
        private void ShowPatch(Patch patch)
        {
            string syntax = "XML";
            if ((patch.FileNameB.LastIndexOf('.') > 0))
            {
                string extension = patch.FileNameB.Substring(patch.FileNameB.LastIndexOf('.') + 1).ToUpper();

                switch (extension)
                {
                    case "BAS":
                    case "VBS":
                    case "VB":
                        syntax = "VBNET";
                        break;
                    case "CS":
                        syntax = "C#";
                        break;
                    case "CMD":
                    case "BAT":
                        syntax = "BAT";
                        break;
                    case "C":
                    case "RC":
                    case "IDL":
                    case "H":
                    case "CPP":
                        syntax = "C#";
                        break;
                    default:
                        break;
                }
            }
            View.SetHighlighting(syntax);

            View.Text = patch.Text;
            View.Refresh();
        }
Пример #23
0
 public TestPatch()
 {
     Patch = new Patch();
     PatchOutput = new StringBuilder();
 }
Пример #24
0
        public void LoadPatchStream(TextReader re, bool applyPatch)
        {
            string input = null;

            patches = new List<Patch>();
            Patch patch = null;

            bool gitPatch = false;

            input = re.ReadLine();

            while (input != null)
            {
                //diff --git a/FileA b/FileB
                //new patch found
                if (input.StartsWith("diff --git "))
                {
                    gitPatch = true;
                    patch = new Patch();
                    patches.Add(patch);

                    patch.FileNameA = input.Substring(input.LastIndexOf(" a/") + 3, input.LastIndexOf(" b/") - (input.LastIndexOf(" a/") + 3));
                    patch.FileNameB = input.Substring(input.LastIndexOf(" b/") + 3);

                    //The next line tells us what kind of patch
                    //new file mode xxxxxx means new file
                    //delete file mode xxxxxx means delete file
                    //index means -> no new and no delete, edit
                    if ((input = re.ReadLine()) != null)
                    {
                        //WTF! No change
                        if (input.StartsWith("diff --git "))
                        {
                            //No change? lets continue to the next line
                            continue;
                        }

                        //new file!
                        if (input.StartsWith("new file mode "))
                            patch.Type = Patch.PatchType.NewFile;
                        else
                            if (input.StartsWith("deleted file mode "))
                                patch.Type = Patch.PatchType.DeleteFile;
                            else
                                patch.Type = Patch.PatchType.ChangeFile;

                        //we need to move to the line that says 'index'
                        //because we are not sure if we are there yet because
                        //we might point at the new or delete line lines
                        if (!input.StartsWith("index "))
                            if ((input = re.ReadLine()) == null)
                                break;
                    }

                    //The next lines tells us more about the change itself
                    //Read the next
                    if ((input = re.ReadLine()) != null)
                    {
                        //Binary files a/FileA and /dev/null differ
                        //means the file is deleted but the changes are not listed explicid
                        if (input.StartsWith("Binary files a/") && input.EndsWith(" and /dev/null differ"))
                        {
                            patch.File = Patch.FileType.Binary;

                            //Check if the type was set correctly
                            if (patch.Type != Patch.PatchType.DeleteFile)
                                throw new Exception("Change not parsed correct: " + input);

                            patch = null;

                            if ((input = re.ReadLine()) == null)
                                break;

                            //Continue loop, we do not get more info about this change
                            continue;
                        }

                        //Binary files a/FileA and /dev/null differ
                        //means the file is deleted but the changes are not listed explicid
                        if (input.StartsWith("Binary files /dev/null and b/") && input.EndsWith(" differ"))
                        {
                            patch.File = Patch.FileType.Binary;

                            //Check if the type was set correctly
                            if (patch.Type != Patch.PatchType.NewFile)
                                throw new Exception("Change not parsed correct: " + input);

                            //TODO: NOT SUPPORTED!
                            patch.Apply = false;

                            patch = null;

                            if ((input = re.ReadLine()) == null)
                                break;

                            continue;
                        }

                        //GIT binary patch
                        //means the file is binairy
                        if (input.StartsWith("GIT binary patch"))
                        {
                            patch.File = Patch.FileType.Binary;

                            //TODO: NOT SUPPORTED!
                            patch.Apply = false;

                            patch = null;

                            if ((input = re.ReadLine()) == null)
                                break;

                            continue;
                        }
                    }

                    continue;
                }

                if (!gitPatch || gitPatch && patch != null)
                {
                    //The previous check checked only if the file was binary
                    //--- /dev/null
                    //means there is no old file, so this should be a new file
                    if (input.StartsWith("--- /dev/null"))
                    {
                        if (!gitPatch)
                        {
                            patch = new Patch();
                            patches.Add(patch);
                        }

                        if (gitPatch && patch.Type != Patch.PatchType.NewFile)
                            throw new Exception("Change not parsed correct: " + input);

                        //This line is parsed, NEXT!
                        if ((input = re.ReadLine()) == null)
                            break;

                    }

                    //line starts with --- means, old file name
                    if (input.StartsWith("--- a/") && !input.StartsWith("--- /dev/null"))
                    {
                        if (!gitPatch)
                        {
                            patch = new Patch();
                            patches.Add(patch);
                        }

                        if (gitPatch && patch.FileNameA != (input.Substring(6).Trim()))
                            throw new Exception("Old filename not parsed correct: " + input);

                        patch.FileNameA = (input.Substring(6).Trim());

                        //This line is parsed, NEXT!
                        if ((input = re.ReadLine()) == null)
                            break;

                    }

                    //If there is no 'newfile', reset files
                    if (input.StartsWith("+++ /dev/null"))
                    {
                        if (gitPatch && patch.Type != Patch.PatchType.DeleteFile)
                            throw new Exception("Change not parsed correct: " + input);

                        //This line is parsed, NEXT!
                        if ((input = re.ReadLine()) == null)
                            break;
                    }

                    //line starts with +++ means, new file name
                    //we expect a new file now!
                    if (input.StartsWith("+++ ") && !input.StartsWith("+++ /dev/null"))
                    {
                        if (gitPatch && patch.FileNameB != (input.Substring(6).Trim()))
                            throw new Exception("New filename not parsed correct: " + input);

                        patch.FileNameB = (input.Substring(6).Trim());

                        //This line is parsed, NEXT!
                        if ((input = re.ReadLine()) == null)
                            break;
                    }
                }

                if (patch != null)
                    patch.Text += input + "\n";

                if ((input = re.ReadLine()) == null)
                    break;
            }

            re.Close();

            if (applyPatch)
            {
                foreach (Patch patchApply in patches)
                {
                    if (patchApply.Apply == true)
                        ApplyPatch(patchApply);
                }
            }
        }
Пример #25
0
        private void handleChangeFilePatchType(Patch patch, string[] patchLines)
        {
            List<string> fileLines = new List<string>();
            foreach (string s in LoadFile(patch.FileNameA).Split('\n'))
            {
                fileLines.Add(s);
            }

            int lineNumber = 0;
            foreach (string line in patchLines)
            {
                //Parse fist line
                //@@ -1,4 +1,4 @@
                if (line.StartsWith("@@") && line.LastIndexOf("@@") > 0)
                {
                    string pos = line.Substring(3, line.LastIndexOf("@@") - 3).Trim();
                    string[] addrem = pos.Split('+', '-');
                    string[] oldLines = addrem[1].Split(',');
                    string[] newLines = addrem[2].Split(',');

                    lineNumber = Int32.Parse(oldLines[0]) - 1;

                    //line = line.Substring(line.LastIndexOf("@@") + 3));
                    continue;
                }

                if (line.StartsWith(" "))
                {
                    //Do some extra checks
                    if (line.Length > 0)
                    {
                        if (fileLines.Count > lineNumber && fileLines[lineNumber].CompareTo(line.Substring(1)) != 0)
                            patch.Rate -= 20;
                    }
                    else
                    {
                        if (fileLines.Count > lineNumber && fileLines[lineNumber] != "")
                            patch.Rate -= 20;
                    }

                    lineNumber++;
                }
                if (line.StartsWith("-"))
                {
                    if (line.Length > 0)
                    {
                        if (fileLines.Count > lineNumber && fileLines[lineNumber].CompareTo(line.Substring(1)) != 0)
                            patch.Rate -= 20;
                    }
                    else
                    {
                        if (fileLines.Count > lineNumber && fileLines[lineNumber] != "")
                            patch.Rate -= 20;
                    }

                    patch.Bookmarks.Add(lineNumber);

                    if (fileLines.Count > lineNumber)
                        fileLines.RemoveAt(lineNumber);
                    else
                        patch.Rate -= 20;

                    //lineNumber++;
                }
                if (line.StartsWith("+"))
                {
                    string insertLine = "";
                    if (line.Length > 1)
                        insertLine = line.Substring(1);

                    //Is the patch allready applied?
                    if (fileLines.Count > lineNumber && fileLines[lineNumber].CompareTo(insertLine) == 0)
                    {
                        patch.Rate -= 20;
                    }

                    fileLines.Insert(lineNumber, insertLine);
                    patch.Bookmarks.Add(lineNumber);

                    lineNumber++;
                }
            }
            foreach (string patchedLine in fileLines)
            {
                patch.FileTextB += patchedLine + "\n";
            }
            if (patch.FileTextB.Length > 0 && patch.FileTextB[patch.FileTextB.Length - 1] == '\n')
                patch.FileTextB = patch.FileTextB.Remove(patch.FileTextB.Length - 1, 1);

            if (patch.Rate != 100)
                patch.Apply = false;
        }
Пример #26
0
 private void ShowPatch(Patch patch)
 {
     View.ViewPatch(patch.Text);
 }
Пример #27
0
        private void handleDeletePatchType(Patch patch)
        {
            patch.FileTextB = "";
            patch.Rate = 100;

            if (!File.Exists(DirToPatch + patch.FileNameA))
            {
                patch.Rate -= 40;
                patch.Apply = false;
            }
        }
Пример #28
0
        private void handleNewFilePatchType(Patch patch, string[] patchLines)
        {
            foreach (string line in patchLines)
            {
                if (line.Length > 0 && line.StartsWith("+"))
                {
                    if (line.Length > 4 && line.StartsWith("+"))
                        patch.AppendText(line.Substring(4));
                    else
                        if (line.Length > 1)
                            patch.FileTextB += line.Substring(1);

                    patch.FileTextB += "\n";
                }
            }
            if (patch.FileTextB.Length > 0 && patch.FileTextB[patch.FileTextB.Length - 1] == '\n')
                patch.FileTextB = patch.FileTextB.Remove(patch.FileTextB.Length - 1, 1);
            patch.Rate = 100;

            if (File.Exists(DirToPatch + patch.FileNameB))
            {
                patch.Rate -= 40;
                patch.Apply = false;
            }
        }
Пример #29
0
        private static void ExtractPatchFilenames(Patch patch)
        {
            Match match = Regex.Match(patch.PatchHeader,
                                      "[ ][\\\"]{0,1}[a]/(.*)[\\\"]{0,1}[ ][\\\"]{0,1}[b]/(.*)[\\\"]{0,1}");

            patch.FileNameA = match.Groups[1].Value;
            patch.FileNameB = match.Groups[2].Value;
        }
Пример #30
0
 public void ViewStagingPatch(Patch patch)
 {
     ViewPatch(patch);
     Reset(true, true, true);
 }
Пример #31
0
        private void ValidateInput(ref string input, Patch patch, PatchProcessorState state)
        {
            if (state == PatchProcessorState.InHeader)
            {
                //--- /dev/null
                //means there is no old file, so this should be a new file
                if (IsOldFileMissing(input))
                {
                    if (patch.Type != Patch.PatchType.NewFile)
                    {
                        throw new FormatException("Change not parsed correct: " + input);
                    }
                }
                //line starts with --- means, old file name
                else if (input.StartsWith("--- "))
                {
                    input = GitModule.UnquoteFileName(input);
                    Match regexMatch = Regex.Match(input, "[-]{3}[ ][\\\"]{0,1}[aiwco12]/(.*)[\\\"]{0,1}");

                    if (!regexMatch.Success || patch.FileNameA != (regexMatch.Groups[1].Value.Trim()))
                    {
                        if (!patch.CombinedDiff)
                        {
                            throw new FormatException("Old filename not parsed correct: " + input);
                        }
                        patch.FileNameA = regexMatch.Groups[1].Value.Trim();
                    }
                }
                else if (IsNewFileMissing(input))
                {
                    if (patch.Type != Patch.PatchType.DeleteFile)
                    {
                        throw new FormatException("Change not parsed correct: " + input);
                    }
                }

                //line starts with +++ means, new file name
                //we expect a new file now!
                else if (input.StartsWith("+++ "))
                {
                    if (patch.CombinedDiff)
                    {
                        return;
                    }
                    input = GitModule.UnquoteFileName(input);
                    Match regexMatch = Regex.Match(input, "[+]{3}[ ][\\\"]{0,1}[biwco12]/(.*)[\\\"]{0,1}");

                    if (!regexMatch.Success || patch.FileNameB != (regexMatch.Groups[1].Value.Trim()))
                    {
                        if (!patch.CombinedDiff)
                        {
                            throw new FormatException("New filename not parsed correct: " + input);
                        }
                        patch.FileNameB = regexMatch.Groups[1].Value.Trim();
                    }
                }
            }
            else
            {
                if (input.StartsWithAny(new string[] { " ", "-", "+", "@" }))
                {
                    //diff content
                    input = GitModule.ReEncodeStringFromLossless(input, FilesContentEncoding);
                }
                else
                {
                    //warnings, messages ...
                    input = GitModule.ReEncodeStringFromLossless(input, GitModule.SystemEncoding);
                }
            }
        }