Ejemplo n.º 1
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()))
                    {
                        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}[ ][\\\"]{0,1}[biwco12]/(.*)[\\\"]{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 = GitModule.ReEncodeStringFromLossless(input, FilesContentEncoding);
                }
                else
                {
                    //warnings, messages ...
                    input = GitModule.ReEncodeStringFromLossless(input, GitModule.SystemEncoding);
                }
            }
        }
Ejemplo n.º 2
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>
        public Patch CreatePatchFromString(string[] lines, ref int lineIndex)
        {
            if (lineIndex >= lines.Length)
            {
                return(null);
            }

            string input = lines[lineIndex];

            if (!IsStartOfANewPatch(input, out var 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);
        }
Ejemplo n.º 3
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;
            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             = GitModule.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 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);
        }
Ejemplo n.º 4
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);
            }
        }