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
d8cc1fb6
Commit
d8cc1fb6
authored
Apr 11, 2014
by
Jacques Germishuys
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Introduce git_diff_format_email and git_diff_commit_as_email
parent
360314c9
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
295 additions
and
0 deletions
+295
-0
include/git2/diff.h
+88
-0
src/diff.c
+204
-0
src/diff.h
+3
-0
tests/diff/format_email.c
+0
-0
No files found.
include/git2/diff.h
View file @
d8cc1fb6
...
...
@@ -1158,6 +1158,94 @@ GIT_EXTERN(int) git_diff_stats_to_buf(
*/
GIT_EXTERN
(
void
)
git_diff_stats_free
(
git_diff_stats
*
stats
);
/**
* Formatting options for diff e-mail generation
*/
typedef
enum
{
/** Normal patch, the default */
GIT_DIFF_FORMAT_EMAIL_NONE
=
0
,
/** Don't insert "[PATCH]" in the subject header*/
GIT_DIFF_FORMAT_EMAIL_EXCLUDE_SUBJECT_PATCH_MARKER
=
(
1
<<
0
),
}
git_diff_format_email_flags_t
;
/**
* Options for controlling the formatting of the generated e-mail.
*/
typedef
struct
{
unsigned
int
version
;
git_diff_format_email_flags_t
flags
;
/** This patch number */
size_t
patch_no
;
/** Total number of patches in this series */
size_t
total_patches
;
/** id to use for the commit */
const
git_oid
*
id
;
/** Summary of the change */
const
char
*
summary
;
/** Author of the change */
const
git_signature
*
author
;
}
git_diff_format_email_options
;
#define GIT_DIFF_FORMAT_EMAIL_OPTIONS_VERSION 1
#define GIT_DIFF_FORMAT_EMAIL_OPTIONS_INIT {GIT_DIFF_FORMAT_EMAIL_OPTIONS_VERSION, 0, 1, 1, NULL, NULL, NULL}
/**
* Create an e-mail ready patch from a diff.
*
* @param out buffer to store the e-mail patch in
* @param diff containing the commit
* @param opts structure with options to influence content and formatting.
* @return 0 or an error code
*/
GIT_EXTERN
(
int
)
git_diff_format_email
(
git_buf
*
out
,
git_diff
*
diff
,
const
git_diff_format_email_options
*
opts
);
/**
* Create an e-mail ready patch for a commit.
*
* Does not support creating patches for merge commits (yet).
*
* @param out buffer to store the e-mail patch in
* @param repo containing the commit
* @param commit pointer to up commit
* @param patch_no patch number of the commit
* @param total_patches total number of patches in the patch set
* @param flags determines the formatting of the e-mail
* @param diff_opts structure with options to influence diff or NULL for defaults.
* @return 0 or an error code
*/
GIT_EXTERN
(
int
)
git_diff_commit_as_email
(
git_buf
*
out
,
git_repository
*
repo
,
git_commit
*
commit
,
size_t
patch_no
,
size_t
total_patches
,
git_diff_format_email_flags_t
flags
,
const
git_diff_options
*
diff_opts
);
/**
* Initializes a `git_diff_format_email_options` with default values. Equivalent to
* creating an instance with GIT_DIFF_FORMAT_EMAIL_OPTIONS_INIT.
*
* @param opts the `git_diff_format_email_options` instance to initialize.
* @param version the version of the struct; you should pass
* `GIT_DIFF_FORMAT_EMAIL_OPTIONS_VERSION` here.
* @return Zero on success; -1 on failure.
*/
GIT_EXTERN
(
int
)
git_diff_format_email_init_options
(
git_diff_format_email_options
*
opts
,
int
version
);
GIT_END_DECL
/** @} */
...
...
src/diff.c
View file @
d8cc1fb6
...
...
@@ -1427,6 +1427,198 @@ int git_diff__paired_foreach(
return
error
;
}
int
git_diff__commit
(
git_diff
**
diff
,
git_repository
*
repo
,
const
git_commit
*
commit
,
const
git_diff_options
*
opts
)
{
git_commit
*
parent
=
NULL
;
git_diff
*
commit_diff
=
NULL
;
git_tree
*
old_tree
=
NULL
,
*
new_tree
=
NULL
;
size_t
parents
;
int
error
=
0
;
if
((
parents
=
git_commit_parentcount
(
commit
))
>
1
)
{
char
commit_oidstr
[
GIT_OID_HEXSZ
+
1
];
error
=
-
1
;
giterr_set
(
GITERR_INVALID
,
"Commit %s is a merge commit"
,
git_oid_tostr
(
commit_oidstr
,
GIT_OID_HEXSZ
+
1
,
git_commit_id
(
commit
)));
goto
on_error
;
}
if
(
parents
>
0
)
if
((
error
=
git_commit_parent
(
&
parent
,
commit
,
0
))
<
0
||
(
error
=
git_commit_tree
(
&
old_tree
,
parent
))
<
0
)
goto
on_error
;
if
((
error
=
git_commit_tree
(
&
new_tree
,
commit
))
<
0
||
(
error
=
git_diff_tree_to_tree
(
&
commit_diff
,
repo
,
old_tree
,
new_tree
,
opts
))
<
0
)
goto
on_error
;
*
diff
=
commit_diff
;
on_error:
git_tree_free
(
new_tree
);
git_tree_free
(
old_tree
);
git_commit_free
(
parent
);
return
error
;
}
int
git_diff_format_email__append_header_tobuf
(
git_buf
*
out
,
const
git_oid
*
id
,
const
git_signature
*
author
,
const
char
*
summary
,
size_t
patch_no
,
size_t
total_patches
,
bool
exclude_patchno_marker
)
{
char
idstr
[
GIT_OID_HEXSZ
+
1
];
char
date_str
[
GIT_DATE_RFC2822_SZ
];
int
error
=
0
;
git_oid_fmt
(
idstr
,
id
);
idstr
[
GIT_OID_HEXSZ
]
=
'\0'
;
if
((
error
=
git__date_rfc2822_fmt
(
date_str
,
sizeof
(
date_str
),
&
author
->
when
))
<
0
)
return
error
;
error
=
git_buf_printf
(
out
,
"From %s Mon Sep 17 00:00:00 2001
\n
"
\
"From: %s <%s>
\n
"
\
"Date: %s
\n
"
\
"Subject: "
,
idstr
,
author
->
name
,
author
->
email
,
date_str
);
if
(
error
<
0
)
return
error
;
if
(
!
exclude_patchno_marker
)
{
if
(
total_patches
==
1
)
{
error
=
git_buf_puts
(
out
,
"[PATCH] "
);
}
else
{
error
=
git_buf_printf
(
out
,
"[PATCH %"
PRIuZ
"/%"
PRIuZ
"] "
,
patch_no
,
total_patches
);
}
if
(
error
<
0
)
return
error
;
}
error
=
git_buf_printf
(
out
,
"%s
\n\n
"
,
summary
);
return
error
;
}
int
git_diff_format_email__append_patches_tobuf
(
git_buf
*
out
,
git_diff
*
diff
)
{
size_t
i
,
deltas
;
int
error
=
0
;
deltas
=
git_diff_num_deltas
(
diff
);
for
(
i
=
0
;
i
<
deltas
;
++
i
)
{
git_patch
*
patch
=
NULL
;
if
((
error
=
git_patch_from_diff
(
&
patch
,
diff
,
i
))
>=
0
)
error
=
git_patch_to_buf
(
out
,
patch
);
git_patch_free
(
patch
);
if
(
error
<
0
)
break
;
}
return
error
;
}
int
git_diff_format_email
(
git_buf
*
out
,
git_diff
*
diff
,
const
git_diff_format_email_options
*
opts
)
{
git_diff_stats
*
stats
=
NULL
;
bool
ignore_marker
;
unsigned
int
format_flags
=
0
;
int
error
;
assert
(
out
&&
diff
&&
opts
);
assert
(
opts
->
summary
&&
opts
->
id
&&
opts
->
author
);
GITERR_CHECK_VERSION
(
opts
,
GIT_DIFF_FORMAT_EMAIL_OPTIONS_VERSION
,
"git_format_email_options"
);
if
((
ignore_marker
=
opts
->
flags
&
GIT_DIFF_FORMAT_EMAIL_EXCLUDE_SUBJECT_PATCH_MARKER
)
==
false
)
{
if
(
opts
->
patch_no
>
opts
->
total_patches
)
{
giterr_set
(
GITERR_INVALID
,
"patch %"
PRIuZ
" out of range. max %"
PRIuZ
,
opts
->
patch_no
,
opts
->
total_patches
);
return
-
1
;
}
if
(
opts
->
patch_no
==
0
)
{
giterr_set
(
GITERR_INVALID
,
"invalid patch no %"
PRIuZ
". should be >0"
,
opts
->
patch_no
);
return
-
1
;
}
}
error
=
git_diff_format_email__append_header_tobuf
(
out
,
opts
->
id
,
opts
->
author
,
opts
->
summary
,
opts
->
patch_no
,
opts
->
total_patches
,
ignore_marker
);
if
(
error
<
0
)
goto
on_error
;
format_flags
=
GIT_DIFF_STATS_FULL
|
GIT_DIFF_STATS_INCLUDE_SUMMARY
;
if
((
error
=
git_buf_puts
(
out
,
"---
\n
"
))
<
0
||
(
error
=
git_diff_get_stats
(
&
stats
,
diff
))
<
0
||
(
error
=
git_diff_stats_to_buf
(
out
,
stats
,
format_flags
))
<
0
||
(
error
=
git_diff_format_email__append_patches_tobuf
(
out
,
diff
))
<
0
)
goto
on_error
;
error
=
git_buf_puts
(
out
,
"--
\n
libgit2 "
LIBGIT2_VERSION
"
\n\n
"
);
on_error:
git_diff_stats_free
(
stats
);
return
error
;
}
int
git_diff_commit_as_email
(
git_buf
*
out
,
git_repository
*
repo
,
git_commit
*
commit
,
size_t
patch_no
,
size_t
total_patches
,
git_diff_format_email_flags_t
flags
,
const
git_diff_options
*
diff_opts
)
{
git_diff
*
diff
=
NULL
;
git_diff_format_email_options
opts
=
GIT_DIFF_FORMAT_EMAIL_OPTIONS_INIT
;
int
error
;
assert
(
out
&&
repo
&&
commit
);
opts
.
flags
=
flags
;
opts
.
patch_no
=
patch_no
;
opts
.
total_patches
=
total_patches
;
opts
.
id
=
git_commit_id
(
commit
);
opts
.
summary
=
git_commit_summary
(
commit
);
opts
.
author
=
git_commit_author
(
commit
);
if
((
error
=
git_diff__commit
(
&
diff
,
repo
,
commit
,
diff_opts
))
<
0
)
return
error
;
error
=
git_diff_format_email
(
out
,
diff
,
&
opts
);
git_diff_free
(
diff
);
return
error
;
}
int
git_diff_init_options
(
git_diff_options
*
opts
,
int
version
)
{
if
(
version
!=
GIT_DIFF_OPTIONS_VERSION
)
{
...
...
@@ -1450,3 +1642,15 @@ int git_diff_find_init_options(git_diff_find_options* opts, int version)
return
0
;
}
}
int
git_diff_format_email_init_options
(
git_diff_format_email_options
*
opts
,
int
version
)
{
if
(
version
!=
GIT_DIFF_FORMAT_EMAIL_OPTIONS_VERSION
)
{
giterr_set
(
GITERR_INVALID
,
"Invalid version %d for git_diff_format_email_options"
,
version
);
return
-
1
;
}
else
{
git_diff_format_email_options
o
=
GIT_DIFF_FORMAT_EMAIL_OPTIONS_INIT
;
memcpy
(
opts
,
&
o
,
sizeof
(
o
));
return
0
;
}
}
src/diff.h
View file @
d8cc1fb6
...
...
@@ -116,6 +116,9 @@ extern void git_diff_find_similar__hashsig_free(void *sig, void *payload);
extern
int
git_diff_find_similar__calc_similarity
(
int
*
score
,
void
*
siga
,
void
*
sigb
,
void
*
payload
);
extern
int
git_diff__commit
(
git_diff
**
diff
,
git_repository
*
repo
,
const
git_commit
*
commit
,
const
git_diff_options
*
opts
);
/*
* Sometimes a git_diff_file will have a zero size; this attempts to
* fill in the size without loading the blob if possible. If that is
...
...
tests/diff/format_email.c
0 → 100644
View file @
d8cc1fb6
This diff is collapsed.
Click to expand it.
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