File indexing completed on 2024-04-28 04:37:46
0001 /* 0002 SPDX-FileCopyrightText: 2007 Andreas Pakulat <apaku@gmx.de> 0003 SPDX-FileCopyrightText: 2007 Matthew Woehlke <mw_triad@users.sourceforge.net> 0004 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #ifndef KDEVPLATFORM_VCSDIFF_H 0009 #define KDEVPLATFORM_VCSDIFF_H 0010 0011 #include <QSharedDataPointer> 0012 #include <QtGlobal> 0013 #include <QMetaType> 0014 #include <QVector> 0015 0016 0017 #include "vcsexport.h" 0018 0019 class QUrl; 0020 class QString; 0021 0022 namespace KDevelop 0023 { 0024 0025 /** 0026 * A class representing a unified diff, possibly with 0027 * conflict markers. 0028 * 0029 * A diff is assumed to be a collection of hunks, where each hunk has the 0030 * following structure: 0031 * 0032 * METADATA 0033 * --- a/SOURCE_PATH 0034 * +++ b/TARGET_PATH 0035 * HUNK1 HEADER 0036 * HUNK1 CONTENT 0037 * [METADATA] 0038 * HUNK2 HEADER 0039 * HUNK2 CONTENT 0040 * ... 0041 * 0042 * METADATA are lines which start with anything except for a '+', '-' and ' '. 0043 * The path specifications may optionally precede a hunk and are assumed to 0044 * apply to all following hunks until a new path specification 0045 * is found. These indicate the files for which the diff is generated. 0046 * 0047 * Hunk Header 0048 * ------------ 0049 * 0050 * Each hunk header has the following form 0051 * 0052 * @@ -SRC_OFFSET[, SRC_CHANGES_COUNT] +TGT_OFFSET[, TGT_CHANGES_COUNT] @@ Heading 0053 * 0054 * where the SRC_OFFSET is a 1-based line index pointing to the source file where 0055 * the hunk applies and TGT_OFFSET is a 1-based line index pointing to the target 0056 * file where the hunk applies. The optional SRC_CHANGES_COUNTS (assumed to be 1 0057 * if not present) specifies the number of context lines plus the number of 0058 * deleted lines. Similarly, the optional TGT_CHANGES_COUNT specifies the 0059 * number of context lines plus the number of added lines. The Heading, used as a 0060 * visual aid for users, is supposed to show the line where the nearest enclosing 0061 * function scope of the hunk starts. 0062 * 0063 * Hunk Content 0064 * ------------ 0065 * 0066 * The hunk content is a collection of lines which starting with '+' (additions), 0067 * '-' (deletions) and ' ' (context lines; empty lines are also take to be context 0068 * lines). Additionally, a hunk may contain conflict markers which are of the form 0069 * 0070 * >>>>>>> our ref 0071 * our content 0072 * ... 0073 * ======= 0074 * their content 0075 * ... 0076 * <<<<<<< their ref 0077 * 0078 * and indicate unresolved conflicts. 0079 * 0080 */ 0081 class KDEVPLATFORMVCS_EXPORT VcsDiff 0082 { 0083 public: 0084 /* Used to represent a patch or its inverse */ 0085 enum DiffDirection { 0086 Normal = 0 /**< the unchanged patch */ 0087 , Foward = 0 /**< the unchanged patch */ 0088 , Reverse = 1 /**< the inverse of the patch (i.e. a new patch which, when applied, undoes the old patch) */ 0089 }; 0090 0091 VcsDiff(); 0092 virtual ~VcsDiff(); 0093 VcsDiff( const VcsDiff& ); 0094 0095 /** 0096 * @returns the source of the diff. 0097 */ 0098 QString diff() const; 0099 0100 /** @returns the base directory of the diff. */ 0101 QUrl baseDiff() const; 0102 0103 /** 0104 * Depth - number of directories to left-strip from paths in the patch - see "patch -p" 0105 * Defaults to 0 0106 */ 0107 uint depth() const; 0108 0109 /** Sets the base directory of the diff to the @p url */ 0110 void setBaseDiff(const QUrl& url); 0111 0112 /** Sets the depth of the diff to @p depth */ 0113 void setDepth(const uint depth); 0114 0115 /** Sets the diff source and parses it. 0116 * 0117 * @param diff the diff in unified diff format 0118 */ 0119 void setDiff( const QString& diff); 0120 0121 VcsDiff& operator=( const VcsDiff& rhs); 0122 0123 /** @returns whether or not there are changes in the diff */ 0124 bool isEmpty() const; 0125 0126 /** 0127 * Creates a standalone diff containing the differences in a given range. 0128 * 0129 * @returns a diff containing only the changes from the current diff 0130 * which are in the range startLine-endLine (in the diff text) 0131 * 0132 * @param startLine 0-based line number (in the diff) of the first line in the range 0133 * @param endLine 0-based line number (in the diff) of the last line in the range 0134 * @param dir if set to Reverse, the role of src and tgt are reversed, i.e. a diff is 0135 * generated which can be applied to the target to get the source. 0136 */ 0137 VcsDiff subDiff(const uint startLine, const uint endLine, DiffDirection dir = Normal) const; 0138 0139 /** 0140 * Creates a new standalone diff from a single hunk identified by a containing line. 0141 * 0142 * @returns a diff containing only the changes from hunk containing 0143 * the line the line 0144 * 0145 * @param line 0-based line number (in the diff) of the line in the hunk 0146 * @param dir if set to Reverse, the role of src and tgt are reversed, i.e. a diff is 0147 * generated which can be applied to the target to get the source. 0148 */ 0149 VcsDiff subDiffHunk(const uint line, DiffDirection dir = Normal) const; 0150 0151 /** 0152 * A struct representing a position in a source file. 0153 * 0154 * @note This should eventually be replaced with a @ref KDevelop::DocumentCursor, 0155 * which, however, currently cannot be used in this file. 0156 */ 0157 struct SourceLocation { 0158 /* Path to the source file (may be relative) */ 0159 QString path = {}; 0160 /* 0-based line number in the source file */ 0161 int line = -1; 0162 }; 0163 0164 /** 0165 * Maps a line position in the diff to a corresponding line position in the source file. 0166 * 0167 * @param line a 0-based line position in the diff 0168 * @returns a @ref SourceLocation whose path is the target file path (relative to diff root) 0169 * and line the 0-based line position in the target file or {"", -1} if no such 0170 * position exists. 0171 */ 0172 SourceLocation diffLineToSource (const uint line) const; 0173 0174 /** 0175 * Maps a line position in the diff to a corresponding line position in the target file. 0176 * 0177 * @param line a 0-based line position in the diff 0178 * @returns a @ref SourceLocation whose path is the source file path (relative to diff root) 0179 * and line the 0-based line position in the source file or {"", -1} if no such 0180 * position exists. 0181 */ 0182 SourceLocation diffLineToTarget (const uint line) const; 0183 0184 /** 0185 * Represents a pair of files which are compared 0186 */ 0187 struct FilePair { 0188 QString source; 0189 QString target; 0190 bool operator==(const FilePair p) const {return (source == p.source && target == p.target); } 0191 }; 0192 0193 /** 0194 * @returns a list of filename pairs that the patch applies to 0195 * 0196 * @note: Each file-pair is only listed once for each consecutive run 0197 * of hunks which apply to it. 0198 */ 0199 const QVector<FilePair> fileNames() const; 0200 0201 private: 0202 QSharedDataPointer<class VcsDiffPrivate> d; 0203 }; 0204 0205 } 0206 0207 Q_DECLARE_METATYPE( KDevelop::VcsDiff ) 0208 Q_DECLARE_TYPEINFO( KDevelop::VcsDiff, Q_MOVABLE_TYPE ); 0209 Q_DECLARE_TYPEINFO( KDevelop::VcsDiff::FilePair, Q_MOVABLE_TYPE ); 0210 0211 #endif 0212