File indexing completed on 2024-05-12 05:52:07
0001 /* 0002 SPDX-FileCopyrightText: 2007 Andreas Pakulat <apaku@gmx.de> 0003 SPDX-FileCopyrightText: 2007 Matthew Woehlke <mw_triad@users.sourceforge.net> 0004 SPDX-FileCopyrightText: 2020 Jonathan Verner <jonathan.verner@matfyz.cz> 0005 0006 SPDX-License-Identifier: LGPL-2.0-or-later 0007 */ 0008 #pragma once 0009 0010 #include <QList> 0011 #include <memory> 0012 0013 class QUrl; 0014 class QString; 0015 0016 /** 0017 * A class representing a unified diff, possibly with 0018 * conflict markers. 0019 * 0020 * A diff is assumed to be a collection of hunks, where each hunk has the 0021 * following structure: 0022 * 0023 * METADATA 0024 * --- a/SOURCE_PATH 0025 * +++ b/TARGET_PATH 0026 * HUNK1 HEADER 0027 * HUNK1 CONTENT 0028 * [METADATA] 0029 * HUNK2 HEADER 0030 * HUNK2 CONTENT 0031 * ... 0032 * 0033 * METADATA are lines which start with anything except for a '+', '-' and ' '. 0034 * The path specifications may optionally precede a hunk and are assumed to 0035 * apply to all following hunks until a new path specification 0036 * is found. These indicate the files for which the diff is generated. 0037 * 0038 * Hunk Header 0039 * ------------ 0040 * 0041 * Each hunk header has the following form 0042 * 0043 * @@ -SRC_OFFSET[, SRC_CHANGES_COUNT] +TGT_OFFSET[, TGT_CHANGES_COUNT] @@ Heading 0044 * 0045 * where the SRC_OFFSET is a 1-based line index pointing to the source file where 0046 * the hunk applies and TGT_OFFSET is a 1-based line index pointing to the target 0047 * file where the hunk applies. The optional SRC_CHANGES_COUNTS (assumed to be 1 0048 * if not present) specifies the number of context lines plus the number of 0049 * deleted lines. Similarly, the optional TGT_CHANGES_COUNT specifies the 0050 * number of context lines plus the number of added lines. The Heading, used as a 0051 * visual aid for users, is supposed to show the line where the nearest enclosing 0052 * function scope of the hunk starts. 0053 * 0054 * Hunk Content 0055 * ------------ 0056 * 0057 * The hunk content is a collection of lines which starting with '+' (additions), 0058 * '-' (deletions) and ' ' (context lines; empty lines are also take to be context 0059 * lines). Additionally, a hunk may contain conflict markers which are of the form 0060 * 0061 * >>>>>>> our ref 0062 * our content 0063 * ... 0064 * ======= 0065 * their content 0066 * ... 0067 * <<<<<<< their ref 0068 * 0069 * and indicate unresolved conflicts. 0070 * 0071 */ 0072 class VcsDiff 0073 { 0074 public: 0075 /* Used to represent a patch or its inverse */ 0076 enum DiffDirection { 0077 Normal = 0 /**< the unchanged patch */ 0078 , 0079 Forward = 0 /**< the unchanged patch */ 0080 , 0081 Reverse = 1 /**< the inverse of the patch (i.e. a new patch which, when applied, undoes the old patch) */ 0082 }; 0083 0084 VcsDiff(); 0085 ~VcsDiff(); 0086 VcsDiff(VcsDiff &&rhs); 0087 0088 /** 0089 * @returns the source of the diff. 0090 */ 0091 QString diff() const; 0092 0093 /** @returns the base directory of the diff. */ 0094 QUrl baseDiff() const; 0095 0096 /** 0097 * Depth - number of directories to left-strip from paths in the patch - see "patch -p" 0098 * Defaults to 0 0099 */ 0100 uint depth() const; 0101 0102 /** Sets the base directory of the diff to the @p url */ 0103 void setBaseDiff(const QUrl &url); 0104 0105 /** Sets the depth of the diff to @p depth */ 0106 void setDepth(const uint depth); 0107 0108 /** Sets the diff source and parses it. 0109 * 0110 * @param diff the diff in unified diff format 0111 */ 0112 void setDiff(const QString &diff); 0113 0114 /** @returns whether or not there are changes in the diff */ 0115 bool isEmpty() const; 0116 0117 /** 0118 * Creates a standalone diff containing the differences in a given range. 0119 * 0120 * @returns a diff containing only the changes from the current diff 0121 * which are in the range startLine-endLine (in the diff text) 0122 * 0123 * @param startLine 0-based line number (in the diff) of the first line in the range 0124 * @param endLine 0-based line number (in the diff) of the last line in the range 0125 * @param dir if set to Reverse, the role of src and tgt are reversed, i.e. a diff is 0126 * generated which can be applied to the target to get the source. 0127 */ 0128 VcsDiff subDiff(const uint startLine, const uint endLine, DiffDirection dir = Normal) const; 0129 0130 /** 0131 * Creates a new standalone diff from a single hunk identified by a containing line. 0132 * 0133 * @returns a diff containing only the changes from hunk containing 0134 * the line the line 0135 * 0136 * @param line 0-based line number (in the diff) of the line in the hunk 0137 * @param dir if set to Reverse, the role of src and tgt are reversed, i.e. a diff is 0138 * generated which can be applied to the target to get the source. 0139 */ 0140 VcsDiff subDiffHunk(const uint line, DiffDirection dir = Normal) const; 0141 0142 /** 0143 * Maps a line position in the diff to a corresponding line position in the source file. 0144 * 0145 * @param line a 0-based line position in the diff 0146 * @returns the 0-based line position in the source file or -1 if no such position exists. 0147 */ 0148 int diffLineToSourceLine(const uint line) const; 0149 0150 /** 0151 * Maps a line position in the diff to a corresponding line position in the source file. 0152 * 0153 * @param line a 0-based line position in the diff 0154 * @returns the 0-based line position in the source file or -1 if no such position exists. 0155 */ 0156 int diffLineToTargetLine(const uint line) const; 0157 0158 private: 0159 std::unique_ptr<class VcsDiffPrivate> d; 0160 }; 0161 0162 // Helper, parses "123, 12" into ints 0163 std::pair<uint, uint> parseRange(const QString &range);