8000 sha256: make sha256 an experimental optional feature · libgit2/libgit2@52abe12 · GitHub
[go: up one dir, main page]

Skip to content

Commit 52abe12

Browse files
committed
sha256: make sha256 an experimental optional feature
libgit2 can be built with optional, experimental sha256 support. This allows consumers to begin testing and providing feedback for our sha256 support while we continue to develop it, and allows us to make API breaking changes while we iterate on a final sha256 implementation. The results will be `git2-experimental.dll` and installed as `git2-experimental.h` to avoid confusion with a production libgit2.
1 parent 080d287 commit 52abe12

22 files changed

+270
-54
lines changed

CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake")
1515
# Build options
1616
#
1717

18+
# Experimental features
19+
option(EXPERIMENTAL_SHA256 "Enable experimental SHA256 support (for R&D/testing)" OFF)
20+
1821
# Optional subsystems
1922
option(BUILD_SHARED_LIBS "Build Shared Library (OFF for Static)" ON)
2023
option(BUILD_TESTS "Build Tests using the Clar suite" ON)
@@ -107,6 +110,7 @@ include(IdeSplitSources)
107110
include(FeatureSummary)
108111
include(EnableWarnings)
109112
include(DefaultCFlags)
113+
include(ExperimentalFeatures)
110114

111115

112116
#

cmake/ExperimentalFeatures.cmake

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
if(EXPERIMENTAL_SHA256)
2+
add_feature_info("SHA256 API" ON "experimental SHA256 APIs")
3+
4+
set(EXPERIMENTAL 1)
5+
set(GIT_EXPERIMENTAL_SHA256 1)
6+
else()
7+
add_feature_info("SHA256 API" OFF "experimental SHA256 APIs")
8+
endif()
9+
10+
if(EXPERIMENTAL)
11+
set(LIBGIT2_FILENAME "${LIBGIT2_FILENAME}-experimental")
12+
endif()

include/git2.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "git2/diff.h"
2929
#include "git2/email.h"
3030
#include "git2/errors.h"
31+
#include "git2/experimental.h"
3132
#include "git2/filter.h"
3233
#include "git2/global.h"
3334
#include "git2/graph.h"

include/git2/deprecated.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -777,6 +777,12 @@ typedef git_trace_cb git_trace_callback;
777777
*/
778778
/**@{*/
779779

780+
#ifndef GIT_EXPERIMENTAL_SHA256
781+
# define GIT_OID_RAWSZ GIT_OID_SHA1_SIZE
782+
# define GIT_OID_HEXSZ GIT_OID_SHA1_HEXSIZE
783+
# define GIT_OID_HEX_ZERO GIT_OID_SHA1_HEXZERO
784+
#endif
785+
780786
GIT_EXTERN(int) git_oid_iszero(const git_oid *id);
781787

782788
/**@}*/

include/git2/oid.h

Lines changed: 63 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
#include "common.h"
1111
#include "types.h"
12+
#include "experimental.h"
1213

1314
/**
1415
* @file git2/oid.h
@@ -21,48 +22,91 @@ GIT_BEGIN_DECL
2122

2223
/** The type of object id. */
2324
typedef enum {
25+
26+
#ifdef GIT_EXPERIMENTAL_SHA256
2427
GIT_OID_SHA1 = 1, /**< SHA1 */
2528
GIT_OID_SHA256 = 2 /**< SHA256 */
29+
#else
30+
GIT_OID_SHA1 = 1 /**< SHA1 */
31+
#endif
32+
2633
} git_oid_t;
2734

35+
/*
36+
* SHA1 is currently the only supported object ID type.
37+
*/
38+
2839
/** SHA1 is currently libgit2's default oid type. */
2940
#define GIT_OID_DEFAULT GIT_OID_SHA1
3041

