summaryrefslogtreecommitdiff
path: root/include/git2/blame.h
blob: d193ce14ed5f2870dfab75032c9b5d3ffb6fa3f8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
/*
 * Copyright (C) the libgit2 contributors. All rights reserved.
 *
 * This file is part of libgit2, distributed under the GNU GPL v2 with
 * a Linking Exception. For full terms see the included COPYING file.
 */

#ifndef INCLUDE_git_blame_h__
#define INCLUDE_git_blame_h__

#include "common.h"
#include "oid.h"

/**
 * @file git2/blame.h
 * @brief Git blame routines
 * @defgroup git_blame Git blame routines
 * @ingroup Git
 * @{
 */
GIT_BEGIN_DECL

/**
 * Flags for indicating option behavior for git_blame APIs.
 */
typedef enum {
	/** Normal blame, the default */
	GIT_BLAME_NORMAL = 0,

	/**
	 * Track lines that have moved within a file (like `git blame -M`).
	 *
	 * This is not yet implemented and reserved for future use.
	 */
	GIT_BLAME_TRACK_COPIES_SAME_FILE = (1<<0),

	/**
	 * Track lines that have moved across files in the same commit
	 * (like `git blame -C`).
	 *
	 * This is not yet implemented and reserved for future use.
	 */
	GIT_BLAME_TRACK_COPIES_SAME_COMMIT_MOVES = (1<<1),

	/**
	 * Track lines that have been copied from another file that exists
	 * in the same commit (like `git blame -CC`).  Implies SAME_FILE.
	 *
	 * This is not yet implemented and reserved for future use.
	 */
	GIT_BLAME_TRACK_COPIES_SAME_COMMIT_COPIES = (1<<2),

	/**
	 * Track lines that have been copied from another file that exists in
	 * *any* commit (like `git blame -CCC`).  Implies SAME_COMMIT_COPIES.
	 *
	 * This is not yet implemented and reserved for future use.
	 */
	GIT_BLAME_TRACK_COPIES_ANY_COMMIT_COPIES = (1<<3),

	/**
	 * Restrict the search of commits to those reachable following only
	 * the first parents.
	 */
	GIT_BLAME_FIRST_PARENT = (1<<4),

	/**
	 * Use mailmap file to map author and committer names and email
	 * addresses to canonical real names and email addresses. The
	 * mailmap will be read from the working directory, or HEAD in a
	 * bare repository.
	 */
	GIT_BLAME_USE_MAILMAP = (1<<5),

	/** Ignore whitespace differences */
	GIT_BLAME_IGNORE_WHITESPACE = (1<<6),
} git_blame_flag_t;

/**
 * Blame options structure
 *
 * Initialize with `GIT_BLAME_OPTIONS_INIT`. Alternatively, you can
 * use `git_blame_options_init`.
 *
 */
typedef struct git_blame_options {
	unsigned int version;

	/** A combination of `git_blame_flag_t` */
	uint32_t flags;

	/**
	 * The lower bound on the number of alphanumeric characters that
	 * must be detected as moving/copying within a file for it to
	 * associate those lines with the parent commit. The default value
	 * is 20.
	 *
	 * This value only takes effect if any of the `GIT_BLAME_TRACK_COPIES_*`
	 * flags are specified.
	 */
	uint16_t min_match_characters;

	/** The id of the newest commit to consider. The default is HEAD. */
	git_oid newest_commit;

	/**
	 * The id of the oldest commit to consider.
	 * The default is the first commit encountered with a NULL parent.
	 */
	git_oid oldest_commit;

	/**
	 * The first line in the file to blame.
	 * The default is 1 (line numbers start with 1).
	 */
	size_t min_line;

	/**
	 * The last line in the file to blame.
	 * The default is the last line of the file.
	 */
	size_t max_line;
} git_blame_options;

#define GIT_BLAME_OPTIONS_VERSION 1
#define GIT_BLAME_OPTIONS_INIT {GIT_BLAME_OPTIONS_VERSION}

/**
 * Initialize git_blame_options structure
 *
 * Initializes a `git_blame_options` with default values. Equivalent to creating
 * an instance with GIT_BLAME_OPTIONS_INIT.
 *
 * @param opts The `git_blame_options` struct to initialize.
 * @param version The struct version; pass `GIT_BLAME_OPTIONS_VERSION`.
 * @return Zero on success; -1 on failure.
 */
