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); } } }
/// <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); }
/// <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); }
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); } }