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