mirror of
https://github.com/SkinnyMind/libgit2dart.git
synced 2025-05-04 20:29:08 -04:00
refactor(patch): initialize DiffHunk with all the information accessible immediately
This commit is contained in:
parent
28f08e308a
commit
77a34c3335
4 changed files with 167 additions and 149 deletions
|
@ -4,7 +4,6 @@ import 'package:ffi/ffi.dart';
|
||||||
import 'package:libgit2dart/libgit2dart.dart';
|
import 'package:libgit2dart/libgit2dart.dart';
|
||||||
import 'package:libgit2dart/src/bindings/diff.dart' as bindings;
|
import 'package:libgit2dart/src/bindings/diff.dart' as bindings;
|
||||||
import 'package:libgit2dart/src/bindings/libgit2_bindings.dart';
|
import 'package:libgit2dart/src/bindings/libgit2_bindings.dart';
|
||||||
import 'package:libgit2dart/src/bindings/patch.dart' as patch_bindings;
|
|
||||||
import 'package:libgit2dart/src/util.dart';
|
import 'package:libgit2dart/src/util.dart';
|
||||||
|
|
||||||
class Diff {
|
class Diff {
|
||||||
|
@ -602,112 +601,3 @@ final _statsFinalizer = Finalizer<Pointer<git_diff_stats>>(
|
||||||
(pointer) => bindings.statsFree(pointer),
|
(pointer) => bindings.statsFree(pointer),
|
||||||
);
|
);
|
||||||
// coverage:ignore-end
|
// coverage:ignore-end
|
||||||
|
|
||||||
class DiffHunk {
|
|
||||||
/// Initializes a new instance of [DiffHunk] class from provided
|
|
||||||
/// pointers to patch object and diff hunk object in memory and number of
|
|
||||||
/// lines in hunk.
|
|
||||||
const DiffHunk(
|
|
||||||
this._patchPointer,
|
|
||||||
this._diffHunkPointer,
|
|
||||||
this.linesCount,
|
|
||||||
this.index,
|
|
||||||
);
|
|
||||||
|
|
||||||
/// Pointer to memory address for allocated diff hunk object.
|
|
||||||
final Pointer<git_diff_hunk> _diffHunkPointer;
|
|
||||||
|
|
||||||
/// Pointer to memory address for allocated patch object.
|
|
||||||
final Pointer<git_patch> _patchPointer;
|
|
||||||
|
|
||||||
/// Number of total lines in this hunk.
|
|
||||||
final int linesCount;
|
|
||||||
|
|
||||||
/// Index of this hunk in the patch.
|
|
||||||
final int index;
|
|
||||||
|
|
||||||
/// Starting line number in 'old file'.
|
|
||||||
int get oldStart => _diffHunkPointer.ref.old_start;
|
|
||||||
|
|
||||||
/// Number of lines in 'old file'.
|
|
||||||
int get oldLines => _diffHunkPointer.ref.old_lines;
|
|
||||||
|
|
||||||
/// Starting line number in 'new file'.
|
|
||||||
int get newStart => _diffHunkPointer.ref.new_start;
|
|
||||||
|
|
||||||
/// Number of lines in 'new file'.
|
|
||||||
int get newLines => _diffHunkPointer.ref.new_lines;
|
|
||||||
|
|
||||||
/// Header of a hunk.
|
|
||||||
String get header {
|
|
||||||
final list = <int>[];
|
|
||||||
for (var i = 0; i < _diffHunkPointer.ref.header_len; i++) {
|
|
||||||
list.add(_diffHunkPointer.ref.header[i]);
|
|
||||||
}
|
|
||||||
return String.fromCharCodes(list);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// List of lines in a hunk of a patch.
|
|
||||||
List<DiffLine> get lines {
|
|
||||||
final lines = <DiffLine>[];
|
|
||||||
for (var i = 0; i < linesCount; i++) {
|
|
||||||
lines.add(
|
|
||||||
DiffLine(
|
|
||||||
patch_bindings.lines(
|
|
||||||
patchPointer: _patchPointer,
|
|
||||||
hunkIndex: index,
|
|
||||||
lineOfHunk: i,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return lines;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
String toString() {
|
|
||||||
return 'DiffHunk{linesCount: $linesCount, index: $index, '
|
|
||||||
'oldStart: $oldStart, oldLines: $oldLines, newStart: $newStart, '
|
|
||||||
'newLines: $newLines, header: $header}';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class DiffLine {
|
|
||||||
/// Initializes a new instance of [DiffLine] class from provided
|
|
||||||
/// pointer to diff line object in memory.
|
|
||||||
const DiffLine(this._diffLinePointer);
|
|
||||||
|
|
||||||
/// Pointer to memory address for allocated diff line object.
|
|
||||||
final Pointer<git_diff_line> _diffLinePointer;
|
|
||||||
|
|
||||||
/// Type of the line.
|
|
||||||
GitDiffLine get origin {
|
|
||||||
return GitDiffLine.values.singleWhere(
|
|
||||||
(e) => _diffLinePointer.ref.origin == e.value,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Line number in old file or -1 for added line.
|
|
||||||
int get oldLineNumber => _diffLinePointer.ref.old_lineno;
|
|
||||||
|
|
||||||
/// Line number in new file or -1 for deleted line.
|
|
||||||
int get newLineNumber => _diffLinePointer.ref.new_lineno;
|
|
||||||
|
|
||||||
/// Number of newline characters in content.
|
|
||||||
int get numLines => _diffLinePointer.ref.num_lines;
|
|
||||||
|
|
||||||
/// Offset in the original file to the content.
|
|
||||||
int get contentOffset => _diffLinePointer.ref.content_offset;
|
|
||||||
|
|
||||||
/// Content of the diff line.
|
|
||||||
String get content => _diffLinePointer.ref.content
|
|
||||||
.cast<Utf8>()
|
|
||||||
.toDartString(length: _diffLinePointer.ref.content_len);
|
|
||||||
|
|
||||||
@override
|
|
||||||
String toString() {
|
|
||||||
return 'DiffLine{oldLineNumber: $oldLineNumber, '
|
|
||||||
'newLineNumber: $newLineNumber, numLines: $numLines, '
|
|
||||||
'contentOffset: $contentOffset, content: $content}';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import 'dart:ffi';
|
import 'dart:ffi';
|
||||||
|
|
||||||
|
import 'package:ffi/ffi.dart';
|
||||||
import 'package:libgit2dart/libgit2dart.dart';
|
import 'package:libgit2dart/libgit2dart.dart';
|
||||||
import 'package:libgit2dart/src/bindings/libgit2_bindings.dart';
|
import 'package:libgit2dart/src/bindings/libgit2_bindings.dart';
|
||||||
import 'package:libgit2dart/src/bindings/patch.dart' as bindings;
|
import 'package:libgit2dart/src/bindings/patch.dart' as bindings;
|
||||||
|
@ -197,14 +198,49 @@ class Patch {
|
||||||
final length = bindings.numHunks(_patchPointer);
|
final length = bindings.numHunks(_patchPointer);
|
||||||
final hunks = <DiffHunk>[];
|
final hunks = <DiffHunk>[];
|
||||||
|
|
||||||
for (var i = 0; i < length; i++) {
|
for (var index = 0; index < length; index++) {
|
||||||
final hunk = bindings.hunk(patchPointer: _patchPointer, hunkIndex: i);
|
final hunk = bindings.hunk(patchPointer: _patchPointer, hunkIndex: index);
|
||||||
|
final hunkPointer = hunk['hunk']! as Pointer<git_diff_hunk>;
|
||||||
|
final linesCount = hunk['linesN']! as int;
|
||||||
|
|
||||||
|
final lines = <DiffLine>[];
|
||||||
|
for (var i = 0; i < linesCount; i++) {
|
||||||
|
final linePointer = bindings.lines(
|
||||||
|
patchPointer: _patchPointer,
|
||||||
|
hunkIndex: index,
|
||||||
|
lineOfHunk: i,
|
||||||
|
);
|
||||||
|
lines.add(
|
||||||
|
DiffLine._(
|
||||||
|
origin: GitDiffLine.values.singleWhere(
|
||||||
|
(e) => linePointer.ref.origin == e.value,
|
||||||
|
),
|
||||||
|
oldLineNumber: linePointer.ref.old_lineno,
|
||||||
|
newLineNumber: linePointer.ref.new_lineno,
|
||||||
|
numLines: linePointer.ref.num_lines,
|
||||||
|
contentOffset: linePointer.ref.content_offset,
|
||||||
|
content: linePointer.ref.content
|
||||||
|
.cast<Utf8>()
|
||||||
|
.toDartString(length: linePointer.ref.content_len),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
final intHeader = <int>[];
|
||||||
|
for (var i = 0; i < hunkPointer.ref.header_len; i++) {
|
||||||
|
intHeader.add(hunkPointer.ref.header[i]);
|
||||||
|
}
|
||||||
|
|
||||||
hunks.add(
|
hunks.add(
|
||||||
DiffHunk(
|
DiffHunk._(
|
||||||
_patchPointer,
|
linesCount: linesCount,
|
||||||
hunk['hunk']! as Pointer<git_diff_hunk>,
|
index: index,
|
||||||
hunk['linesN']! as int,
|
oldStart: hunkPointer.ref.old_start,
|
||||||
i,
|
oldLines: hunkPointer.ref.old_lines,
|
||||||
|
newStart: hunkPointer.ref.new_start,
|
||||||
|
newLines: hunkPointer.ref.new_lines,
|
||||||
|
header: String.fromCharCodes(intHeader),
|
||||||
|
lines: lines,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -251,3 +287,83 @@ class PatchStats {
|
||||||
'deletions: $deletions}';
|
'deletions: $deletions}';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class DiffHunk {
|
||||||
|
const DiffHunk._({
|
||||||
|
required this.linesCount,
|
||||||
|
required this.index,
|
||||||
|
required this.oldStart,
|
||||||
|
required this.oldLines,
|
||||||
|
required this.newStart,
|
||||||
|
required this.newLines,
|
||||||
|
required this.header,
|
||||||
|
required this.lines,
|
||||||
|
});
|
||||||
|
|
||||||
|
/// Number of total lines in this hunk.
|
||||||
|
final int linesCount;
|
||||||
|
|
||||||
|
/// Index of this hunk in the patch.
|
||||||
|
final int index;
|
||||||
|
|
||||||
|
/// Starting line number in 'old file'.
|
||||||
|
final int oldStart;
|
||||||
|
|
||||||
|
/// Number of lines in 'old file'.
|
||||||
|
final int oldLines;
|
||||||
|
|
||||||
|
/// Starting line number in 'new file'.
|
||||||
|
final int newStart;
|
||||||
|
|
||||||
|
/// Number of lines in 'new file'.
|
||||||
|
final int newLines;
|
||||||
|
|
||||||
|
/// Header of a hunk.
|
||||||
|
final String header;
|
||||||
|
|
||||||
|
/// List of lines in a hunk of a patch.
|
||||||
|
final List<DiffLine> lines;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'DiffHunk{linesCount: $linesCount, index: $index, '
|
||||||
|
'oldStart: $oldStart, oldLines: $oldLines, newStart: $newStart, '
|
||||||
|
'newLines: $newLines, header: $header}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DiffLine {
|
||||||
|
const DiffLine._({
|
||||||
|
required this.origin,
|
||||||
|
required this.oldLineNumber,
|
||||||
|
required this.newLineNumber,
|
||||||
|
required this.numLines,
|
||||||
|
required this.contentOffset,
|
||||||
|
required this.content,
|
||||||
|
});
|
||||||
|
|
||||||
|
/// Type of the line.
|
||||||
|
final GitDiffLine origin;
|
||||||
|
|
||||||
|
/// Line number in old file or -1 for added line.
|
||||||
|
final int oldLineNumber;
|
||||||
|
|
||||||
|
/// Line number in new file or -1 for deleted line.
|
||||||
|
final int newLineNumber;
|
||||||
|
|
||||||
|
/// Number of newline characters in content.
|
||||||
|
final int numLines;
|
||||||
|
|
||||||
|
/// Offset in the original file to the content.
|
||||||
|
final int contentOffset;
|
||||||
|
|
||||||
|
/// Content of the diff line.
|
||||||
|
final String content;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'DiffLine{oldLineNumber: $oldLineNumber, '
|
||||||
|
'newLineNumber: $newLineNumber, numLines: $numLines, '
|
||||||
|
'contentOffset: $contentOffset, content: $content}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -559,33 +559,6 @@ index e69de29..c217c63 100644
|
||||||
expect(Diff.parse(patchText).patch, patchText);
|
expect(Diff.parse(patchText).patch, patchText);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('returns hunks in a patch', () {
|
|
||||||
final patch = Patch.fromDiff(diff: Diff.parse(patchText), index: 0);
|
|
||||||
final hunk = patch.hunks[0];
|
|
||||||
|
|
||||||
expect(patch.hunks.length, 1);
|
|
||||||
expect(hunk.linesCount, 1);
|
|
||||||
expect(hunk.oldStart, 0);
|
|
||||||
expect(hunk.oldLines, 0);
|
|
||||||
expect(hunk.newStart, 1);
|
|
||||||
expect(hunk.newLines, 1);
|
|
||||||
expect(hunk.header, '@@ -0,0 +1 @@\n');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('returns lines in a hunk', () {
|
|
||||||
final patch = Patch.fromDiff(diff: Diff.parse(patchText), index: 0);
|
|
||||||
final hunk = patch.hunks[0];
|
|
||||||
final line = hunk.lines[0];
|
|
||||||
|
|
||||||
expect(hunk.lines.length, 1);
|
|
||||||
expect(line.origin, GitDiffLine.addition);
|
|
||||||
expect(line.oldLineNumber, -1);
|
|
||||||
expect(line.newLineNumber, 1);
|
|
||||||
expect(line.numLines, 1);
|
|
||||||
expect(line.contentOffset, 155);
|
|
||||||
expect(line.content, 'Modified content\n');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('manually releases allocated memory', () {
|
test('manually releases allocated memory', () {
|
||||||
final diff = Diff.parse(patchText);
|
final diff = Diff.parse(patchText);
|
||||||
expect(() => diff.free(), returnsNormally);
|
expect(() => diff.free(), returnsNormally);
|
||||||
|
@ -597,8 +570,8 @@ index e69de29..c217c63 100644
|
||||||
});
|
});
|
||||||
|
|
||||||
test(
|
test(
|
||||||
'returns string representation of Diff, DiffDelta, DiffFile, '
|
'returns string representation of Diff, DiffDelta, DiffFile '
|
||||||
'DiffHunk, DiffLine and DiffStats objects', () {
|
' and DiffStats objects', () {
|
||||||
final diff = Diff.parse(patchText);
|
final diff = Diff.parse(patchText);
|
||||||
final patch = Patch.fromDiff(diff: diff, index: 0);
|
final patch = Patch.fromDiff(diff: diff, index: 0);
|
||||||
final stats = diff.stats;
|
final stats = diff.stats;
|
||||||
|
@ -606,8 +579,6 @@ index e69de29..c217c63 100644
|
||||||
expect(diff.toString(), contains('Diff{'));
|
expect(diff.toString(), contains('Diff{'));
|
||||||
expect(patch.delta.toString(), contains('DiffDelta{'));
|
expect(patch.delta.toString(), contains('DiffDelta{'));
|
||||||
expect(patch.delta.oldFile.toString(), contains('DiffFile{'));
|
expect(patch.delta.oldFile.toString(), contains('DiffFile{'));
|
||||||
expect(patch.hunks[0].toString(), contains('DiffHunk{'));
|
|
||||||
expect(patch.hunks[0].lines[0].toString(), contains('DiffLine{'));
|
|
||||||
expect(stats.toString(), contains('DiffStats{'));
|
expect(stats.toString(), contains('DiffStats{'));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -155,6 +155,43 @@ index e69de29..0000000
|
||||||
expect(() => Patch(nullptr).text, throwsA(isA<LibGit2Error>()));
|
expect(() => Patch(nullptr).text, throwsA(isA<LibGit2Error>()));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('returns hunks in a patch', () {
|
||||||
|
final patch = Patch.fromBuffers(
|
||||||
|
oldBuffer: oldBuffer,
|
||||||
|
newBuffer: newBuffer,
|
||||||
|
oldBufferPath: path,
|
||||||
|
newBufferPath: path,
|
||||||
|
);
|
||||||
|
final hunk = patch.hunks[0];
|
||||||
|
|
||||||
|
expect(patch.hunks.length, 1);
|
||||||
|
expect(hunk.linesCount, 1);
|
||||||
|
expect(hunk.oldStart, 0);
|
||||||
|
expect(hunk.oldLines, 0);
|
||||||
|
expect(hunk.newStart, 1);
|
||||||
|
expect(hunk.newLines, 1);
|
||||||
|
expect(hunk.header, '@@ -0,0 +1 @@\n');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('returns lines in a hunk', () {
|
||||||
|
final patch = Patch.fromBuffers(
|
||||||
|
oldBuffer: oldBuffer,
|
||||||
|
newBuffer: newBuffer,
|
||||||
|
oldBufferPath: path,
|
||||||
|
newBufferPath: path,
|
||||||
|
);
|
||||||
|
final hunk = patch.hunks[0];
|
||||||
|
final line = hunk.lines[0];
|
||||||
|
|
||||||
|
expect(hunk.lines.length, 1);
|
||||||
|
expect(line.origin, GitDiffLine.addition);
|
||||||
|
expect(line.oldLineNumber, -1);
|
||||||
|
expect(line.newLineNumber, 1);
|
||||||
|
expect(line.numLines, 1);
|
||||||
|
expect(line.contentOffset, 0);
|
||||||
|
expect(line.content, 'Feature edit\n');
|
||||||
|
});
|
||||||
|
|
||||||
test('returns line counts of each type in a patch', () {
|
test('returns line counts of each type in a patch', () {
|
||||||
final patch = Patch.fromBuffers(
|
final patch = Patch.fromBuffers(
|
||||||
oldBuffer: oldBuffer,
|
oldBuffer: oldBuffer,
|
||||||
|
@ -180,7 +217,9 @@ index e69de29..0000000
|
||||||
expect(() => patch.free(), returnsNormally);
|
expect(() => patch.free(), returnsNormally);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('returns string representation of Patch object', () {
|
test(
|
||||||
|
'returns string representation of Patch, DiffHunk and DiffLine objects',
|
||||||
|
() {
|
||||||
final patch = Patch.fromBuffers(
|
final patch = Patch.fromBuffers(
|
||||||
oldBuffer: oldBuffer,
|
oldBuffer: oldBuffer,
|
||||||
newBuffer: newBuffer,
|
newBuffer: newBuffer,
|
||||||
|
@ -189,6 +228,8 @@ index e69de29..0000000
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(patch.toString(), contains('Patch{'));
|
expect(patch.toString(), contains('Patch{'));
|
||||||
|
expect(patch.hunks[0].toString(), contains('DiffHunk{'));
|
||||||
|
expect(patch.hunks[0].lines[0].toString(), contains('DiffLine{'));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue