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