GIT_EXTERN(int) git_blame_options_init(
	git_blame_options *opts,
	unsigned int version);

/**
 * Structure that represents a blame hunk.
 */
typedef struct git_blame_hunk {
	/**
	 * The number of lines in this hunk.
	 */
	size_t lines_in_hunk;

	/**
	 * The OID of the commit where this line was last changed.
	 */
	git_oid final_commit_id;

	/**
	 * The 1-based line number where this hunk begins, in the final version
	 * of the file.
	 */
	size_t final_start_line_number;

	/**
	 * The author of `final_commit_id`. If `GIT_BLAME_USE_MAILMAP` has been
	 * specified, it will contain the canonical real name and email address.
	 */
	git_signature *final_signature;

	/**
	 * The OID of the commit where this hunk was found.
	 * This will usually be the same as `final_commit_id`, except when
	 * `GIT_BLAME_TRACK_COPIES_ANY_COMMIT_COPIES` has been specified.
	 */
	git_oid orig_commit_id;

	/**
	 * The path to the file where this hunk originated, as of the commit
	 * specified by `orig_commit_id`.
	 */
	const char *orig_path;

	/**
	 * The 1-based line number where this hunk begins in the file named by
	 * `orig_path` in the commit specified by `orig_commit_id`.
	 */
	size_t orig_start_line_number;

	/**
	 * The author of `orig_commit_id`. If `GIT_BLAME_USE_MAILMAP` has been
	 * specified, it will contain the canonical real name and email address.
	 */
	git_signature *orig_signature;

	/**
	 * The 1 iff the hunk has been tracked to a boundary commit (the root,
	 * or the commit specified in git_blame_options.oldest_commit)
	 */
	char boundary;
} git_blame_hunk;


/** Opaque structure to hold blame results */
typedef struct git_blame git_blame;

/**
 * Gets the number of hunks that exist in the blame structure.
 */
GIT_EXTERN(uint32_t) git_blame_get_hunk_count(git_blame *blame);

/**
 * Gets the blame hunk at the given index.
 *
 * @param blame the blame structure to query
 * @param index index of the hunk to retrieve
 * @return the hunk at the given index, or NULL on error
 */
GIT_EXTERN(const git_blame_hunk*) git_blame_get_hunk_byindex(
		git_blame *blame,
		uint32_t index);

/**
 * Gets the hunk that relates to the given line number in the newest commit.
 *
 * @param blame the blame structure to query
 * @param lineno the (1-based) line number to find a hunk for
 * @return the hunk that contains the given line, or NULL on error
 */
GIT_EXTERN(const git_blame_hunk*) git_blame_get_hunk_byline(
		git_blame *blame,
		size_t lineno);

/**
 * Get the blame for a single file.
 *
 * @param out pointer that will receive the blame object
 * @param repo repository whose history is to be walked
 * @param path path to file to consider
 * @param options options for the blame operation.  If NULL, this is treated as
 *                though GIT_BLAME_OPTIONS_INIT were passed.
 * @return 0 on success, or an error code. (use git_error_last for information
 *         about the error.)
 */
GIT_EXTERN(int) git_blame_file(
		git_blame **out,
		git_repository *repo,
		const char *path,
		git_blame_options *options);


/**
 * Get blame data for a file that has been modified in memory. The `reference`
 * parameter is a pre-calculated blame for the in-odb history of the file. This
 * means that once a file blame is completed (which can be expensive), updating
 * the buffer blame is very fast.
 *
 * Lines that differ between the buffer and the committed version are marked as
 * having a zero OID for their final_commit_id.
 *
 * @param out pointer that will receive the resulting blame data
 * @param reference cached blame from the history of the file (usually the output
 *                  from git_blame_file)
 * @param buffer the (possibly) modified contents of the file
 * @param buffer_len number of valid bytes in the buffer
 * @return 0 on success, or an error code. (use git_error_last for information
 *         about the error)
 */
GIT_EXTERN(int) git_blame_buffer(
		git_blame **out,
		git_blame *reference,
		const char *buffer,
		size_t buffer_len);

/**
 * Free memory allocated by git_blame_file or git_blame_buffer.
 *
 * @param blame the blame structure to free
 */
GIT_EXTERN(void) git_blame_free(git_blame *blame);

/** @} */
GIT_END_DECL
#endif