31-
/** Size (in bytes) of a raw/binary oid */
42+
/** Size (in bytes) of a raw/binary sha1 oid */
3243
#define GIT_OID_SHA1_SIZE 20
33-
#define GIT_OID_SHA256_SIZE 32
34-
#define GIT_OID_MAX_SIZE GIT_OID_SHA256_SIZE
35-
36-
/** Size (in bytes) of a hex formatted oid */
44+
/** Size (in bytes) of a hex formatted sha1 oid */
3745
#define GIT_OID_SHA1_HEXSIZE (GIT_OID_SHA1_SIZE * 2)
38-
#define GIT_OID_SHA256_HEXSIZE (GIT_OID_SHA256_SIZE * 2)
39-
#define GIT_OID_MAX_HEXSIZE GIT_OID_SHA256_HEXSIZE
46+
47+
/**
48+
* The binary representation of the null sha1 object ID.
49+
*/
50+
#ifndef GIT_EXPERIMENTAL_SHA256
51+
# define GIT_OID_SHA1_ZERO { { 0 } }
52+
#else
53+
# define GIT_OID_SHA1_ZERO { GIT_OID_SHA1, { 0 } }
54+
#endif
55+
56+
/**
57+
* The string representation of the null sha1 object ID.
58+
*/
59+
#define GIT_OID_SHA1_HEXZERO "0000000000000000000000000000000000000000"
60+
61+
/*
62+
* Experimental SHA256 support is a breaking change to the API.
63+
* This exists for application compatibility testing.
64+
*/
65+
66+
#ifdef GIT_EXPERIMENTAL_SHA256
67+
68+
/** Size (in bytes) of a raw/binary sha256 oid */
69+
# define GIT_OID_SHA256_SIZE 32
70+
/** Size (in bytes) of a hex formatted sha256 oid */
71+
# define GIT_OID_SHA256_HEXSIZE (GIT_OID_SHA256_SIZE * 2)
72+
73+
/**
74+
* The binary representation of the null sha256 object ID.
75+
*/
76+
# define GIT_OID_SHA256_ZERO { GIT_OID_SHA256, { 0 } }
77+
78+
/**
79+
* The string representation of the null sha256 object ID.
80+
*/
81+
# define GIT_OID_SHA256_HEXZERO "0000000000000000000000000000000000000000000000000000000000000000"
82+
83+
#endif
84+
85+
/* Maximum possible object ID size in raw / hex string format. */
86+
#ifndef GIT_EXPERIMENTAL_SHA256
87+
# define GIT_OID_MAX_SIZE GIT_OID_SHA1_SIZE
88+
# define GIT_OID_MAX_HEXSIZE GIT_OID_SHA1_HEXSIZE
89+
#else
90+
# define GIT_OID_MAX_SIZE GIT_OID_SHA256_SIZE
91+
# define GIT_OID_MAX_HEXSIZE GIT_OID_SHA256_HEXSIZE
92+
#endif
4093

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

4598
/** Unique identity of any object (commit, tree, blob, tag). */
4699
typedef struct git_oid {
100+
101+
#ifdef GIT_EXPERIMENTAL_SHA256
47102
/** type of object id */
48103
unsigned char type;
104+
#endif
49105

50106
/** raw binary formatted id */
51107
unsigned char id[GIT_OID_MAX_SIZE];
52108
} git_oid;
53109

