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; } }
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; }
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); }
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); }
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); }
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; }
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); } }
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(); } }
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); } }
/// <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; }
public void ViewPatch(Patch patch) { string text = patch != null ? patch.Text : ""; ViewPatch(text); }
/// <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); }
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; } }
public TestPatch() { Patch = new PatchApply.Patch(); PatchOutput = new StringBuilder(); }
/// <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; }
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); }
public void TestConstructor() { Patch patch = new Patch(); Assert.IsNotNull(patch); }
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; }
/// <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); }
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); } }
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; }
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(); }
public TestPatch() { Patch = new Patch(); PatchOutput = new StringBuilder(); }
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); } } }
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; }
private void ShowPatch(Patch patch) { View.ViewPatch(patch.Text); }
private void handleDeletePatchType(Patch patch) { patch.FileTextB = ""; patch.Rate = 100; if (!File.Exists(DirToPatch + patch.FileNameA)) { patch.Rate -= 40; patch.Apply = false; } }
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; } }
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; }
public void ViewStagingPatch(Patch patch) { ViewPatch(patch); Reset(true, true, true); }
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); } } }