summaryrefslogtreecommitdiffstats
path: root/include/git2/oid.h
blob: 35b43ef183a1bd844c00ca7f7fc27f909340c827 (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
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
/*
 * 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_oid_h__
#define INCLUDE_git_oid_h__

#include "common.h"
#include "types.h"
#include "experimental.h"

/**
 * @file git2/oid.h
 * @brief Git object id routines
 * @defgroup git_oid Git object id routines
 * @ingroup Git
 * @{
 */
GIT_BEGIN_DECL

/** The type of object id. */
typedef enum {

#ifdef GIT_EXPERIMENTAL_SHA256
	GIT_OID_SHA1 = 1,  /**< SHA1 */
	GIT_OID_SHA256 = 2 /**< SHA256 */
#else
	GIT_OID_SHA1 = 1   /**< SHA1 */
#endif

} git_oid_t;

/*
 * SHA1 is currently the only supported object ID type.
 */

/** SHA1 is currently libgit2's default oid type. */
#define GIT_OID_DEFAULT         GIT_OID_SHA1

/** Size (in bytes) of a raw/binary sha1 oid */
#define GIT_OID_SHA1_SIZE       20
/** Size (in bytes) of a hex formatted sha1 oid */
#define GIT_OID_SHA1_HEXSIZE   (GIT_OID_SHA1_SIZE * 2)

/**
 * The binary representation of the null sha1 object ID.
 */
#ifndef GIT_EXPERIMENTAL_SHA256
# define GIT_OID_SHA1_ZERO   { { 0 } }
#else
# define GIT_OID_SHA1_ZERO   { GIT_OID_SHA1, { 0 } }
#endif

/**
 * The string representation of the null sha1 object ID.
 */
#define GIT_OID_SHA1_HEXZERO   "0000000000000000000000000000000000000000"

/*
 * Experimental SHA256 support is a breaking change to the API.
 * This exists for application compatibility testing.
 */

#ifdef GIT_EXPERIMENTAL_SHA256

/** Size (in bytes) of a raw/binary sha256 oid */
# define GIT_OID_SHA256_SIZE     32
/** Size (in bytes) of a hex formatted sha256 oid */
# define GIT_OID_SHA256_HEXSIZE (GIT_OID_SHA256_SIZE * 2)

/**
 * The binary representation of the null sha256 object ID.
 */
# define GIT_OID_SHA256_ZERO { GIT_OID_SHA256, { 0 } }

/**
 * The string representation of the null sha256 object ID.
 */
# define GIT_OID_SHA256_HEXZERO "0000000000000000000000000000000000000000000000000000000000000000"

#endif

/* Maximum possible object ID size in raw / hex string format. */
#ifndef GIT_EXPERIMENTAL_SHA256
# define GIT_OID_MAX_SIZE        GIT_OID_SHA1_SIZE
# define GIT_OID_MAX_HEXSIZE     GIT_OID_SHA1_HEXSIZE
#else
# define GIT_OID_MAX_SIZE        GIT_OID_SHA256_SIZE
# define GIT_OID_MAX_HEXSIZE     GIT_OID_SHA256_HEXSIZE
#endif

/** Minimum length (in number of hex characters,
 * i.e. packets of 4 bits) of an oid prefix */
#define GIT_OID_MINPREFIXLEN 4

/** Unique identity of any object (commit, tree, blob, tag). */
typedef struct git_oid {

#ifdef GIT_EXPERIMENTAL_SHA256
	/** type of object id */
	unsigned char type;
#endif

	/** raw binary formatted id */
	unsigned char id[GIT_OID_MAX_SIZE];
} git_oid;

/**
 * Parse a hex formatted object id into a git_oid.
 *
 * The appropriate number of bytes for the given object ID type will
 * be read from the string - 40 bytes for SHA1, 64 bytes for SHA256.
 * The given string need not be NUL terminated.
 *
 * @param out oid structure the result is written into.
 * @param str input hex string; must be pointing at the start of
 *		the hex sequence and have at least the number of bytes
 *		needed for an oid encoded in hex (40 bytes for sha1,
 *		256 bytes for sha256).
 * @param type the type of object id
 * @return 0 or an error code
 */
#ifdef GIT_EXPERIMENTAL_SHA256
GIT_EXTERN(int) git_oid_fromstr(git_oid *out, const char *str, git_oid_t type);
#else
GIT_EXTERN(int) git_oid_fromstr(git_oid *out, const char *str);
#endif

/**
 * Parse a hex formatted NUL-terminated string into a git_oid.
 *
 * @param out oid structure the result is written into.
 * @param str input hex string; must be null-terminated.
 * @param type the type of object id
 * @return 0 or an error code
 */
#ifdef GIT_EXPERIMENTAL_SHA256
GIT_EXTERN(int) git_oid_fromstrp(git_oid *out, const char *str, git_oid_t type);
#else
GIT_EXTERN(int) git_oid_fromstrp(git_oid *out, const char *str);
#endif

/**
 * Parse N characters of a hex formatted object id into a git_oid.
 *
 * If N is odd, the last byte's high nibble will be read in and the
 * low nibble set to zero.
 *
 * @param out oid structure the result is written into.
 * @param str input hex string of at least size `length`
 * @param length length of the input string
 * @param type the type of object id
 * @return 0 or an error code
 */
#ifdef GIT_EXPERIMENTAL_SHA256
GIT_EXTERN(int) git_oid_fromstrn(git_oid *out, const char *str, size_t length, git_oid_t type);
#else
GIT_EXTERN(int) git_oid_fromstrn(git_oid *out, const char *str, size_t length);
#endif

/**
 * Copy an already raw oid into a git_oid structure.
 *
 * @param out oid structure the result is written into.
 * @param raw the raw input bytes to be copied.
 * @return 0 on success or error code
 */
#ifdef GIT_EXPERIMENTAL_SHA256
GIT_EXTERN(int) git_oid_fromraw(git_oid *out, const unsigned char *raw, git_oid_t type);
#else
GIT_EXTERN(int) git_oid_fromraw(git_oid *out, const unsigned char *raw);
#endif

/**
 * Format a git_oid into a hex string.
 *
 * @param out output hex string; must be pointing at the start of
 *		the hex sequence and have at least the number of bytes
 *		needed for an oid encoded in hex (40 bytes for SHA1,
 *		64 bytes for SHA256). Only the oid digits are written;
 *		a '\\0' terminator must be added by the caller if it is
 *		required.
 * @param id oid structure to format.
 * @return 0 on success or error code
 */
GIT_EXTERN(int) git_oid_fmt(char *out, const git_oid *id);

/**
 * Format a git_oid into a partial hex string.
 *
 * @param out output hex string; you say how many bytes to write.
 *		If the number of bytes is > GIT_OID_SHA1_HEXSIZE, extra bytes
 *		will be zeroed; if not, a '\0' terminator is NOT added.
 * @param n number of characters to write into out string
 * @param id oid structure to format.
 * @return 0 on success or error code
 */
GIT_EXTERN(int) git_oid_nfmt(char *out, size_t n, const git_oid *id);

/**
 * Format a git_oid into a loose-object path string.
 *
 * The resulting string is "aa/...", where "aa" is the first two
 * hex digits of the oid and "..." is the remaining 38 digits.
 *
 * @param out output hex string; must be pointing at the start of
 *		the hex sequence and have at least the number of bytes
 *		needed for an oid encoded in hex (41 bytes for SHA1,
 *		65 bytes for SHA256). Only the oid digits are written;
 *		a '\\0' terminator must be added by the caller if it
 *		is required.
 * @param id oid structure to format.
 * @return 0 on success, non-zero callback return value, or error code
 */
GIT_EXTERN(int) git_oid_pathfmt(char *out, const git_oid *id);

/**
 * Format a git_oid into a statically allocated c-string.
 *
 * The c-string is owned by the library and should not be freed
 * by the user. If libgit2 is built with thread support, the string
 * will be stored in TLS (i.e. one buffer per thread) to allow for
 * concurrent calls of the function.
 *
 * @param oid The oid structure to format
 * @return the c-string or NULL on failure
 */
GIT_EXTERN(char *) git_oid_tostr_s(const git_oid *oid);

/**
 * Format a git_oid into a buffer as a hex format c-string.
 *
 * If the buffer is smaller than the size of a hex-formatted oid string
 * plus an additional byte (GIT_OID_SHA_HEXSIZE + 1 for SHA1 or
 * GIT_OID_SHA256_HEXSIZE + 1 for SHA256), then the resulting
 * oid c-string will be truncated to n-1 characters (but will still be
 * NUL-byte terminated).
 *
 * If there are any input parameter errors (out == NULL, n == 0, oid ==
 * NULL), then a pointer to an empty string is returned, so that the
 * return value can always be printed.
 *
 * @param out the buffer into which the oid string is output.
 * @param n the size of the out buffer.
 * @param id the oid structure to format.
 * @return the out buffer pointer, assuming no input parameter
 *			errors, otherwise a pointer to an empty string.
 */
GIT_EXTERN(char *) git_oid_tostr(char *out, size_t n, const git_oid *id);

/**
 * Copy an oid from one structure to another.
 *
 * @param out oid structure the result is written into.
 * @param src oid structure to copy from.
 * @return 0 on success or error code
 */
GIT_EXTERN(int) git_oid_cpy(git_oid *out, const git_oid *src);

/**
 * Compare two oid structures.
 *
 * @param a first oid structure.
 * @param b second oid structure.
 * @return <0, 0, >0 if a < b, a == b, a > b.
 */
GIT_EXTERN(int) git_oid_cmp(const git_oid *a, const git_oid *b);

/**
 * Compare two oid structures for equality
 *
 * @param a first oid structure.
 * @param b second oid structure.
 * @return true if equal, false otherwise
 */
GIT_EXTERN(int) git_oid_equal(const git_oid *a, const git_oid *b);

/**
 * Compare the first 'len' hexadecimal characters (packets of 4 bits)
 * of two oid structures.
 *
 * @param a first oid structure.
 * @param b second oid structure.
 * @param len the number of hex chars to compare
 * @return 0 in case of a match
 */
GIT_EXTERN(int) git_oid_ncmp(const git_oid *a, const git_oid *b, size_t len);

/**
 * Check if an oid equals an hex formatted object id.
 *
 * @param id oid structure.
 * @param str input hex string of an object id.
 * @return 0 in case of a match, -1 otherwise.
 */
GIT_EXTERN(int) git_oid_streq(const git_oid *id, const char *str);

/**
 * Compare an oid to an hex formatted object id.
 *
 * @param id oid structure.
 * @param str input hex string of an object id.
 * @return -1 if str is not valid, <0 if id sorts before str,
 *         0 if id matches str, >0 if id sorts after str.
 */
GIT_EXTERN(int) git_oid_strcmp(const git_oid *id, const char *str);

/**
 * Check is an oid is all zeros.
 *
 * @return 1 if all zeros, 0 otherwise.
 */
GIT_EXTERN(int) git_oid_is_zero(const git_oid *id);

/**
 * OID Shortener object
 */
typedef struct git_oid_shorten git_oid_shorten;

/**
 * Create a new OID shortener.
 *
 * The OID shortener is used to process a list of OIDs
 * in text form and return the shortest length that would
 * uniquely identify all of them.
 *
 * E.g. look at the result of `git log --abbrev`.
 *
 * @param min_length The minimal length for all identifiers,
 *		which will be used even if shorter OIDs would still
 *		be unique.
 *	@return a `git_oid_shorten` instance, NULL if OOM
 */
GIT_EXTERN(git_oid_shorten *) git_oid_shorten_new(size_t min_length);

/**
 * Add a new OID to set of shortened OIDs and calculate
 * the minimal length to uniquely identify all the OIDs in
 * the set.
 *
 * The OID is expected to be a 40-char hexadecimal string.
 * The OID is owned by the user and will not be modified
 * or freed.
 *
 * For performance reasons, there is a hard-limit of how many
 * OIDs can be added to a single set (around ~32000, assuming
 * a mostly randomized distribution), which should be enough
 * for any kind of program, and keeps the algorithm fast and
 * memory-efficient.
 *
 * Attempting to add more than those OIDs will result in a
 * GIT_ERROR_INVALID error
 *
 * @param os a `git_oid_shorten` instance
 * @param text_id an OID in text form
 * @return the minimal length to uniquely identify all OIDs
 *		added so far to the set; or an error code (<0) if an
 *		error occurs.
 */
GIT_EXTERN(int) git_oid_shorten_add(git_oid_shorten *os, const char *text_id);

/**
 * Free an OID shortener instance
 *
 * @param os a `git_oid_shorten` instance
 */
GIT_EXTERN(void) git_oid_shorten_free(git_oid_shorten *os);

/** @} */
GIT_END_DECL
#endif