54-
/**
55-
* The binary representation of the null object ID.
56-
*/
57-
#define GIT_OID_SHA1_ZERO { GIT_OID_SHA1, { 0 } }
58-
#define GIT_OID_SHA256_ZERO { GIT_OID_SHA256, { 0 } }
59-
60-
/**
61-
* The string representation of the null object ID.
62-
*/
63-
#define GIT_OID_SHA1_HEXZERO "0000000000000000000000000000000000000000"
64-
#define GIT_OID_SHA256_HEXZERO "0000000000000000000000000000000000000000000000000000000000000000"
65-
66110
/**
67111
* Parse a hex formatted object id into a git_oid.
68112
*

src/cli/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
set(CLI_INCLUDES
22
"${libgit2_BINARY_DIR}/src/util"
3+
"${libgit2_BINARY_DIR}/include"
4+
"${libgit2_BINARY_DIR}/include/git2"
35
"${libgit2_SOURCE_DIR}/src/util"
46
"${libgit2_SOURCE_DIR}/src/cli"
57
"${libgit2_SOURCE_DIR}/include")
@@ -39,6 +41,7 @@ target_link_libraries(git2_cli ${CLI_LIBGIT2_LIBRARY} ${LIBGIT2_SYSTEM_LIBS})
3941

4042
set_target_properties(git2_cli PROPERTIES C_STANDARD 90)
4143
set_target_properties(git2_cli PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${libgit2_BINARY_DIR})
44+
set_target_properties(git2_cli PROPERTIES OUTPUT_NAME ${LIBGIT2_FILENAME})
4245

4346
ide_split_sources(git2_cli)
4447

src/libgit2/CMakeLists.txt

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ include(PkgBuildConfig)
99

1010
set(LIBGIT2_INCLUDES
1111
"${PROJECT_BINARY_DIR}/src/util"
12+
"${PROJECT_BINARY_DIR}/include"
13+
"${PROJECT_BINARY_DIR}/include/git2"
1214
"${PROJECT_SOURCE_DIR}/src/libgit2"
1315
"${PROJECT_SOURCE_DIR}/src/util"
1416
"${PROJECT_SOURCE_DIR}/include")
@@ -109,7 +111,7 @@ if(SONAME)
109111
endif()
110112
endif()
111113

112-
pkg_build_config(NAME libgit2
114+
pkg_build_config(NAME "${LIBGIT2_FILENAME}"
113115
VERSION ${libgit2_VERSION}
114116
DESCRIPTION "The git library, take 2"
115117
LIBS_SELF git2
@@ -122,10 +124,26 @@ if(MSVC_IDE)
122124
set_source_files_properties(win32/precompiled.c COMPILE_FLAGS "/Ycprecompiled.h")
123125
endif()
124126

127+
# support experimental features and functionality
128+
129+
configure_file(experimental.h.in "${PROJECT_BINARY_DIR}/include/git2/experimental.h")
130+
131+
# translate filenames in the git2.h so that they match the install directory
132+
# (allows for side-by-side installs of libgit2 and libgit2-experimental.)
133+
134+
FILE(READ "${PROJECT_SOURCE_DIR}/include/git2.h" LIBGIT2_INCLUDE)
135+ 10000
STRING(REGEX REPLACE "#include \"git2\/" "#include \"${LIBGIT2_FILENAME}/" LIBGIT2_INCLUDE "${LIBGIT2_INCLUDE}")
136+
FILE(WRITE "${PROJECT_BINARY_DIR}/include/${LIBGIT2_FILENAME}.h" ${LIBGIT2_INCLUDE})
137+
125138
# Install
139+
126140
install(TARGETS libgit2package
127141
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
128142
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
129143
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
130-
install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/git2 DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
131-
install(FILES ${PROJECT_SOURCE_DIR}/include/git2.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
144+
install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/git2/
145+
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${LIBGIT2_FILENAME}")
146+
install(FILES ${PROJECT_BINARY_DIR}/include/git2/experimental.h
147+
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${LIBGIT2_FILENAME}")
148+
install(FILES "${PROJECT_BINARY_DIR}/include/${LIBGIT2_FILENAME}.h"
149+
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})

src/libgit2/diff.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,10 @@ int git_diff_patchid(git_oid *out, git_diff *diff, git_diff_patchid_options *opt
381381
if ((error = (flush_hunk(&args.result, &args.ctx))) < 0)
382382
goto out;
383383

384+
#ifdef GIT_EXPERIMENTAL_SHA256
384385
args.result.type = GIT_OID_SHA1;
386+
#endif
387+
385388
git_oid_cpy(out, &args.result);
386389

387390
out:

src/libgit2/experimental.h.in

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#ifndef INCLUDE_experimental_h__
2+
#define INCLUDE_experimental_h__
3+
4+
#cmakedefine GIT_EXPERIMENTAL_SHA256 1
5+
6+
#endif

src/libgit2/indexer.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,7 +444,10 @@ static int store_object(git_indexer *idx)
444444
git__free(pentry);
445445
goto on_error;
446446
}
447+
448+
#ifdef GIT_EXPERIMENTAL_SHA256
447449
oid.type = GIT_OID_SHA1;
450+
#endif
448451

449452
entry_size = idx->off - entry_start;
450453
if (entry_start > UINT31_MAX) {

src/libgit2/object.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -520,7 +520,10 @@ static int git_object__short_id(git_str *out, const git_object *obj)
520520
memcpy(&id.id, &obj->cached.oid.id, (len + 1) / 2);
521521
if (len & 1)
522522
id.id[len / 2] &= 0xf0;
523+
524+
#ifdef GIT_EXPERIMENTAL_SHA256
523525
id.type = GIT_OID_SHA1;
526+
#endif
524527

525528
error = git_odb_exists_prefix(NULL, odb, &id, len);
526529
if (error != GIT_EAMBIGUOUS)
@@ -635,7 +638,7 @@ int git_object__write_oid_header(
635638
const char *header,
636639
const git_oid *oid)
637640
{
638-
size_t hex_size = git_oid_hexsize(oid->type);
641+
size_t hex_size = git_oid_hexsize(git_oid_type(oid));
639642
char hex_oid[GIT_OID_MAX_HEXSIZE];
640643

641644
if (!hex_size) {

src/libgit2/odb.c

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,10 @@ int git_odb__hashobj(git_oid *id, git_rawobj *obj, git_oid_t oid_type)
140140
vec[1].data = obj->data;
141141
vec[1].len = obj->len;
142142

143+
#ifdef GIT_EXPERIMENTAL_SHA256
143144
id->type = oid_type;
145+
#endif
146+
144147
return git_hash_vec(id->id, vec, 2, algorithm);
145148
}
146149

@@ -254,7 +257,10 @@ int git_odb__hashfd(
254257
}
255258

256259
error = git_hash_final(out->id, &ctx);
260+
261+
#ifdef GIT_EXPERIMENTAL_SHA256
257262
out->type = oid_type;
263+
#endif
258264

259265
done:
260266
git_hash_ctx_cleanup(&ctx);
@@ -1332,7 +1338,7 @@ int git_odb_read(git_odb_object **out, git_odb *db, const git_oid *id)
13321338
error = odb_read_1(out, db, id, true);
13331339

13341340
if (error == GIT_ENOTFOUND)
1335-
return git_odb__error_notfound("no match for id", id, git_oid_hexsize(id->type));
1341+
return git_odb__error_notfound("no match for id", id, git_oid_hexsize(git_oid_type(id)));
13361342

13371343
return error;
13381344
}
@@ -1679,7 +1685,10 @@ int git_odb_stream_finalize_write(git_oid *out, git_odb_stream *stream)
16791685
"stream_finalize_write()");
16801686

16811687
git_hash_final(out->id, stream->hash_ctx);
1688+
1689+
#ifdef GIT_EXPERIMENTAL_SHA256
16821690
out->type = stream->oid_type;
1691+
#endif
16831692

16841693
if (git_odb__freshen(stream->backend->odb, out))
16851694
return 0;
@@ -1858,8 +1867,8 @@ int git_odb__error_mismatch(const git_oid *expected, const git_oid *actual)
18581867
char expected_oid[GIT_OID_MAX_HEXSIZE + 1],
18591868
actual_oid[GIT_OID_MAX_HEXSIZE + 1];
18601869

1861-
git_oid_tostr(expected_oid, git_oi B023 d_hexsize(expected->type) + 1, expected);
1862-
git_oid_tostr(actual_oid, git_oid_hexsize(actual->type) + 1, actual);
1870+
git_oid_tostr(expected_oid, git_oid_hexsize(git_oid_type(expected)) + 1, expected);
1871+
git_oid_tostr(actual_oid, git_oid_hexsize(git_oid_type(actual)) + 1, actual);
18631872

18641873
git_error_set(GIT_ERROR_ODB, "object hash mismatch - expected %s but got %s",
18651874
expected_oid, actual_oid);

src/libgit2/odb_loose.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -737,7 +737,9 @@ GIT_INLINE(int) filename_to_oid(struct loose_backend *backend, git_oid *oid, con
737737
oid->id[1 + i/2] = (unsigned char) v;
738738
}
739739

740+
#ifdef GIT_EXPERIMENTAL_SHA256
740741
oid->type = backend->options.oid_type;
742+
#endif
741743

742744
return 0;
743745
}

0 commit comments

Comments
 (0)
0