11import 'dart:io' ;
22import '../models/git_commit.dart' ;
33import '../models/changed_file.dart' ;
4+ import '../models/diff_result.dart' ;
45
56class GitService {
67 /// Check if the given path is a valid Git repository.
@@ -16,7 +17,7 @@ class GitService {
1617 }) async {
1718 final result = await Process .run ('git' , [
1819 'log' ,
19- '--format=%H||%h||%s||%an|| %aI' ,
20+ '--format=%H%x1F%h%x1F%s%x1F%an%x1F %aI' ,
2021 '-n' ,
2122 '$limit ' ,
2223 ], workingDirectory: projectPath);
@@ -73,4 +74,67 @@ class GitService {
7374 return allFiles.map ((path) => ChangedFile (relativePath: path)).toList ()
7475 ..sort ((a, b) => a.relativePath.compareTo (b.relativePath));
7576 }
77+
78+ /// Get the raw unified diff for a file between its base and new state.
79+ Future <DiffResult > getFileDiff (
80+ String projectPath,
81+ String filePath,
82+ String oldestCommit,
83+ String newestCommit,
84+ ) async {
85+ // get parent of oldest commit
86+ String ? baseCommit;
87+ final parentResult = await Process .run ('git' , [
88+ 'log' , '-1' , '--format=%P' , oldestCommit
89+ ], workingDirectory: projectPath);
90+
91+ if (parentResult.exitCode == 0 ) {
92+ final parents = (parentResult.stdout as String ).trim ().split (' ' );
93+ if (parents.isNotEmpty && parents.first.isNotEmpty) {
94+ baseCommit = parents.first;
95+ }
96+ }
97+
98+ String ? baseTime;
99+ if (baseCommit != null ) {
100+ final timeRes = await Process .run ('git' , [
101+ 'log' , '-1' , '--format=%aI' , baseCommit
102+ ], workingDirectory: projectPath);
103+ if (timeRes.exitCode == 0 ) {
104+ baseTime = (timeRes.stdout as String ).trim ();
105+ }
106+ }
107+
108+ String ? newTime;
109+ final newTimeRes = await Process .run ('git' , [
110+ 'log' , '-1' , '--format=%aI' , newestCommit
111+ ], workingDirectory: projectPath);
112+ if (newTimeRes.exitCode == 0 ) {
113+ newTime = (newTimeRes.stdout as String ).trim ();
114+ }
115+
116+ final diffArgs = [
117+ 'diff' ,
118+ if (baseCommit != null )
119+ '$baseCommit ..$newestCommit '
120+ else
121+ '4b825dc642cb6eb9a060e54bf8d69288fbee4904..$newestCommit ' ,
122+ '--' ,
123+ filePath
124+ ];
125+
126+ final diffRes = await Process .run ('git' , diffArgs, workingDirectory: projectPath);
127+ final diffText = diffRes.stdout as String ;
128+
129+ bool isNewFile = baseCommit == null || diffText.contains ('new file mode ' );
130+ bool isBinary = diffText.contains ('Binary files ' ) && diffText.contains (' differ' );
131+
132+ return DiffResult (
133+ diffText: diffText,
134+ baseCommitTime: baseTime,
135+ newCommitTime: newTime,
136+ isNewFile: isNewFile,
137+ isBinary: isBinary,
138+ );
139+ }
76140}
0 commit comments