Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
G
git2
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
lvzhengyang
git2
Commits
5e96f316
Commit
5e96f316
authored
Aug 08, 2013
by
Ben Straub
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1738 from libgit2/diff-patch-content-size
Add API for getting at git_diff_patch->content_size
parents
bf145a6a
eb1c1707
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
186 additions
and
67 deletions
+186
-67
include/git2/diff.h
+23
-1
src/diff.h
+7
-0
src/diff_patch.c
+51
-6
src/diff_print.c
+66
-40
tests-clar/diff/patch.c
+39
-20
No files found.
include/git2/diff.h
View file @
5e96f316
...
...
@@ -391,7 +391,7 @@ typedef enum {
*/
GIT_DIFF_LINE_FILE_HDR
=
'F'
,
GIT_DIFF_LINE_HUNK_HDR
=
'H'
,
GIT_DIFF_LINE_BINARY
=
'B'
GIT_DIFF_LINE_BINARY
=
'B'
/**< For "Binary files x and y differ" */
}
git_diff_line_t
;
/**
...
...
@@ -943,6 +943,28 @@ GIT_EXTERN(int) git_diff_patch_get_line_in_hunk(
size_t
line_of_hunk
);
/**
* Look up size of patch diff data in bytes
*
* This returns the raw size of the patch data. This only includes the
* actual data from the lines of the diff, not the file or hunk headers.
*
* If you pass `include_context` as true (non-zero), this will be the size
* of all of the diff output; if you pass it as false (zero), this will
* only include the actual changed lines (as if `context_lines` was 0).
*
* @param patch A git_diff_patch representing changes to one file
* @param include_context Include context lines in size if non-zero
* @param include_hunk_headers Include hunk header lines if non-zero
* @param include_file_headers Include file header lines if non-zero
* @return The number of bytes of data
*/
GIT_EXTERN
(
size_t
)
git_diff_patch_size
(
git_diff_patch
*
patch
,
int
include_context
,
int
include_hunk_headers
,
int
include_file_headers
);
/**
* Serialize the patch to text via callback.
*
* Returning a non-zero value from the callback will terminate the iteration
...
...
src/diff.h
View file @
5e96f316
...
...
@@ -82,6 +82,13 @@ extern const char *git_diff_delta__path(const git_diff_delta *delta);
extern
bool
git_diff_delta__should_skip
(
const
git_diff_options
*
opts
,
const
git_diff_delta
*
delta
);
extern
int
git_diff_delta__format_file_header
(
git_buf
*
out
,
const
git_diff_delta
*
delta
,
const
char
*
oldpfx
,
const
char
*
newpfx
,
int
oid_strlen
);
extern
int
git_diff__oid_for_file
(
git_repository
*
,
const
char
*
,
uint16_t
,
git_off_t
,
git_oid
*
);
...
...
src/diff_patch.c
View file @
5e96f316
...
...
@@ -42,7 +42,7 @@ struct git_diff_patch {
git_array_t
(
diff_patch_hunk
)
hunks
;
git_array_t
(
diff_patch_line
)
lines
;
size_t
oldno
,
newno
;
size_t
content_size
;
size_t
content_size
,
context_size
,
header_size
;
git_pool
flattened
;
};
...
...
@@ -810,6 +810,39 @@ notfound:
return
diff_error_outofrange
(
thing
);
}
size_t
git_diff_patch_size
(
git_diff_patch
*
patch
,
int
include_context
,
int
include_hunk_headers
,
int
include_file_headers
)
{
size_t
out
;
assert
(
patch
);
out
=
patch
->
content_size
;
if
(
!
include_context
)
out
-=
patch
->
context_size
;
if
(
include_hunk_headers
)
out
+=
patch
->
header_size
;
if
(
include_file_headers
)
{
git_buf
file_header
=
GIT_BUF_INIT
;
if
(
git_diff_delta__format_file_header
(
&
file_header
,
patch
->
delta
,
NULL
,
NULL
,
0
)
<
0
)
giterr_clear
();
else
out
+=
git_buf_len
(
&
file_header
);
git_buf_free
(
&
file_header
);
}
return
out
;
}
git_diff_list
*
git_diff_patch__diff
(
git_diff_patch
*
patch
)
{
return
patch
->
diff
;
...
...
@@ -904,6 +937,8 @@ static int diff_patch_hunk_cb(
hunk
->
header
[
header_len
]
=
'\0'
;
hunk
->
header_len
=
header_len
;
patch
->
header_size
+=
header_len
;
hunk
->
line_start
=
git_array_size
(
patch
->
lines
);
hunk
->
line_count
=
0
;
...
...
@@ -924,6 +959,7 @@ static int diff_patch_line_cb(
git_diff_patch
*
patch
=
payload
;
diff_patch_hunk
*
hunk
;
diff_patch_line
*
line
;
const
char
*
content_end
=
content
+
content_len
;
GIT_UNUSED
(
delta
);
GIT_UNUSED
(
range
);
...
...
@@ -938,34 +974,43 @@ static int diff_patch_line_cb(
line
->
len
=
content_len
;
line
->
origin
=
line_origin
;
patch
->
content_size
+=
content_len
;
/* do some bookkeeping so we can provide old/new line numbers */
for
(
line
->
lines
=
0
;
content_len
>
0
;
--
content_len
)
{
line
->
lines
=
0
;
while
(
content
<
content_end
)
if
(
*
content
++
==
'\n'
)
++
line
->
lines
;
}
patch
->
content_size
+=
content_len
;
switch
(
line_origin
)
{
case
GIT_DIFF_LINE_ADDITION
:
patch
->
content_size
+=
1
;
case
GIT_DIFF_LINE_DEL_EOFNL
:
line
->
oldno
=
-
1
;
line
->
newno
=
patch
->
newno
;
patch
->
newno
+=
line
->
lines
;
break
;
case
GIT_DIFF_LINE_DELETION
:
patch
->
content_size
+=
1
;
case
GIT_DIFF_LINE_ADD_EOFNL
:
line
->
oldno
=
patch
->
oldno
;
line
->
newno
=
-
1
;
patch
->
oldno
+=
line
->
lines
;
break
;
default:
case
GIT_DIFF_LINE_CONTEXT
:
patch
->
content_size
+=
1
;
patch
->
context_size
+=
1
;
case
GIT_DIFF_LINE_CONTEXT_EOFNL
:
patch
->
context_size
+=
content_len
;
line
->
oldno
=
patch
->
oldno
;
line
->
newno
=
patch
->
newno
;
patch
->
oldno
+=
line
->
lines
;
patch
->
newno
+=
line
->
lines
;
break
;
default:
assert
(
false
);
break
;
}
hunk
->
line_count
++
;
...
...
src/diff_print.c
View file @
5e96f316
...
...
@@ -98,12 +98,12 @@ static int diff_print_one_compact(
if
(
delta
->
old_file
.
path
!=
delta
->
new_file
.
path
&&
strcomp
(
delta
->
old_file
.
path
,
delta
->
new_file
.
path
)
!=
0
)
git_buf_printf
(
out
,
"%c
\t
%s%c
->
%s%c
\n
"
,
code
,
git_buf_printf
(
out
,
"%c
\t
%s%c %s%c
\n
"
,
code
,
delta
->
old_file
.
path
,
old_suffix
,
delta
->
new_file
.
path
,
new_suffix
);
else
if
(
delta
->
old_file
.
mode
!=
delta
->
new_file
.
mode
&&
delta
->
old_file
.
mode
!=
0
&&
delta
->
new_file
.
mode
!=
0
)
git_buf_printf
(
out
,
"%c
\t
%s%c
(%o -> %o)
\n
"
,
code
,
delta
->
old_file
.
path
,
new_suffix
,
delta
->
old_file
.
mode
,
delta
->
new_file
.
mode
);
git_buf_printf
(
out
,
"%c
\t
%s%c
%s%c
\n
"
,
code
,
delta
->
old_file
.
path
,
old_suffix
,
delta
->
new_file
.
path
,
new_suffix
);
else
if
(
old_suffix
!=
' '
)
git_buf_printf
(
out
,
"%c
\t
%s%c
\n
"
,
code
,
delta
->
old_file
.
path
,
old_suffix
);
else
...
...
@@ -198,13 +198,13 @@ int git_diff_print_raw(
return
error
;
}
static
int
diff_print_oid_range
(
diff_print_info
*
pi
,
const
git_diff_delta
*
delta
)
static
int
diff_print_oid_range
(
git_buf
*
out
,
const
git_diff_delta
*
delta
,
int
oid_strlen
)
{
git_buf
*
out
=
pi
->
buf
;
char
start_oid
[
GIT_OID_HEXSZ
+
1
],
end_oid
[
GIT_OID_HEXSZ
+
1
];
git_oid_tostr
(
start_oid
,
pi
->
oid_strlen
,
&
delta
->
old_file
.
oid
);
git_oid_tostr
(
end_oid
,
pi
->
oid_strlen
,
&
delta
->
new_file
.
oid
);
git_oid_tostr
(
start_oid
,
oid_strlen
,
&
delta
->
old_file
.
oid
);
git_oid_tostr
(
end_oid
,
oid_strlen
,
&
delta
->
new_file
.
oid
);
/* TODO: Match git diff more closely */
if
(
delta
->
old_file
.
mode
==
delta
->
new_file
.
mode
)
{
...
...
@@ -228,52 +228,78 @@ static int diff_print_oid_range(diff_print_info *pi, const git_diff_delta *delta
return
0
;
}
static
int
diff_print_patch_file
(
const
git_diff_delta
*
delta
,
float
progress
,
void
*
data
)
static
int
diff_delta_format_with_paths
(
git_buf
*
out
,
const
git_diff_delta
*
delta
,
const
char
*
oldpfx
,
const
char
*
newpfx
,
const
char
*
template
)
{
diff_print_info
*
pi
=
data
;
const
char
*
oldpfx
=
pi
->
diff
?
pi
->
diff
->
opts
.
old_prefix
:
NULL
;
const
char
*
oldpath
=
delta
->
old_file
.
path
;
const
char
*
newpfx
=
pi
->
diff
?
pi
->
diff
->
opts
.
new_prefix
:
NULL
;
const
char
*
newpath
=
delta
->
new_file
.
path
;
uint32_t
opts_flags
=
pi
->
diff
?
pi
->
diff
->
opts
.
flags
:
GIT_DIFF_NORMAL
;
GIT_UNUSED
(
progress
);
if
(
git_oid_iszero
(
&
delta
->
old_file
.
oid
))
{
oldpfx
=
""
;
oldpath
=
"/dev/null"
;
}
if
(
git_oid_iszero
(
&
delta
->
new_file
.
oid
))
{
newpfx
=
""
;
newpath
=
"/dev/null"
;
}
if
(
S_ISDIR
(
delta
->
new_file
.
mode
)
||
delta
->
status
==
GIT_DELTA_UNMODIFIED
||
delta
->
status
==
GIT_DELTA_IGNORED
||
(
delta
->
status
==
GIT_DELTA_UNTRACKED
&&
(
opts_flags
&
GIT_DIFF_INCLUDE_UNTRACKED_CONTENT
)
==
0
))
return
0
;
return
git_buf_printf
(
out
,
template
,
oldpfx
,
oldpath
,
newpfx
,
newpath
);
}
int
git_diff_delta__format_file_header
(
git_buf
*
out
,
const
git_diff_delta
*
delta
,
const
char
*
oldpfx
,
const
char
*
newpfx
,
int
oid_strlen
)
{
if
(
!
oldpfx
)
oldpfx
=
DIFF_OLD_PREFIX_DEFAULT
;
if
(
!
newpfx
)
newpfx
=
DIFF_NEW_PREFIX_DEFAULT
;
if
(
!
oid_strlen
)
oid_strlen
=
GIT_ABBREV_DEFAULT
+
1
;
git_buf_clear
(
pi
->
buf
);
git_buf_printf
(
pi
->
buf
,
"diff --git %s%s %s%s
\n
"
,
git_buf_clear
(
out
);
git_buf_printf
(
out
,
"diff --git %s%s %s%s
\n
"
,
oldpfx
,
delta
->
old_file
.
path
,
newpfx
,
delta
->
new_file
.
path
);
if
(
diff_print_oid_range
(
pi
,
delta
)
<
0
)
if
(
diff_print_oid_range
(
out
,
delta
,
oid_strlen
)
<
0
)
return
-
1
;
if
(
git_oid_iszero
(
&
delta
->
old_file
.
oid
))
{
oldpfx
=
""
;
oldpath
=
"/dev/null"
;
}
if
(
git_oid_iszero
(
&
delta
->
new_file
.
oid
))
{
newpfx
=
""
;
newpath
=
"/dev/null"
;
}
if
((
delta
->
flags
&
GIT_DIFF_FLAG_BINARY
)
==
0
)
diff_delta_format_with_paths
(
out
,
delta
,
oldpfx
,
newpfx
,
"--- %s%s
\n
+++ %s%s
\n
"
);
if
((
delta
->
flags
&
GIT_DIFF_FLAG_BINARY
)
==
0
)
{
git_buf_printf
(
pi
->
buf
,
"--- %s%s
\n
"
,
oldpfx
,
oldpath
);
git_buf_printf
(
pi
->
buf
,
"+++ %s%s
\n
"
,
newpfx
,
newpath
);
}
return
git_buf_oom
(
out
)
?
-
1
:
0
;
}
if
(
git_buf_oom
(
pi
->
buf
))
static
int
diff_print_patch_file
(
const
git_diff_delta
*
delta
,
float
progress
,
void
*
data
)
{
diff_print_info
*
pi
=
data
;
const
char
*
oldpfx
=
pi
->
diff
?
pi
->
diff
->
opts
.
old_prefix
:
DIFF_OLD_PREFIX_DEFAULT
;
const
char
*
newpfx
=
pi
->
diff
?
pi
->
diff
->
opts
.
new_prefix
:
DIFF_NEW_PREFIX_DEFAULT
;
uint32_t
opts_flags
=
pi
->
diff
?
pi
->
diff
->
opts
.
flags
:
GIT_DIFF_NORMAL
;
GIT_UNUSED
(
progress
);
if
(
S_ISDIR
(
delta
->
new_file
.
mode
)
||
delta
->
status
==
GIT_DELTA_UNMODIFIED
||
delta
->
status
==
GIT_DELTA_IGNORED
||
(
delta
->
status
==
GIT_DELTA_UNTRACKED
&&
(
opts_flags
&
GIT_DIFF_INCLUDE_UNTRACKED_CONTENT
)
==
0
))
return
0
;
if
(
git_diff_delta__format_file_header
(
pi
->
buf
,
delta
,
oldpfx
,
newpfx
,
pi
->
oid_strlen
)
<
0
)
return
-
1
;
if
(
pi
->
print_cb
(
delta
,
NULL
,
GIT_DIFF_LINE_FILE_HDR
,
...
...
@@ -284,10 +310,10 @@ static int diff_print_patch_file(
return
0
;
git_buf_clear
(
pi
->
buf
);
git_buf_printf
(
pi
->
buf
,
"Binary files %s%s and %s%s differ
\n
"
,
oldpfx
,
oldpath
,
newpfx
,
newpath
);
if
(
git_buf_oom
(
pi
->
buf
)
)
if
(
diff_delta_format_with_paths
(
pi
->
buf
,
delta
,
oldpfx
,
newpfx
,
"Binary files %s%s and %s%s differ
\n
"
)
<
0
)
return
-
1
;
if
(
pi
->
print_cb
(
delta
,
NULL
,
GIT_DIFF_LINE_BINARY
,
...
...
tests-clar/diff/patch.c
View file @
5e96f316
...
...
@@ -128,6 +128,11 @@ void test_diff_patch__to_string(void)
cl_assert_equal_s
(
expected
,
text
);
cl_assert_equal_sz
(
31
,
git_diff_patch_size
(
patch
,
0
,
0
,
0
));
cl_assert_equal_sz
(
31
,
git_diff_patch_size
(
patch
,
1
,
0
,
0
));
cl_assert_equal_sz
(
31
+
16
,
git_diff_patch_size
(
patch
,
1
,
1
,
0
));
cl_assert_equal_sz
(
strlen
(
expected
),
git_diff_patch_size
(
patch
,
1
,
1
,
1
));
git__free
(
text
);
git_diff_patch_free
(
patch
);
git_diff_list_free
(
diff
);
...
...
@@ -408,7 +413,7 @@ void test_diff_patch__hunks_have_correct_line_numbers(void)
static
void
check_single_patch_stats
(
git_repository
*
repo
,
size_t
hunks
,
size_t
adds
,
size_t
dels
,
size_t
ctxt
,
size_t
adds
,
size_t
dels
,
size_t
ctxt
,
size_t
*
sizes
,
const
char
*
expected
)
{
git_diff_list
*
diff
;
...
...
@@ -437,6 +442,18 @@ static void check_single_patch_stats(
cl_git_pass
(
git_diff_patch_to_str
(
&
text
,
patch
));
cl_assert_equal_s
(
expected
,
text
);
git__free
(
text
);
cl_assert_equal_sz
(
strlen
(
expected
),
git_diff_patch_size
(
patch
,
1
,
1
,
1
));
}
if
(
sizes
)
{
if
(
sizes
[
0
])
cl_assert_equal_sz
(
sizes
[
0
],
git_diff_patch_size
(
patch
,
0
,
0
,
0
));
if
(
sizes
[
1
])
cl_assert_equal_sz
(
sizes
[
1
],
git_diff_patch_size
(
patch
,
1
,
0
,
0
));
if
(
sizes
[
2
])
cl_assert_equal_sz
(
sizes
[
2
],
git_diff_patch_size
(
patch
,
1
,
1
,
0
));
}
/* walk lines in hunk with basic sanity checks */
...
...
@@ -481,6 +498,23 @@ void test_diff_patch__line_counts_with_eofnl(void)
git_buf
content
=
GIT_BUF_INIT
;
const
char
*
end
;
git_index
*
index
;
const
char
*
expected
=
/* below is pasted output of 'git diff' with fn context removed */
"diff --git a/songof7cities.txt b/songof7cities.txt
\n
"
"index 378a7d9..3d0154e 100644
\n
"
"--- a/songof7cities.txt
\n
"
"+++ b/songof7cities.txt
\n
"
"@@ -42,7 +42,7 @@ With peoples undefeated of the dark, enduring blood.
\n
"
"
\n
"
" To the sound of trumpets shall their seed restore my Cities
\n
"
" Wealthy and well-weaponed, that once more may I behold
\n
"
"-All the world go softly when it walks before my Cities,
\n
"
"+#All the world go softly when it walks before my Cities,
\n
"
" And the horses and the chariots fleeing from them as of old!
\n
"
"
\n
"
" -- Rudyard Kipling
\n
"
"
\\
No newline at end of file
\n
"
;
size_t
expected_sizes
[
3
]
=
{
115
,
119
+
115
+
114
,
119
+
115
+
114
+
71
};
g_repo
=
cl_git_sandbox_init
(
"renames"
);
...
...
@@ -495,14 +529,14 @@ void test_diff_patch__line_counts_with_eofnl(void)
git_buf_consume
(
&
content
,
end
);
cl_git_rewritefile
(
"renames/songof7cities.txt"
,
content
.
ptr
);
check_single_patch_stats
(
g_repo
,
1
,
0
,
1
,
3
,
NULL
);
check_single_patch_stats
(
g_repo
,
1
,
0
,
1
,
3
,
NULL
,
NULL
);
/* remove trailing whitespace */
git_buf_rtrim
(
&
content
);
cl_git_rewritefile
(
"renames/songof7cities.txt"
,
content
.
ptr
);
check_single_patch_stats
(
g_repo
,
2
,
1
,
2
,
6
,
NULL
);
check_single_patch_stats
(
g_repo
,
2
,
1
,
2
,
6
,
NULL
,
NULL
);
/* add trailing whitespace */
...
...
@@ -514,7 +548,7 @@ void test_diff_patch__line_counts_with_eofnl(void)
cl_git_pass
(
git_buf_putc
(
&
content
,
'\n'
));
cl_git_rewritefile
(
"renames/songof7cities.txt"
,
content
.
ptr
);
check_single_patch_stats
(
g_repo
,
1
,
1
,
1
,
3
,
NULL
);
check_single_patch_stats
(
g_repo
,
1
,
1
,
1
,
3
,
NULL
,
NULL
);
/* no trailing whitespace as context line */
...
...
@@ -537,22 +571,7 @@ void test_diff_patch__line_counts_with_eofnl(void)
cl_git_rewritefile
(
"renames/songof7cities.txt"
,
content
.
ptr
);
check_single_patch_stats
(
g_repo
,
1
,
1
,
1
,
6
,
/* below is pasted output of 'git diff' with fn context removed */
"diff --git a/songof7cities.txt b/songof7cities.txt
\n
"
"index 378a7d9..3d0154e 100644
\n
"
"--- a/songof7cities.txt
\n
"
"+++ b/songof7cities.txt
\n
"
"@@ -42,7 +42,7 @@ With peoples undefeated of the dark, enduring blood.
\n
"
"
\n
"
" To the sound of trumpets shall their seed restore my Cities
\n
"
" Wealthy and well-weaponed, that once more may I behold
\n
"
"-All the world go softly when it walks before my Cities,
\n
"
"+#All the world go softly when it walks before my Cities,
\n
"
" And the horses and the chariots fleeing from them as of old!
\n
"
"
\n
"
" -- Rudyard Kipling
\n
"
"
\\
No newline at end of file
\n
"
);
g_repo
,
1
,
1
,
1
,
6
,
expected_sizes
,
expected
);
git_buf_free
(
&
content
);
git_config_free
(
cfg
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment