1 /*
2  * Copyright (C) the libgit2 contributors. All rights reserved.
3  *
4  * This file is part of libgit2, distributed under the GNU GPL v2 with
5  * a Linking Exception. For full terms see the included COPYING file.
6  */
7 
8 #ifndef INCLUDE_git_blame_h__
9 #define INCLUDE_git_blame_h__
10 
11 #include "common.h"
12 #include "oid.h"
13 
14 /**
15  * @file git2/blame.h
16  * @brief Git blame routines
17  * @defgroup git_blame Git blame routines
18  * @ingroup Git
19  * @{
20  */
21 GIT_BEGIN_DECL
22 
23 /**
24  * Flags for indicating option behavior for git_blame APIs.
25  */
26 typedef enum {
27 	/** Normal blame, the default */
28 	GIT_BLAME_NORMAL = 0,
29 
30 	/**
31 	 * Track lines that have moved within a file (like `git blame -M`).
32 	 *
33 	 * This is not yet implemented and reserved for future use.
34 	 */
35 	GIT_BLAME_TRACK_COPIES_SAME_FILE = (1<<0),
36 
37 	/**
38 	 * Track lines that have moved across files in the same commit
39 	 * (like `git blame -C`).
40 	 *
41 	 * This is not yet implemented and reserved for future use.
42 	 */
43 	GIT_BLAME_TRACK_COPIES_SAME_COMMIT_MOVES = (1<<1),
44 
45 	/**
46 	 * Track lines that have been copied from another file that exists
47 	 * in the same commit (like `git blame -CC`).  Implies SAME_FILE.
48 	 *
49 	 * This is not yet implemented and reserved for future use.
50 	 */
51 	GIT_BLAME_TRACK_COPIES_SAME_COMMIT_COPIES = (1<<2),
52 
53 	/**
54 	 * Track lines that have been copied from another file that exists in
55 	 * *any* commit (like `git blame -CCC`).  Implies SAME_COMMIT_COPIES.
56 	 *
57 	 * This is not yet implemented and reserved for future use.
58 	 */
59 	GIT_BLAME_TRACK_COPIES_ANY_COMMIT_COPIES = (1<<3),
60 
61 	/**
62 	 * Restrict the search of commits to those reachable following only
63 	 * the first parents.
64 	 */
65 	GIT_BLAME_FIRST_PARENT = (1<<4),
66 
67 	/**
68 	 * Use mailmap file to map author and committer names and email
69 	 * addresses to canonical real names and email addresses. The
70 	 * mailmap will be read from the working directory, or HEAD in a
71 	 * bare repository.
72 	 */
73 	GIT_BLAME_USE_MAILMAP = (1<<5),
74 
75 	/** Ignore whitespace differences */
76 	GIT_BLAME_IGNORE_WHITESPACE = (1<<6),
77 } git_blame_flag_t;
78 
79 /**
80  * Blame options structure
81  *
82  * Initialize with `GIT_BLAME_OPTIONS_INIT`. Alternatively, you can
83  * use `git_blame_options_init`.
84  *
85  */
86 typedef struct git_blame_options {
87 	unsigned int version;
88 
89 	/** A combination of `git_blame_flag_t` */
90 	uint32_t flags;
91 
92 	/**
93 	 * The lower bound on the number of alphanumeric characters that
94 	 * must be detected as moving/copying within a file for it to
95 	 * associate those lines with the parent commit. The default value
96 	 * is 20.
97 	 *
98 	 * This value only takes effect if any of the `GIT_BLAME_TRACK_COPIES_*`
99 	 * flags are specified.
100 	 */
101 	uint16_t min_match_characters;
102 
103 	/** The id of the newest commit to consider. The default is HEAD. */
104 	git_oid newest_commit;
105 
106 	/**
107 	 * The id of the oldest commit to consider.
108 	 * The default is the first commit encountered with a NULL parent.
109 	 */
110 	git_oid oldest_commit;
111 
112 	/**
113 	 * The first line in the file to blame.
114 	 * The default is 1 (line numbers start with 1).
115 	 */
116 	size_t min_line;
117 
118 	/**
119 	 * The last line in the file to blame.
120 	 * The default is the last line of the file.
121 	 */
122 	size_t max_line;
123 } git_blame_options;
124 
125 #define GIT_BLAME_OPTIONS_VERSION 1
126 #define GIT_BLAME_OPTIONS_INIT {GIT_BLAME_OPTIONS_VERSION}
127 
128 /**
129  * Initialize git_blame_options structure
130  *
131  * Initializes a `git_blame_options` with default values. Equivalent to creating
132  * an instance with GIT_BLAME_OPTIONS_INIT.
133  *
134  * @param opts The `git_blame_options` struct to initialize.
135  * @param version The struct version; pass `GIT_BLAME_OPTIONS_VERSION`.
136  * @return Zero on success; -1 on failure.
137  */
138 GIT_EXTERN(int) git_blame_options_init(
139 	git_blame_options *opts,
140 	unsigned int version);
141 
142 /**
143  * Structure that represents a blame hunk.
144  */
145 typedef struct git_blame_hunk {
146 	/**
147 	 * The number of lines in this hunk.
148 	 */
149 	size_t lines_in_hunk;
150 
151 	/**
152 	 * The OID of the commit where this line was last changed.
153 	 */
154 	git_oid final_commit_id;
155 
156 	/**
157 	 * The 1-based line number where this hunk begins, in the final version
158 	 * of the file.
159 	 */
160 	size_t final_start_line_number;
161 
162 	/**
163 	 * The author of `final_commit_id`. If `GIT_BLAME_USE_MAILMAP` has been
164 	 * specified, it will contain the canonical real name and email address.
165 	 */
166 	git_signature *final_signature;
167 
168 	/**
169 	 * The OID of the commit where this hunk was found.
170 	 * This will usually be the same as `final_commit_id`, except when
171 	 * `GIT_BLAME_TRACK_COPIES_ANY_COMMIT_COPIES` has been specified.
172 	 */
173 	git_oid orig_commit_id;
174 
175 	/**
176 	 * The path to the file where this hunk originated, as of the commit
177 	 * specified by `orig_commit_id`.
178 	 */
179 	const char *orig_path;
180 
181 	/**
182 	 * The 1-based line number where this hunk begins in the file named by
183 	 * `orig_path` in the commit specified by `orig_commit_id`.
184 	 */
185 	size_t orig_start_line_number;
186 
187 	/**
188 	 * The author of `orig_commit_id`. If `GIT_BLAME_USE_MAILMAP` has been
189 	 * specified, it will contain the canonical real name and email address.
190 	 */
191 	git_signature *orig_signature;
192 
193 	/**
194 	 * The 1 iff the hunk has been tracked to a boundary commit (the root,
195 	 * or the commit specified in git_blame_options.oldest_commit)
196 	 */
197 	char boundary;
198 } git_blame_hunk;
199 
200 
201 /** Opaque structure to hold blame results */
202 typedef struct git_blame git_blame;
203 
204 /**
205  * Gets the number of hunks that exist in the blame structure.
206  */
207 GIT_EXTERN(uint32_t) git_blame_get_hunk_count(git_blame *blame);
208 
209 /**
210  * Gets the blame hunk at the given index.
211  *
212  * @param blame the blame structure to query
213  * @param index index of the hunk to retrieve
214  * @return the hunk at the given index, or NULL on error
215  */
216 GIT_EXTERN(const git_blame_hunk*) git_blame_get_hunk_byindex(
217 		git_blame *blame,
218 		uint32_t index);
219 
220 /**
221  * Gets the hunk that relates to the given line number in the newest commit.
222  *
223  * @param blame the blame structure to query
224  * @param lineno the (1-based) line number to find a hunk for
225  * @return the hunk that contains the given line, or NULL on error
226  */
227 GIT_EXTERN(const git_blame_hunk*) git_blame_get_hunk_byline(
228 		git_blame *blame,
229 		size_t lineno);
230 
231 /**
232  * Get the blame for a single file.
233  *
234  * @param out pointer that will receive the blame object
235  * @param repo repository whose history is to be walked
236  * @param path path to file to consider
237  * @param options options for the blame operation.  If NULL, this is treated as
238  *                though GIT_BLAME_OPTIONS_INIT were passed.
239  * @return 0 on success, or an error code. (use git_error_last for information
240  *         about the error.)
241  */
242 GIT_EXTERN(int) git_blame_file(
243 		git_blame **out,
244 		git_repository *repo,
245 		const char *path,
246 		git_blame_options *options);
247 
248 
249 /**
250  * Get blame data for a file that has been modified in memory. The `reference`
251  * parameter is a pre-calculated blame for the in-odb history of the file. This
252  * means that once a file blame is completed (which can be expensive), updating
253  * the buffer blame is very fast.
254  *
255  * Lines that differ between the buffer and the committed version are marked as
256  * having a zero OID for their final_commit_id.
257  *
258  * @param out pointer that will receive the resulting blame data
259  * @param reference cached blame from the history of the file (usually the output
260  *                  from git_blame_file)
261  * @param buffer the (possibly) modified contents of the file
262  * @param buffer_len number of valid bytes in the buffer
263  * @return 0 on success, or an error code. (use git_error_last for information
264  *         about the error)
265  */
266 GIT_EXTERN(int) git_blame_buffer(
267 		git_blame **out,
268 		git_blame *reference,
269 		const char *buffer,
270 		size_t buffer_len);
271 
272 /**
273  * Free memory allocated by git_blame_file or git_blame_buffer.
274  *
275  * @param blame the blame structure to free
276  */
277 GIT_EXTERN(void) git_blame_free(git_blame *blame);
278 
279 /** @} */
280 GIT_END_DECL
281 #endif
282 
283