<?php
class
IDF_Diff
{
public
$repo
=
''
;
public
$diff
=
''
;
protected
$lines
=
array
();
public
$files
=
array
();
public
function
__construct(
$diff
,
$repo
=
''
)
{
$this
->repo =
$repo
;
$this
->diff =
$diff
;
$this
->lines = preg_split(
"/\015\012|\015|\012/"
,
$diff
);
}
public
function
parse()
{
$current_file
=
''
;
$current_chunk
= 0;
$lline
= 0;
$rline
= 0;
$files
=
array
();
foreach
(
$this
->lines
as
$line
) {
if
(0 ===
strpos
(
$line
,
'diff --git a'
)) {
$current_file
= self::getFile(
$line
);
$files
[
$current_file
] =
array
();
$files
[
$current_file
][
'chunks'
] =
array
();
$files
[
$current_file
][
'chunks_def'
] =
array
();
$current_chunk
= 0;
continue
;
}
if
(0 ===
strpos
(
$line
,
'Index: '
)) {
$current_file
= self::getSvnFile(
$line
);
$files
[
$current_file
] =
array
();
$files
[
$current_file
][
'chunks'
] =
array
();
$files
[
$current_file
][
'chunks_def'
] =
array
();
$current_chunk
= 0;
continue
;
}
if
(0 ===
strpos
(
$line
,
'@@ '
)) {
$files
[
$current_file
][
'chunks_def'
][] = self::getChunk(
$line
);
$files
[
$current_file
][
'chunks'
][] =
array
();
$current_chunk
++;
$lline
=
$files
[
$current_file
][
'chunks_def'
][
$current_chunk
-1][0][0];
$rline
=
$files
[
$current_file
][
'chunks_def'
][
$current_chunk
-1][1][0];
continue
;
}
if
(0 ===
strpos
(
$line
,
'---'
)
or
0 ===
strpos
(
$line
,
'+++'
)) {
continue
;
}
if
(0 ===
strpos
(
$line
,
'-'
)) {
$files
[
$current_file
][
'chunks'
][
$current_chunk
-1][] =
array
(
$lline
,
''
,
substr
(
$line
, 1));
$lline
++;
continue
;
}
if
(0 ===
strpos
(
$line
,
'+'
)) {
$files
[
$current_file
][
'chunks'
][
$current_chunk
-1][] =
array
(
''
,
$rline
,
substr
(
$line
, 1));
$rline
++;
continue
;
}
if
(0 ===
strpos
(
$line
,
' '
)) {
$files
[
$current_file
][
'chunks'
][
$current_chunk
-1][] =
array
(
$lline
,
$rline
,
substr
(
$line
, 1));
$rline
++;
$lline
++;
continue
;
}
}
$this
->files =
$files
;
return
$files
;
}
public
static
function
getFile(
$line
)
{
$line
=
substr
(trim(
$line
), 10);
$n
= (int)
strlen
(
$line
)/2;
return
trim(
substr
(
$line
, 3,
$n
-3));
}
public
static
function
getSvnFile(
$line
)
{
return
substr
(trim(
$line
), 7);
}
public
function
as_html()
{
$out
=
''
;
foreach
(
$this
->files
as
$filename
=>
$file
) {
$pretty
=
''
;
$fileinfo
= IDF_Views_Source::getMimeType(
$filename
);
if
(IDF_Views_Source::isSupportedExtension(
$fileinfo
[2])) {
$pretty
=
' prettyprint'
;
}
$out
.=
"\n"
.
'<table class="diff" summary="">'
.
"\n"
;
$out
.=
'<tr id="diff-'
.md5(
$filename
).
'"><th colspan="3">'
.Pluf_esc(
$filename
).
'</th></tr>'
.
"\n"
;
$cc
= 1;
foreach
(
$file
[
'chunks'
]
as
$chunk
) {
foreach
(
$chunk
as
$line
) {
if
(
$line
[0]
and
$line
[1]) {
$class
=
'diff-c'
;
}
elseif
(
$line
[0]) {
$class
=
'diff-r'
;
}
else
{
$class
=
'diff-a'
;
}
$line_content
= self::padLine(Pluf_esc(
$line
[2]));
$out
.= sprintf(
'<tr class="diff-line"><td class="diff-lc">%s</td><td class="diff-lc">%s</td><td class="%s%s mono">%s</td></tr>'
.
"\n"
,
$line
[0],
$line
[1],
$class
,
$pretty
,
$line_content
);
}
if
(
count
(
$file
[
'chunks'
]) >
$cc
)
$out
.=
'<tr class="diff-next"><td>...</td><td>...</td><td> </td></tr>'
.
"\n"
;
$cc
++;
}
$out
.=
'</table>'
;
}
return
Pluf_Template::markSafe(
$out
);
}
public
static
function
padLine(
$line
)
{
$n
=
strlen
(
$line
);
for
(
$i
=0;
$i
<
$n
;
$i
++) {
if
(
substr
(
$line
,
$i
, 1) !=
' '
) {
break
;
}
}
return
str_repeat
(
' '
,
$i
).
substr
(
$line
,
$i
);
}
public
static
function
getChunk(
$line
)
{
$elts
= split(
' '
,
$line
);
$res
=
array
();
for
(
$i
=1;
$i
<3;
$i
++) {
$res
[] = split(
','
, trim(
substr
(
$elts
[
$i
], 1)));
}
return
$res
;
}
}