summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/git2/common.h8
-rw-r--r--include/git2/odb_backend.h2
-rw-r--r--include/git2/transport.h12
-rw-r--r--include/git2/worktree.h12
-rw-r--r--src/blame_git.c14
-rw-r--r--src/config_cache.c1
-rw-r--r--src/config_file.c10
-rw-r--r--src/diff_parse.c6
-rw-r--r--src/filebuf.c11
-rw-r--r--src/filebuf.h4
-rw-r--r--src/fileops.c53
-rw-r--r--src/fileops.h25
-rw-r--r--src/hash/hash_collisiondetect.h12
-rw-r--r--src/hash/sha1dc/sha1.c1013
-rw-r--r--src/hash/sha1dc/sha1.h73
-rw-r--r--src/hash/sha1dc/ubc_check.c6
-rw-r--r--src/hash/sha1dc/ubc_check.h13
-rw-r--r--src/indexer.c30
-rw-r--r--src/indexer.h12
-rw-r--r--src/merge.c20
-rw-r--r--src/object.c1
-rw-r--r--src/object.h1
-rw-r--r--src/odb.c28
-rw-r--r--src/odb.h17
-rw-r--r--src/odb_loose.c20
-rw-r--r--src/odb_pack.c2
-rw-r--r--src/openssl_stream.c2
-rw-r--r--src/pack-objects.c4
-rw-r--r--src/pack-objects.h1
-rw-r--r--src/patch_parse.c4
-rw-r--r--src/posix.c2
-rw-r--r--src/posix.h6
-rw-r--r--src/rebase.c18
-rw-r--r--src/refdb_fs.c38
-rw-r--r--src/repository.c22
-rw-r--r--src/repository.h3
-rw-r--r--src/settings.c4
-rw-r--r--src/submodule.c24
-rw-r--r--src/unix/posix.h7
-rw-r--r--src/win32/posix_w32.c2
-rw-r--r--src/worktree.c148
-rw-r--r--src/worktree.h2
-rw-r--r--tests/core/posix.c5
-rw-r--r--tests/odb/loose.c55
-rw-r--r--tests/pack/packbuilder.c37
-rw-r--r--tests/refs/create.c68
-rw-r--r--tests/resources/submodules/testrepo/.gitted/config3
-rw-r--r--tests/worktree/open.c111
-rw-r--r--tests/worktree/refs.c26
-rw-r--r--tests/worktree/submodule.c92
-rw-r--r--tests/worktree/worktree.c7
51 files changed, 1666 insertions, 431 deletions
diff --git a/include/git2/common.h b/include/git2/common.h
index f13dfd509..c909f86ca 100644
--- a/include/git2/common.h
+++ b/include/git2/common.h
@@ -179,6 +179,7 @@ typedef enum {
GIT_OPT_SET_SSL_CIPHERS,
GIT_OPT_GET_USER_AGENT,
GIT_OPT_ENABLE_OFS_DELTA,
+ GIT_OPT_ENABLE_SYNCHRONOUS_OBJECT_CREATION,
} git_libgit2_opt_t;
/**
@@ -316,6 +317,13 @@ typedef enum {
* > Packfiles containing offset deltas can still be read.
* > This defaults to enabled.
*
+ * * opts(GIT_OPT_ENABLE_SYNCHRONOUS_OBJECT_CREATION, int enabled)
+ *
+ * > Enable synchronized writes of new objects using `fsync`
+ * > (or the platform equivalent) to ensure that new object data
+ * > is written to permanent storage, not simply cached. This
+ * > defaults to disabled.
+ *
* @param option Option key
* @param ... value to set the option
* @return 0 on success, <0 on failure
diff --git a/include/git2/odb_backend.h b/include/git2/odb_backend.h
index b17cfd8ba..9199538ce 100644
--- a/include/git2/odb_backend.h
+++ b/include/git2/odb_backend.h
@@ -39,7 +39,7 @@ GIT_EXTERN(int) git_odb_backend_pack(git_odb_backend **out, const char *objects_
* @param out location to store the odb backend pointer
* @param objects_dir the Git repository's objects directory
* @param compression_level zlib compression level to use
- * @param do_fsync whether to do an fsync() after writing (currently ignored)
+ * @param do_fsync whether to do an fsync() after writing
* @param dir_mode permissions to use creating a directory or 0 for defaults
* @param file_mode permissions to use creating a file or 0 for defaults
*
diff --git a/include/git2/transport.h b/include/git2/transport.h
index 0ec241699..0c371bf4b 100644
--- a/include/git2/transport.h
+++ b/include/git2/transport.h
@@ -321,13 +321,13 @@ GIT_EXTERN(void) git_cred_free(git_cred *cred);
/**
* Signature of a function which acquires a credential object.
*
- * - cred: The newly created credential object.
- * - url: The resource for which we are demanding a credential.
- * - username_from_url: The username that was embedded in a "user\@host"
+ * @param cred The newly created credential object.
+ * @param url The resource for which we are demanding a credential.
+ * @param username_from_url The username that was embedded in a "user\@host"
* remote url, or NULL if not included.
- * - allowed_types: A bitmask stating which cred types are OK to return.
- * - payload: The payload provided when specifying this callback.
- * - returns 0 for success, < 0 to indicate an error, > 0 to indicate
+ * @param allowed_types A bitmask stating which cred types are OK to return.
+ * @param payload The payload provided when specifying this callback.
+ * @return 0 for success, < 0 to indicate an error, > 0 to indicate
* no credential was acquired
*/
typedef int (*git_cred_acquire_cb)(
diff --git a/include/git2/worktree.h b/include/git2/worktree.h
index cad1284fa..4c4f9284d 100644
--- a/include/git2/worktree.h
+++ b/include/git2/worktree.h
@@ -44,6 +44,18 @@ GIT_EXTERN(int) git_worktree_list(git_strarray *out, git_repository *repo);
GIT_EXTERN(int) git_worktree_lookup(git_worktree **out, git_repository *repo, const char *name);
/**
+ * Open a worktree of a given repository
+ *
+ * If a repository is not the main tree but a worktree, this
+ * function will look up the worktree inside the parent
+ * repository and create a new `git_worktree` structure.
+ *
+ * @param out Out-pointer for the newly allocated worktree
+ * @param repo Repository to look up worktree for
+ */
+GIT_EXTERN(int) git_worktree_open_from_repository(git_worktree **out, git_repository *repo);
+
+/**
* Free a previously allocated worktree
*
* @param wt worktree handle to close. If NULL nothing occurs.
diff --git a/src/blame_git.c b/src/blame_git.c
index 96785c75b..735b62d95 100644
--- a/src/blame_git.c
+++ b/src/blame_git.c
@@ -478,14 +478,15 @@ cleanup:
* The blobs of origin and porigin exactly match, so everything origin is
* suspected for can be blamed on the parent.
*/
-static void pass_whole_blame(git_blame *blame,
+static int pass_whole_blame(git_blame *blame,
git_blame__origin *origin, git_blame__origin *porigin)
{
git_blame__entry *e;
- if (!porigin->blob)
- git_object_lookup((git_object**)&porigin->blob, blame->repository,
- git_blob_id(origin->blob), GIT_OBJ_BLOB);
+ if (!porigin->blob &&
+ git_object_lookup((git_object**)&porigin->blob, blame->repository,
+ git_blob_id(origin->blob), GIT_OBJ_BLOB) < 0)
+ return -1;
for (e=blame->ent; e; e=e->next) {
if (!same_suspect(e->suspect, origin))
continue;
@@ -493,6 +494,8 @@ static void pass_whole_blame(git_blame *blame,
origin_decref(e->suspect);
e->suspect = porigin;
}
+
+ return 0;
}
static int pass_blame(git_blame *blame, git_blame__origin *origin, uint32_t opt)
@@ -543,7 +546,8 @@ static int pass_blame(git_blame *blame, git_blame__origin *origin, uint32_t opt)
}
if (porigin->blob && origin->blob &&
!git_oid_cmp(git_blob_id(porigin->blob), git_blob_id(origin->blob))) {
- pass_whole_blame(blame, origin, porigin);
+ error = pass_whole_blame(blame, origin, porigin);
+ goto finish;
origin_decref(porigin);
goto finish;
}
diff --git a/src/config_cache.c b/src/config_cache.c
index dbea871b9..840722274 100644
--- a/src/config_cache.c
+++ b/src/config_cache.c
@@ -78,6 +78,7 @@ static struct map_data _cvar_maps[] = {
{"core.logallrefupdates", NULL, 0, GIT_LOGALLREFUPDATES_DEFAULT },
{"core.protecthfs", NULL, 0, GIT_PROTECTHFS_DEFAULT },
{"core.protectntfs", NULL, 0, GIT_PROTECTNTFS_DEFAULT },
+ {"core.fsyncobjectfiles", NULL, 0, GIT_FSYNCOBJECTFILES_DEFAULT },
};
int git_config__cvar(int *out, git_config *config, git_cvar_cached cvar)
diff --git a/src/config_file.c b/src/config_file.c
index cd5727c05..50c5a3d82 100644
--- a/src/config_file.c
+++ b/src/config_file.c
@@ -1041,8 +1041,9 @@ static int parse_section_header_ext(struct reader *reader, const char *line, con
GITERR_CHECK_ALLOC_ADD(&alloc_len, base_name_len, quoted_len);
GITERR_CHECK_ALLOC_ADD(&alloc_len, alloc_len, 2);
- git_buf_grow(&buf, alloc_len);
- git_buf_printf(&buf, "%s.", base_name);
+ if (git_buf_grow(&buf, alloc_len) < 0 ||
+ git_buf_printf(&buf, "%s.", base_name) < 0)
+ goto end_parse;
rpos = 0;
@@ -1082,6 +1083,11 @@ static int parse_section_header_ext(struct reader *reader, const char *line, con
} while (line + rpos < last_quote);
end_parse:
+ if (git_buf_oom(&buf)) {
+ git_buf_free(&buf);
+ return -1;
+ }
+
if (line[rpos] != '"' || line[rpos + 1] != ']') {
set_parse_error(reader, rpos, "Unexpected text after closing quotes");
git_buf_free(&buf);
diff --git a/src/diff_parse.c b/src/diff_parse.c
index 93915683e..24a8a4af6 100644
--- a/src/diff_parse.c
+++ b/src/diff_parse.c
@@ -44,7 +44,11 @@ static git_diff_parsed *diff_parsed_alloc(void)
diff->base.patch_fn = git_patch_parsed_from_diff;
diff->base.free_fn = diff_parsed_free;
- git_diff_init_options(&diff->base.opts, GIT_DIFF_OPTIONS_VERSION);
+ if (git_diff_init_options(&diff->base.opts, GIT_DIFF_OPTIONS_VERSION) < 0) {
+ git__free(&diff);
+ return NULL;
+ }
+
diff->base.opts.flags &= ~GIT_DIFF_IGNORE_CASE;
git_pool_init(&diff->base.pool, 1);
diff --git a/src/filebuf.c b/src/filebuf.c
index 825b9c04c..80250ccdf 100644
--- a/src/filebuf.c
+++ b/src/filebuf.c
@@ -291,6 +291,9 @@ int git_filebuf_open_withsize(git_filebuf *file, const char *path, int flags, mo
if (flags & GIT_FILEBUF_DO_NOT_BUFFER)
file->do_not_buffer = true;
+ if (flags & GIT_FILEBUF_FSYNC)
+ file->do_fsync = true;
+
file->buf_size = size;
file->buf_pos = 0;
file->fd = -1;
@@ -425,6 +428,11 @@ int git_filebuf_commit(git_filebuf *file)
file->fd_is_open = false;
+ if (file->do_fsync && p_fsync(file->fd) < 0) {
+ giterr_set(GITERR_OS, "failed to fsync '%s'", file->path_lock);
+ goto on_error;
+ }
+
if (p_close(file->fd) < 0) {
giterr_set(GITERR_OS, "failed to close file at '%s'", file->path_lock);
goto on_error;
@@ -437,6 +445,9 @@ int git_filebuf_commit(git_filebuf *file)
goto on_error;
}
+ if (file->do_fsync && git_futils_fsync_parent(file->path_original) < 0)
+ goto on_error;
+
file->did_rename = true;
git_filebuf_cleanup(file);
diff --git a/src/filebuf.h b/src/filebuf.h
index 467708d45..c65aea780 100644
--- a/src/filebuf.h
+++ b/src/filebuf.h
@@ -20,7 +20,8 @@
#define GIT_FILEBUF_FORCE (1 << 3)
#define GIT_FILEBUF_TEMPORARY (1 << 4)
#define GIT_FILEBUF_DO_NOT_BUFFER (1 << 5)
-#define GIT_FILEBUF_DEFLATE_SHIFT (6)
+#define GIT_FILEBUF_FSYNC (1 << 6)
+#define GIT_FILEBUF_DEFLATE_SHIFT (7)
#define GIT_FILELOCK_EXTENSION ".lock\0"
#define GIT_FILELOCK_EXTLENGTH 6
@@ -47,6 +48,7 @@ struct git_filebuf {
bool created_lock;
bool did_rename;
bool do_not_buffer;
+ bool do_fsync;
int last_error;
};
diff --git a/src/fileops.c b/src/fileops.c
index cc638ea5b..ad2a988a9 100644
--- a/src/fileops.c
+++ b/src/fileops.c
@@ -236,10 +236,16 @@ int git_futils_readbuffer(git_buf *buf, const char *path)
int git_futils_writebuffer(
const git_buf *buf, const char *path, int flags, mode_t mode)
{
- int fd, error = 0;
+ int fd, do_fsync = 0, error = 0;
- if (flags <= 0)
+ if (!flags)
flags = O_CREAT | O_TRUNC | O_WRONLY;
+
+ if ((flags & O_FSYNC) != 0)
+ do_fsync = 1;
+
+ flags &= ~O_FSYNC;
+
if (!mode)
mode = GIT_FILEMODE_BLOB;
@@ -254,8 +260,19 @@ int git_futils_writebuffer(
return error;
}
- if ((error = p_close(fd)) < 0)
+ if (do_fsync && (error = p_fsync(fd)) < 0) {
+ giterr_set(GITERR_OS, "could not fsync '%s'", path);
+ p_close(fd);
+ return error;
+ }
+
+ if ((error = p_close(fd)) < 0) {
giterr_set(GITERR_OS, "error while closing '%s'", path);
+ return error;
+ }
+
+ if (do_fsync && (flags & O_CREAT))
+ error = git_futils_fsync_parent(path);
return error;
}
@@ -1108,3 +1125,33 @@ void git_futils_filestamp_set_from_stat(
memset(stamp, 0, sizeof(*stamp));
}
}
+
+int git_futils_fsync_dir(const char *path)
+{
+#ifdef GIT_WIN32
+ GIT_UNUSED(path);
+ return 0;
+#else
+ int fd, error = -1;
+
+ if ((fd = p_open(path, O_RDONLY)) < 0) {
+ giterr_set(GITERR_OS, "failed to open directory '%s' for fsync", path);
+ return -1;
+ }
+
+ if ((error = p_fsync(fd)) < 0)
+ giterr_set(GITERR_OS, "failed to fsync directory '%s'", path);
+
+ p_close(fd);
+ return error;
+#endif
+}
+
+int git_futils_fsync_parent(const char *path)
+{
+ char *parent = git_path_dirname(path);
+ int error = git_futils_fsync_dir(parent);
+
+ git__free(parent);
+ return error;
+}
diff --git a/src/fileops.h b/src/fileops.h
index 65c96a6f5..46886b0d7 100644
--- a/src/fileops.h
+++ b/src/fileops.h
@@ -25,6 +25,13 @@ extern int git_futils_readbuffer_updated(
git_buf *obj, const char *path, git_oid *checksum, int *updated);
extern int git_futils_readbuffer_fd(git_buf *obj, git_file fd, size_t len);
+/* Additional constants for `git_futils_writebuffer`'s `open_flags`. We
+ * support these internally and they will be removed before the `open` call.
+ */
+#ifndef O_FSYNC
+# define O_FSYNC (1 << 31)
+#endif
+
extern int git_futils_writebuffer(
const git_buf *buf, const char *path, int open_flags, mode_t mode);
@@ -356,4 +363,22 @@ extern void git_futils_filestamp_set(
extern void git_futils_filestamp_set_from_stat(
git_futils_filestamp *stamp, struct stat *st);
+/**
+ * `fsync` the parent directory of the given path, if `fsync` is
+ * supported for directories on this platform.
+ *
+ * @param path Path of the directory to sync.
+ * @return 0 on success, -1 on error
+ */
+extern int git_futils_fsync_dir(const char *path);
+
+/**
+ * `fsync` the parent directory of the given path, if `fsync` is
+ * supported for directories on this platform.
+ *
+ * @param path Path of the file whose parent directory should be synced.
+ * @return 0 on success, -1 on error
+ */
+extern int git_futils_fsync_parent(const char *path);
+
#endif /* INCLUDE_fileops_h__ */
diff --git a/src/hash/hash_collisiondetect.h b/src/hash/hash_collisiondetect.h
index 2bb27ba14..5fdae8df6 100644
--- a/src/hash/hash_collisiondetect.h
+++ b/src/hash/hash_collisiondetect.h
@@ -28,18 +28,8 @@ GIT_INLINE(int) git_hash_init(git_hash_ctx *ctx)
GIT_INLINE(int) git_hash_update(git_hash_ctx *ctx, const void *data, size_t len)
{
- const char *p = data;
-
assert(ctx);
-
- /* We expect a size_t, but sha1dc only takes an int */
- while (len > INT_MAX) {
- SHA1DCUpdate(&ctx->c, p, INT_MAX);
- p += INT_MAX;
- len -= INT_MAX;
- }
-
- SHA1DCUpdate(&ctx->c, p, len);
+ SHA1DCUpdate(&ctx->c, data, len);
return 0;
}
diff --git a/src/hash/sha1dc/sha1.c b/src/hash/sha1dc/sha1.c
index c846a163e..8d12b832b 100644
--- a/src/hash/sha1dc/sha1.c
+++ b/src/hash/sha1dc/sha1.c
@@ -1,5 +1,5 @@
/***
-* Copyright 2017 Marc Stevens <marc@marc-stevens.nl>, Dan Shumow (danshu@microsoft.com)
+* Copyright 2017 Marc Stevens <marc@marc-stevens.nl>, Dan Shumow (danshu@microsoft.com)
* Distributed under the MIT Software License.
* See accompanying file LICENSE.txt or copy at
* https://opensource.org/licenses/MIT
@@ -8,16 +8,48 @@
#include <string.h>
#include <memory.h>
#include <stdio.h>
+#include <stdlib.h>
#include "sha1.h"
#include "ubc_check.h"
+
+/*
+ Because Little-Endian architectures are most common,
+ we only set BIGENDIAN if one of these conditions is met.
+ Note that all MSFT platforms are little endian,
+ so none of these will be defined under the MSC compiler.
+ If you are compiling on a big endian platform and your compiler does not define one of these,
+ you will have to add whatever macros your tool chain defines to indicate Big-Endianness.
+ */
+#if (defined(__BYTE_ORDER) && (__BYTE_ORDER == __BIG_ENDIAN)) || \
+ (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __BIG_ENDIAN__)) || \
+ defined(__BIG_ENDIAN__) || defined(__ARMEB__) || defined(__THUMBEB__) || defined(__AARCH64EB__) || \
+ defined(_MIPSEB) || defined(__MIPSEB) || defined(__MIPSEB__)
+
+#define BIGENDIAN (1)
+
+#endif /*ENDIANNESS SELECTION*/
+
#define rotate_right(x,n) (((x)>>(n))|((x)<<(32-(n))))
#define rotate_left(x,n) (((x)<<(n))|((x)>>(32-(n))))
+#define sha1_bswap32(x) \
+ {x = ((x << 8) & 0xFF00FF00) | ((x >> 8) & 0xFF00FF); x = (x << 16) | (x >> 16);}
+
+#define sha1_mix(W, t) (rotate_left(W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16], 1))
+
+#if defined(BIGENDIAN)
+ #define sha1_load(m, t, temp) { temp = m[t]; }
+#else
+ #define sha1_load(m, t, temp) { temp = m[t]; sha1_bswap32(temp); }
+#endif /*define(BIGENDIAN)*/
+
+#define sha1_store(W, t, x) *(volatile uint32_t *)&W[t] = x
+
#define sha1_f1(b,c,d) ((d)^((b)&((c)^(d))))
#define sha1_f2(b,c,d) ((b)^(c)^(d))
-#define sha1_f3(b,c,d) (((b) & ((c)|(d))) | ((c)&(d)))
+#define sha1_f3(b,c,d) (((b)&(c))+((d)&((b)^(c))))
#define sha1_f4(b,c,d) ((b)^(c)^(d))
#define HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, m, t) \
@@ -38,28 +70,36 @@
#define HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(a, b, c, d, e, m, t) \
{ b = rotate_right(b, 30); e -= rotate_left(a, 5) + sha1_f4(b,c,d) + 0xCA62C1D6 + m[t]; }
-#define SHA1_STORE_STATE(i) states[i][0] = a; states[i][1] = b; states[i][2] = c; states[i][3] = d; states[i][4] = e;
+#define SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(a, b, c, d, e, m, W, t, temp) \
+ {sha1_load(m, t, temp); sha1_store(W, t, temp); e += temp + rotate_left(a, 5) + sha1_f1(b,c,d) + 0x5A827999; b = rotate_left(b, 30);}
+#define SHA1COMPRESS_FULL_ROUND1_STEP_EXPAND(a, b, c, d, e, W, t, temp) \
+ {temp = sha1_mix(W, t); sha1_store(W, t, temp); e += temp + rotate_left(a, 5) + sha1_f1(b,c,d) + 0x5A827999; b = rotate_left(b, 30); }
+#define SHA1COMPRESS_FULL_ROUND2_STEP(a, b, c, d, e, W, t, temp) \
+ {temp = sha1_mix(W, t); sha1_store(W, t, temp); e += temp + rotate_left(a, 5) + sha1_f2(b,c,d) + 0x6ED9EBA1; b = rotate_left(b, 30); }
-void sha1_message_expansion(uint32_t W[80])
-{
- unsigned i;
+#define SHA1COMPRESS_FULL_ROUND3_STEP(a, b, c, d, e, W, t, temp) \
+ {temp = sha1_mix(W, t); sha1_store(W, t, temp); e += temp + rotate_left(a, 5) + sha1_f3(b,c,d) + 0x8F1BBCDC; b = rotate_left(b, 30); }
- for (i = 16; i < 80; ++i)
- W[i] = rotate_left(W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16], 1);
-}
+#define SHA1COMPRESS_FULL_ROUND4_STEP(a, b, c, d, e, W, t, temp) \
+ {temp = sha1_mix(W, t); sha1_store(W, t, temp); e += temp + rotate_left(a, 5) + sha1_f4(b,c,d) + 0xCA62C1D6; b = rotate_left(b, 30); }
+
+#define SHA1_STORE_STATE(i) states[i][0] = a; states[i][1] = b; states[i][2] = c; states[i][3] = d; states[i][4] = e;
+
+#ifdef BUILDNOCOLLDETECTSHA1COMPRESSION
void sha1_compression(uint32_t ihv[5], const uint32_t m[16])
{
- uint32_t a, b, c, d, e, W[80];
+ uint32_t W[80];
+ uint32_t a,b,c,d,e;
unsigned i;
memcpy(W, m, 16 * 4);
for (i = 16; i < 80; ++i)
- W[i] = rotate_left(W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16], 1);
+ W[i] = sha1_mix(W, i);
- a = ihv[0], b = ihv[1], c = ihv[2], d = ihv[3], e = ihv[4];
+ a = ihv[0]; b = ihv[1]; c = ihv[2]; d = ihv[3]; e = ihv[4];
HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, W, 0);
HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, W, 1);
@@ -147,10 +187,10 @@ void sha1_compression(uint32_t ihv[5], const uint32_t m[16])
ihv[0] += a; ihv[1] += b; ihv[2] += c; ihv[3] += d; ihv[4] += e;
}
+#endif /*BUILDNOCOLLDETECTSHA1COMPRESSION*/
-
-void sha1_compression_W(uint32_t ihv[5], const uint32_t W[80])
+static void sha1_compression_W(uint32_t ihv[5], const uint32_t W[80])
{
uint32_t a = ihv[0], b = ihv[1], c = ihv[2], d = ihv[3], e = ihv[4];
@@ -188,7 +228,7 @@ void sha1_compression_W(uint32_t ihv[5], const uint32_t W[80])
HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, W, 30);
HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, W, 31);
HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, W, 32);
- HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, W, 33);
+ HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, W, 33);
HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, W, 34);
HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, W, 35);
HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, W, 36);
@@ -243,416 +283,417 @@ void sha1_compression_W(uint32_t ihv[5], const uint32_t W[80])
-void sha1_compression_states(uint32_t ihv[5], const uint32_t W[80], uint32_t states[80][5])
+void sha1_compression_states(uint32_t ihv[5], const uint32_t m[16], uint32_t W[80], uint32_t states[80][5])
{
uint32_t a = ihv[0], b = ihv[1], c = ihv[2], d = ihv[3], e = ihv[4];
+ uint32_t temp;
#ifdef DOSTORESTATE00
SHA1_STORE_STATE(0)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, W, 0);
+ SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(a, b, c, d, e, m, W, 0, temp);
#ifdef DOSTORESTATE01
SHA1_STORE_STATE(1)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, W, 1);
+ SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(e, a, b, c, d, m, W, 1, temp);
#ifdef DOSTORESTATE02
SHA1_STORE_STATE(2)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, W, 2);
+ SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(d, e, a, b, c, m, W, 2, temp);
#ifdef DOSTORESTATE03
SHA1_STORE_STATE(3)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, W, 3);
+ SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(c, d, e, a, b, m, W, 3, temp);
#ifdef DOSTORESTATE04
SHA1_STORE_STATE(4)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, W, 4);
+ SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(b, c, d, e, a, m, W, 4, temp);
#ifdef DOSTORESTATE05
SHA1_STORE_STATE(5)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, W, 5);
+ SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(a, b, c, d, e, m, W, 5, temp);
#ifdef DOSTORESTATE06
SHA1_STORE_STATE(6)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, W, 6);
+ SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(e, a, b, c, d, m, W, 6, temp);
#ifdef DOSTORESTATE07
SHA1_STORE_STATE(7)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, W, 7);
+ SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(d, e, a, b, c, m, W, 7, temp);
#ifdef DOSTORESTATE08
SHA1_STORE_STATE(8)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, W, 8);
+ SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(c, d, e, a, b, m, W, 8, temp);
#ifdef DOSTORESTATE09
SHA1_STORE_STATE(9)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, W, 9);
+ SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(b, c, d, e, a, m, W, 9, temp);
#ifdef DOSTORESTATE10
SHA1_STORE_STATE(10)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, W, 10);
+ SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(a, b, c, d, e, m, W, 10, temp);
#ifdef DOSTORESTATE11
SHA1_STORE_STATE(11)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, W, 11);
+ SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(e, a, b, c, d, m, W, 11, temp);
#ifdef DOSTORESTATE12
SHA1_STORE_STATE(12)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, W, 12);
+ SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(d, e, a, b, c, m, W, 12, temp);
#ifdef DOSTORESTATE13
SHA1_STORE_STATE(13)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, W, 13);
+ SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(c, d, e, a, b, m, W, 13, temp);
#ifdef DOSTORESTATE14
SHA1_STORE_STATE(14)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, W, 14);
+ SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(b, c, d, e, a, m, W, 14, temp);
#ifdef DOSTORESTATE15
SHA1_STORE_STATE(15)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND1_STEP(a, b, c, d, e, W, 15);
+ SHA1COMPRESS_FULL_ROUND1_STEP_LOAD(a, b, c, d, e, m, W, 15, temp);
#ifdef DOSTORESTATE16
SHA1_STORE_STATE(16)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND1_STEP(e, a, b, c, d, W, 16);
+ SHA1COMPRESS_FULL_ROUND1_STEP_EXPAND(e, a, b, c, d, W, 16, temp);
#ifdef DOSTORESTATE17
SHA1_STORE_STATE(17)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND1_STEP(d, e, a, b, c, W, 17);
+ SHA1COMPRESS_FULL_ROUND1_STEP_EXPAND(d, e, a, b, c, W, 17, temp);
#ifdef DOSTORESTATE18
SHA1_STORE_STATE(18)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND1_STEP(c, d, e, a, b, W, 18);
+ SHA1COMPRESS_FULL_ROUND1_STEP_EXPAND(c, d, e, a, b, W, 18, temp);
#ifdef DOSTORESTATE19
SHA1_STORE_STATE(19)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND1_STEP(b, c, d, e, a, W, 19);
+ SHA1COMPRESS_FULL_ROUND1_STEP_EXPAND(b, c, d, e, a, W, 19, temp);
#ifdef DOSTORESTATE20
SHA1_STORE_STATE(20)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, W, 20);
+ SHA1COMPRESS_FULL_ROUND2_STEP(a, b, c, d, e, W, 20, temp);
#ifdef DOSTORESTATE21
SHA1_STORE_STATE(21)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, W, 21);
-
+ SHA1COMPRESS_FULL_ROUND2_STEP(e, a, b, c, d, W, 21, temp);
+
#ifdef DOSTORESTATE22
SHA1_STORE_STATE(22)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, W, 22);
-
+ SHA1COMPRESS_FULL_ROUND2_STEP(d, e, a, b, c, W, 22, temp);
+
#ifdef DOSTORESTATE23
SHA1_STORE_STATE(23)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, W, 23);
+ SHA1COMPRESS_FULL_ROUND2_STEP(c, d, e, a, b, W, 23, temp);
#ifdef DOSTORESTATE24
SHA1_STORE_STATE(24)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, W, 24);
+ SHA1COMPRESS_FULL_ROUND2_STEP(b, c, d, e, a, W, 24, temp);
#ifdef DOSTORESTATE25
SHA1_STORE_STATE(25)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, W, 25);
+ SHA1COMPRESS_FULL_ROUND2_STEP(a, b, c, d, e, W, 25, temp);
#ifdef DOSTORESTATE26
SHA1_STORE_STATE(26)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, W, 26);
+ SHA1COMPRESS_FULL_ROUND2_STEP(e, a, b, c, d, W, 26, temp);
#ifdef DOSTORESTATE27
SHA1_STORE_STATE(27)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, W, 27);
-
+ SHA1COMPRESS_FULL_ROUND2_STEP(d, e, a, b, c, W, 27, temp);
+
#ifdef DOSTORESTATE28
SHA1_STORE_STATE(28)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, W, 28);
-
+ SHA1COMPRESS_FULL_ROUND2_STEP(c, d, e, a, b, W, 28, temp);
+
#ifdef DOSTORESTATE29
SHA1_STORE_STATE(29)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, W, 29);
-
+ SHA1COMPRESS_FULL_ROUND2_STEP(b, c, d, e, a, W, 29, temp);
+
#ifdef DOSTORESTATE30
SHA1_STORE_STATE(30)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, W, 30);
-
+ SHA1COMPRESS_FULL_ROUND2_STEP(a, b, c, d, e, W, 30, temp);
+
#ifdef DOSTORESTATE31
SHA1_STORE_STATE(31)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, W, 31);
-
+ SHA1COMPRESS_FULL_ROUND2_STEP(e, a, b, c, d, W, 31, temp);
+
#ifdef DOSTORESTATE32
SHA1_STORE_STATE(32)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, W, 32);
+ SHA1COMPRESS_FULL_ROUND2_STEP(d, e, a, b, c, W, 32, temp);
#ifdef DOSTORESTATE33
SHA1_STORE_STATE(33)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, W, 33);
+ SHA1COMPRESS_FULL_ROUND2_STEP(c, d, e, a, b, W, 33, temp);
#ifdef DOSTORESTATE34
SHA1_STORE_STATE(34)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, W, 34);
+ SHA1COMPRESS_FULL_ROUND2_STEP(b, c, d, e, a, W, 34, temp);
#ifdef DOSTORESTATE35
SHA1_STORE_STATE(35)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND2_STEP(a, b, c, d, e, W, 35);
-
+ SHA1COMPRESS_FULL_ROUND2_STEP(a, b, c, d, e, W, 35, temp);
+
#ifdef DOSTORESTATE36
SHA1_STORE_STATE(36)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND2_STEP(e, a, b, c, d, W, 36);
-
+ SHA1COMPRESS_FULL_ROUND2_STEP(e, a, b, c, d, W, 36, temp);
+
#ifdef DOSTORESTATE37
SHA1_STORE_STATE(37)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND2_STEP(d, e, a, b, c, W, 37);
-
+ SHA1COMPRESS_FULL_ROUND2_STEP(d, e, a, b, c, W, 37, temp);
+
#ifdef DOSTORESTATE38
SHA1_STORE_STATE(38)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND2_STEP(c, d, e, a, b, W, 38);
-
+ SHA1COMPRESS_FULL_ROUND2_STEP(c, d, e, a, b, W, 38, temp);
+
#ifdef DOSTORESTATE39
SHA1_STORE_STATE(39)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND2_STEP(b, c, d, e, a, W, 39);
+ SHA1COMPRESS_FULL_ROUND2_STEP(b, c, d, e, a, W, 39, temp);
#ifdef DOSTORESTATE40
SHA1_STORE_STATE(40)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, W, 40);
+ SHA1COMPRESS_FULL_ROUND3_STEP(a, b, c, d, e, W, 40, temp);
#ifdef DOSTORESTATE41
SHA1_STORE_STATE(41)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, W, 41);
+ SHA1COMPRESS_FULL_ROUND3_STEP(e, a, b, c, d, W, 41, temp);
#ifdef DOSTORESTATE42
SHA1_STORE_STATE(42)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, W, 42);
+ SHA1COMPRESS_FULL_ROUND3_STEP(d, e, a, b, c, W, 42, temp);
#ifdef DOSTORESTATE43
SHA1_STORE_STATE(43)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, W, 43);
+ SHA1COMPRESS_FULL_ROUND3_STEP(c, d, e, a, b, W, 43, temp);
#ifdef DOSTORESTATE44
SHA1_STORE_STATE(44)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, W, 44);
+ SHA1COMPRESS_FULL_ROUND3_STEP(b, c, d, e, a, W, 44, temp);
#ifdef DOSTORESTATE45
SHA1_STORE_STATE(45)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, W, 45);
+ SHA1COMPRESS_FULL_ROUND3_STEP(a, b, c, d, e, W, 45, temp);
#ifdef DOSTORESTATE46
SHA1_STORE_STATE(46)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, W, 46);
+ SHA1COMPRESS_FULL_ROUND3_STEP(e, a, b, c, d, W, 46, temp);
#ifdef DOSTORESTATE47
SHA1_STORE_STATE(47)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, W, 47);
+ SHA1COMPRESS_FULL_ROUND3_STEP(d, e, a, b, c, W, 47, temp);
#ifdef DOSTORESTATE48
SHA1_STORE_STATE(48)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, W, 48);
+ SHA1COMPRESS_FULL_ROUND3_STEP(c, d, e, a, b, W, 48, temp);
#ifdef DOSTORESTATE49
SHA1_STORE_STATE(49)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, W, 49);
+ SHA1COMPRESS_FULL_ROUND3_STEP(b, c, d, e, a, W, 49, temp);
#ifdef DOSTORESTATE50
SHA1_STORE_STATE(50)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, W, 50);
+ SHA1COMPRESS_FULL_ROUND3_STEP(a, b, c, d, e, W, 50, temp);
#ifdef DOSTORESTATE51
SHA1_STORE_STATE(51)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, W, 51);
+ SHA1COMPRESS_FULL_ROUND3_STEP(e, a, b, c, d, W, 51, temp);
#ifdef DOSTORESTATE52
SHA1_STORE_STATE(52)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, W, 52);
+ SHA1COMPRESS_FULL_ROUND3_STEP(d, e, a, b, c, W, 52, temp);
#ifdef DOSTORESTATE53
SHA1_STORE_STATE(53)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, W, 53);
+ SHA1COMPRESS_FULL_ROUND3_STEP(c, d, e, a, b, W, 53, temp);
#ifdef DOSTORESTATE54
SHA1_STORE_STATE(54)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, W, 54);
+ SHA1COMPRESS_FULL_ROUND3_STEP(b, c, d, e, a, W, 54, temp);
#ifdef DOSTORESTATE55
SHA1_STORE_STATE(55)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND3_STEP(a, b, c, d, e, W, 55);
+ SHA1COMPRESS_FULL_ROUND3_STEP(a, b, c, d, e, W, 55, temp);
#ifdef DOSTORESTATE56
SHA1_STORE_STATE(56)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND3_STEP(e, a, b, c, d, W, 56);
+ SHA1COMPRESS_FULL_ROUND3_STEP(e, a, b, c, d, W, 56, temp);
#ifdef DOSTORESTATE57
SHA1_STORE_STATE(57)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND3_STEP(d, e, a, b, c, W, 57);
+ SHA1COMPRESS_FULL_ROUND3_STEP(d, e, a, b, c, W, 57, temp);
#ifdef DOSTORESTATE58
SHA1_STORE_STATE(58)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND3_STEP(c, d, e, a, b, W, 58);
+ SHA1COMPRESS_FULL_ROUND3_STEP(c, d, e, a, b, W, 58, temp);
#ifdef DOSTORESTATE59
SHA1_STORE_STATE(59)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND3_STEP(b, c, d, e, a, W, 59);
-
+ SHA1COMPRESS_FULL_ROUND3_STEP(b, c, d, e, a, W, 59, temp);
+
#ifdef DOSTORESTATE60
SHA1_STORE_STATE(60)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, W, 60);
+ SHA1COMPRESS_FULL_ROUND4_STEP(a, b, c, d, e, W, 60, temp);
#ifdef DOSTORESTATE61
SHA1_STORE_STATE(61)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, W, 61);
+ SHA1COMPRESS_FULL_ROUND4_STEP(e, a, b, c, d, W, 61, temp);
#ifdef DOSTORESTATE62
SHA1_STORE_STATE(62)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, W, 62);
+ SHA1COMPRESS_FULL_ROUND4_STEP(d, e, a, b, c, W, 62, temp);
#ifdef DOSTORESTATE63
SHA1_STORE_STATE(63)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, W, 63);
+ SHA1COMPRESS_FULL_ROUND4_STEP(c, d, e, a, b, W, 63, temp);
#ifdef DOSTORESTATE64
SHA1_STORE_STATE(64)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, W, 64);
+ SHA1COMPRESS_FULL_ROUND4_STEP(b, c, d, e, a, W, 64, temp);
#ifdef DOSTORESTATE65
SHA1_STORE_STATE(65)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, W, 65);
+ SHA1COMPRESS_FULL_ROUND4_STEP(a, b, c, d, e, W, 65, temp);
#ifdef DOSTORESTATE66
SHA1_STORE_STATE(66)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, W, 66);
+ SHA1COMPRESS_FULL_ROUND4_STEP(e, a, b, c, d, W, 66, temp);
#ifdef DOSTORESTATE67
SHA1_STORE_STATE(67)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, W, 67);
+ SHA1COMPRESS_FULL_ROUND4_STEP(d, e, a, b, c, W, 67, temp);
#ifdef DOSTORESTATE68
SHA1_STORE_STATE(68)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, W, 68);
+ SHA1COMPRESS_FULL_ROUND4_STEP(c, d, e, a, b, W, 68, temp);
#ifdef DOSTORESTATE69
SHA1_STORE_STATE(69)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, W, 69);
+ SHA1COMPRESS_FULL_ROUND4_STEP(b, c, d, e, a, W, 69, temp);
#ifdef DOSTORESTATE70
SHA1_STORE_STATE(70)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, W, 70);
+ SHA1COMPRESS_FULL_ROUND4_STEP(a, b, c, d, e, W, 70, temp);
#ifdef DOSTORESTATE71
SHA1_STORE_STATE(71)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, W, 71);
+ SHA1COMPRESS_FULL_ROUND4_STEP(e, a, b, c, d, W, 71, temp);
#ifdef DOSTORESTATE72
SHA1_STORE_STATE(72)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, W, 72);
+ SHA1COMPRESS_FULL_ROUND4_STEP(d, e, a, b, c, W, 72, temp);
#ifdef DOSTORESTATE73
SHA1_STORE_STATE(73)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, W, 73);
+ SHA1COMPRESS_FULL_ROUND4_STEP(c, d, e, a, b, W, 73, temp);
#ifdef DOSTORESTATE74
SHA1_STORE_STATE(74)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, W, 74);
+ SHA1COMPRESS_FULL_ROUND4_STEP(b, c, d, e, a, W, 74, temp);
#ifdef DOSTORESTATE75
SHA1_STORE_STATE(75)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND4_STEP(a, b, c, d, e, W, 75);
+ SHA1COMPRESS_FULL_ROUND4_STEP(a, b, c, d, e, W, 75, temp);
#ifdef DOSTORESTATE76
SHA1_STORE_STATE(76)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND4_STEP(e, a, b, c, d, W, 76);
+ SHA1COMPRESS_FULL_ROUND4_STEP(e, a, b, c, d, W, 76, temp);
#ifdef DOSTORESTATE77
SHA1_STORE_STATE(77)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND4_STEP(d, e, a, b, c, W, 77);
+ SHA1COMPRESS_FULL_ROUND4_STEP(d, e, a, b, c, W, 77, temp);
#ifdef DOSTORESTATE78
SHA1_STORE_STATE(78)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, W, 78);
+ SHA1COMPRESS_FULL_ROUND4_STEP(c, d, e, a, b, W, 78, temp);
#ifdef DOSTORESTATE79
SHA1_STORE_STATE(79)
#endif
- HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, W, 79);
+ SHA1COMPRESS_FULL_ROUND4_STEP(b, c, d, e, a, W, 79, temp);
@@ -663,7 +704,7 @@ void sha1_compression_states(uint32_t ihv[5], const uint32_t W[80], uint32_t sta
#define SHA1_RECOMPRESS(t) \
-void sha1recompress_fast_ ## t (uint32_t ihvin[5], uint32_t ihvout[5], const uint32_t me2[80], const uint32_t state[5]) \
+static void sha1recompress_fast_ ## t (uint32_t ihvin[5], uint32_t ihvout[5], const uint32_t me2[80], const uint32_t state[5]) \
{ \
uint32_t a = state[0], b = state[1], c = state[2], d = state[3], e = state[4]; \
if (t > 79) HASHCLASH_SHA1COMPRESS_ROUND4_STEP_BW(b, c, d, e, a, me2, 79); \
@@ -829,180 +870,794 @@ void sha1recompress_fast_ ## t (uint32_t ihvin[5], uint32_t ihvout[5], const uin
if (t <= 78) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(c, d, e, a, b, me2, 78); \
if (t <= 79) HASHCLASH_SHA1COMPRESS_ROUND4_STEP(b, c, d, e, a, me2, 79); \
ihvout[0] = ihvin[0] + a; ihvout[1] = ihvin[1] + b; ihvout[2] = ihvin[2] + c; ihvout[3] = ihvin[3] + d; ihvout[4] = ihvin[4] + e; \
-}
+}
+#ifdef DOSTORESTATE0
SHA1_RECOMPRESS(0)
+#endif
+
+#ifdef DOSTORESTATE1
SHA1_RECOMPRESS(1)
+#endif
+
+#ifdef DOSTORESTATE2
SHA1_RECOMPRESS(2)
+#endif
+
+#ifdef DOSTORESTATE3
SHA1_RECOMPRESS(3)
+#endif
+
+#ifdef DOSTORESTATE4
SHA1_RECOMPRESS(4)
+#endif
+
+#ifdef DOSTORESTATE5
SHA1_RECOMPRESS(5)
+#endif
+
+#ifdef DOSTORESTATE6
SHA1_RECOMPRESS(6)
+#endif
+
+#ifdef DOSTORESTATE7
SHA1_RECOMPRESS(7)
+#endif
+
+#ifdef DOSTORESTATE8
SHA1_RECOMPRESS(8)
+#endif
+
+#ifdef DOSTORESTATE9
SHA1_RECOMPRESS(9)
+#endif
+#ifdef DOSTORESTATE10
SHA1_RECOMPRESS(10)
+#endif
+
+#ifdef DOSTORESTATE11
SHA1_RECOMPRESS(11)
+#endif
+
+#ifdef DOSTORESTATE12
SHA1_RECOMPRESS(12)
+#endif
+
+#ifdef DOSTORESTATE13
SHA1_RECOMPRESS(13)
+#endif
+
+#ifdef DOSTORESTATE14
SHA1_RECOMPRESS(14)
+#endif
+
+#ifdef DOSTORESTATE15
SHA1_RECOMPRESS(15)
+#endif
+
+#ifdef DOSTORESTATE16
SHA1_RECOMPRESS(16)
+#endif
+
+#ifdef DOSTORESTATE17
SHA1_RECOMPRESS(17)
+#endif
+
+#ifdef DOSTORESTATE18
SHA1_RECOMPRESS(18)
+#endif
+
+#ifdef DOSTORESTATE19
SHA1_RECOMPRESS(19)
+#endif
+#ifdef DOSTORESTATE20
SHA1_RECOMPRESS(20)
+#endif
+
+#ifdef DOSTORESTATE21
SHA1_RECOMPRESS(21)
+#endif
+
+#ifdef DOSTORESTATE22
SHA1_RECOMPRESS(22)
+#endif
+
+#ifdef DOSTORESTATE23
SHA1_RECOMPRESS(23)
+#endif
+
+#ifdef DOSTORESTATE24
SHA1_RECOMPRESS(24)
+#endif
+
+#ifdef DOSTORESTATE25
SHA1_RECOMPRESS(25)
+#endif
+
+#ifdef DOSTORESTATE26
SHA1_RECOMPRESS(26)
+#endif
+
+#ifdef DOSTORESTATE27
SHA1_RECOMPRESS(27)
+#endif
+
+#ifdef DOSTORESTATE28
SHA1_RECOMPRESS(28)
+#endif
+
+#ifdef DOSTORESTATE29
SHA1_RECOMPRESS(29)
+#endif
+#ifdef DOSTORESTATE30
SHA1_RECOMPRESS(30)
+#endif
+
+#ifdef DOSTORESTATE31
SHA1_RECOMPRESS(31)
+#endif
+
+#ifdef DOSTORESTATE32
SHA1_RECOMPRESS(32)
+#endif
+
+#ifdef DOSTORESTATE33
SHA1_RECOMPRESS(33)
+#endif
+
+#ifdef DOSTORESTATE34
SHA1_RECOMPRESS(34)
+#endif
+
+#ifdef DOSTORESTATE35
SHA1_RECOMPRESS(35)
+#endif
+
+#ifdef DOSTORESTATE36
SHA1_RECOMPRESS(36)
+#endif
+
+#ifdef DOSTORESTATE37
SHA1_RECOMPRESS(37)
+#endif
+
+#ifdef DOSTORESTATE38
SHA1_RECOMPRESS(38)
+#endif
+
+#ifdef DOSTORESTATE39
SHA1_RECOMPRESS(39)
+#endif
+#ifdef DOSTORESTATE40
SHA1_RECOMPRESS(40)
+#endif
+
+#ifdef DOSTORESTATE41
SHA1_RECOMPRESS(41)
+#endif
+
+#ifdef DOSTORESTATE42
SHA1_RECOMPRESS(42)
+#endif
+
+#ifdef DOSTORESTATE43
SHA1_RECOMPRESS(43)
+#endif
+
+#ifdef DOSTORESTATE44
SHA1_RECOMPRESS(44)
+#endif
+
+#ifdef DOSTORESTATE45
SHA1_RECOMPRESS(45)
+#endif
+
+#ifdef DOSTORESTATE46
SHA1_RECOMPRESS(46)
+#endif
+
+#ifdef DOSTORESTATE47
SHA1_RECOMPRESS(47)
+#endif
+
+#ifdef DOSTORESTATE48
SHA1_RECOMPRESS(48)
+#endif
+
+#ifdef DOSTORESTATE49
SHA1_RECOMPRESS(49)
+#endif
+#ifdef DOSTORESTATE50
SHA1_RECOMPRESS(50)
+#endif
+
+#ifdef DOSTORESTATE51
SHA1_RECOMPRESS(51)
+#endif
+
+#ifdef DOSTORESTATE52
SHA1_RECOMPRESS(52)
+#endif
+
+#ifdef DOSTORESTATE53
SHA1_RECOMPRESS(53)
+#endif
+
+#ifdef DOSTORESTATE54
SHA1_RECOMPRESS(54)
+#endif
+
+#ifdef DOSTORESTATE55
SHA1_RECOMPRESS(55)
+#endif
+
+#ifdef DOSTORESTATE56
SHA1_RECOMPRESS(56)
+#endif
+
+#ifdef DOSTORESTATE57
SHA1_RECOMPRESS(57)
+#endif
+
+#ifdef DOSTORESTATE58
SHA1_RECOMPRESS(58)
+#endif
+
+#ifdef DOSTORESTATE59
SHA1_RECOMPRESS(59)
+#endif
+#ifdef DOSTORESTATE60
SHA1_RECOMPRESS(60)
+#endif
+
+#ifdef DOSTORESTATE61
SHA1_RECOMPRESS(61)
+#endif
+
+#ifdef DOSTORESTATE62
SHA1_RECOMPRESS(62)
+#endif
+
+#ifdef DOSTORESTATE63
SHA1_RECOMPRESS(63)
+#endif
+
+#ifdef DOSTORESTATE64
SHA1_RECOMPRESS(64)
+#endif
+
+#ifdef DOSTORESTATE65
SHA1_RECOMPRESS(65)
+#endif
+
+#ifdef DOSTORESTATE66
SHA1_RECOMPRESS(66)
+#endif
+
+#ifdef DOSTORESTATE67
SHA1_RECOMPRESS(67)
+#endif
+
+#ifdef DOSTORESTATE68
SHA1_RECOMPRESS(68)
+#endif
+
+#ifdef DOSTORESTATE69
SHA1_RECOMPRESS(69)
+#endif
+#ifdef DOSTORESTATE70
SHA1_RECOMPRESS(70)
+#endif
+
+#ifdef DOSTORESTATE71
SHA1_RECOMPRESS(71)
+#endif
+
+#ifdef DOSTORESTATE72
SHA1_RECOMPRESS(72)
+#endif
+
+#ifdef DOSTORESTATE73
SHA1_RECOMPRESS(73)
+#endif
+
+#ifdef DOSTORESTATE74
SHA1_RECOMPRESS(74)
+#endif
+
+#ifdef DOSTORESTATE75
SHA1_RECOMPRESS(75)
+#endif
+
+#ifdef DOSTORESTATE76
SHA1_RECOMPRESS(76)
+#endif
+
+#ifdef DOSTORESTATE77
SHA1_RECOMPRESS(77)
+#endif
+
+#ifdef DOSTORESTATE78
SHA1_RECOMPRESS(78)
+#endif
+
+#ifdef DOSTORESTATE79
SHA1_RECOMPRESS(79)
+#endif
-sha1_recompression_type sha1_recompression_step[80] =
+static void sha1_recompression_step(uint32_t step, uint32_t ihvin[5], uint32_t ihvout[5], const uint32_t me2[80], const uint32_t state[5])
{
- sha1recompress_fast_0, sha1recompress_fast_1, sha1recompress_fast_2, sha1recompress_fast_3, sha1recompress_fast_4, sha1recompress_fast_5, sha1recompress_fast_6, sha1recompress_fast_7, sha1recompress_fast_8, sha1recompress_fast_9,
- sha1recompress_fast_10, sha1recompress_fast_11, sha1recompress_fast_12, sha1recompress_fast_13, sha1recompress_fast_14, sha1recompress_fast_15, sha1recompress_fast_16, sha1recompress_fast_17, sha1recompress_fast_18, sha1recompress_fast_19,
- sha1recompress_fast_20, sha1recompress_fast_21, sha1recompress_fast_22, sha1recompress_fast_23, sha1recompress_fast_24, sha1recompress_fast_25, sha1recompress_fast_26, sha1recompress_fast_27, sha1recompress_fast_28, sha1recompress_fast_29,
- sha1recompress_fast_30, sha1recompress_fast_31, sha1recompress_fast_32, sha1recompress_fast_33, sha1recompress_fast_34, sha1recompress_fast_35, sha1recompress_fast_36, sha1recompress_fast_37, sha1recompress_fast_38, sha1recompress_fast_39,
- sha1recompress_fast_40, sha1recompress_fast_41, sha1recompress_fast_42, sha1recompress_fast_43, sha1recompress_fast_44, sha1recompress_fast_45, sha1recompress_fast_46, sha1recompress_fast_47, sha1recompress_fast_48, sha1recompress_fast_49,
- sha1recompress_fast_50, sha1recompress_fast_51, sha1recompress_fast_52, sha1recompress_fast_53, sha1recompress_fast_54, sha1recompress_fast_55, sha1recompress_fast_56, sha1recompress_fast_57, sha1recompress_fast_58, sha1recompress_fast_59,
- sha1recompress_fast_60, sha1recompress_fast_61, sha1recompress_fast_62, sha1recompress_fast_63, sha1recompress_fast_64, sha1recompress_fast_65, sha1recompress_fast_66, sha1recompress_fast_67, sha1recompress_fast_68, sha1recompress_fast_69,
- sha1recompress_fast_70, sha1recompress_fast_71, sha1recompress_fast_72, sha1recompress_fast_73, sha1recompress_fast_74, sha1recompress_fast_75, sha1recompress_fast_76, sha1recompress_fast_77, sha1recompress_fast_78, sha1recompress_fast_79,
-};
-
+ switch (step)
+ {
+#ifdef DOSTORESTATE0
+ case 0:
+ sha1recompress_fast_0(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE1
+ case 1:
+ sha1recompress_fast_1(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE2
+ case 2:
+ sha1recompress_fast_2(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE3
+ case 3:
+ sha1recompress_fast_3(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE4
+ case 4:
+ sha1recompress_fast_4(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE5
+ case 5:
+ sha1recompress_fast_5(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE6
+ case 6:
+ sha1recompress_fast_6(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE7
+ case 7:
+ sha1recompress_fast_7(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE8
+ case 8:
+ sha1recompress_fast_8(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE9
+ case 9:
+ sha1recompress_fast_9(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE10
+ case 10:
+ sha1recompress_fast_10(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE11
+ case 11:
+ sha1recompress_fast_11(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE12
+ case 12:
+ sha1recompress_fast_12(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE13
+ case 13:
+ sha1recompress_fast_13(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE14
+ case 14:
+ sha1recompress_fast_14(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE15
+ case 15:
+ sha1recompress_fast_15(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE16
+ case 16:
+ sha1recompress_fast_16(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE17
+ case 17:
+ sha1recompress_fast_17(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE18
+ case 18:
+ sha1recompress_fast_18(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE19
+ case 19:
+ sha1recompress_fast_19(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE20
+ case 20:
+ sha1recompress_fast_20(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE21
+ case 21:
+ sha1recompress_fast_21(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE22
+ case 22:
+ sha1recompress_fast_22(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE23
+ case 23:
+ sha1recompress_fast_23(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE24
+ case 24:
+ sha1recompress_fast_24(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE25
+ case 25:
+ sha1recompress_fast_25(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE26
+ case 26:
+ sha1recompress_fast_26(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE27
+ case 27:
+ sha1recompress_fast_27(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE28
+ case 28:
+ sha1recompress_fast_28(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE29
+ case 29:
+ sha1recompress_fast_29(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE30
+ case 30:
+ sha1recompress_fast_30(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE31
+ case 31:
+ sha1recompress_fast_31(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE32
+ case 32:
+ sha1recompress_fast_32(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE33
+ case 33:
+ sha1recompress_fast_33(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE34
+ case 34:
+ sha1recompress_fast_34(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE35
+ case 35:
+ sha1recompress_fast_35(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE36
+ case 36:
+ sha1recompress_fast_36(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE37
+ case 37:
+ sha1recompress_fast_37(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE38
+ case 38:
+ sha1recompress_fast_38(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE39
+ case 39:
+ sha1recompress_fast_39(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE40
+ case 40:
+ sha1recompress_fast_40(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE41
+ case 41:
+ sha1recompress_fast_41(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE42
+ case 42:
+ sha1recompress_fast_42(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE43
+ case 43:
+ sha1recompress_fast_43(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE44
+ case 44:
+ sha1recompress_fast_44(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE45
+ case 45:
+ sha1recompress_fast_45(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE46
+ case 46:
+ sha1recompress_fast_46(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE47
+ case 47:
+ sha1recompress_fast_47(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE48
+ case 48:
+ sha1recompress_fast_48(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE49
+ case 49:
+ sha1recompress_fast_49(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE50
+ case 50:
+ sha1recompress_fast_50(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE51
+ case 51:
+ sha1recompress_fast_51(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE52
+ case 52:
+ sha1recompress_fast_52(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE53
+ case 53:
+ sha1recompress_fast_53(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE54
+ case 54:
+ sha1recompress_fast_54(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE55
+ case 55:
+ sha1recompress_fast_55(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE56
+ case 56:
+ sha1recompress_fast_56(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE57
+ case 57:
+ sha1recompress_fast_57(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE58
+ case 58:
+ sha1recompress_fast_58(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE59
+ case 59:
+ sha1recompress_fast_59(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE60
+ case 60:
+ sha1recompress_fast_60(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE61
+ case 61:
+ sha1recompress_fast_61(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE62
+ case 62:
+ sha1recompress_fast_62(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE63
+ case 63:
+ sha1recompress_fast_63(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE64
+ case 64:
+ sha1recompress_fast_64(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE65
+ case 65:
+ sha1recompress_fast_65(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE66
+ case 66:
+ sha1recompress_fast_66(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE67
+ case 67:
+ sha1recompress_fast_67(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE68
+ case 68:
+ sha1recompress_fast_68(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE69
+ case 69:
+ sha1recompress_fast_69(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE70
+ case 70:
+ sha1recompress_fast_70(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE71
+ case 71:
+ sha1recompress_fast_71(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE72
+ case 72:
+ sha1recompress_fast_72(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE73
+ case 73:
+ sha1recompress_fast_73(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE74
+ case 74:
+ sha1recompress_fast_74(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE75
+ case 75:
+ sha1recompress_fast_75(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE76
+ case 76:
+ sha1recompress_fast_76(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE77
+ case 77:
+ sha1recompress_fast_77(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE78
+ case 78:
+ sha1recompress_fast_78(ihvin, ihvout, me2, state);
+ break;
+#endif
+#ifdef DOSTORESTATE79
+ case 79:
+ sha1recompress_fast_79(ihvin, ihvout, me2, state);
+ break;
+#endif
+ default:
+ abort();
+ }
+}
-void sha1_process(SHA1_CTX* ctx, const uint32_t block[16])
+static void sha1_process(SHA1_CTX* ctx, const uint32_t block[16])
{
unsigned i, j;
- uint32_t ubc_dv_mask[DVMASKSIZE];
+ uint32_t ubc_dv_mask[DVMASKSIZE] = { 0xFFFFFFFF };
uint32_t ihvtmp[5];
- for (i=0; i < DVMASKSIZE; ++i)
- ubc_dv_mask[i]=0;
+
ctx->ihv1[0] = ctx->ihv[0];
ctx->ihv1[1] = ctx->ihv[1];
ctx->ihv1[2] = ctx->ihv[2];
ctx->ihv1[3] = ctx->ihv[3];
ctx->ihv1[4] = ctx->ihv[4];
- memcpy(ctx->m1, block, 64);
- sha1_message_expansion(ctx->m1);
- if (ctx->detect_coll && ctx->ubc_check)
- {
- ubc_check(ctx->m1, ubc_dv_mask);
- }
- sha1_compression_states(ctx->ihv, ctx->m1, ctx->states);
+
+ sha1_compression_states(ctx->ihv, block, ctx->m1, ctx->states);
+
if (ctx->detect_coll)
{
- for (i = 0; sha1_dvs[i].dvType != 0; ++i)
+ if (ctx->ubc_check)
+ {
+ ubc_check(ctx->m1, ubc_dv_mask);
+ }
+
+ if (ubc_dv_mask[0] != 0)
{
- if ((0 == ctx->ubc_check) || (((uint32_t)(1) << sha1_dvs[i].maskb) & ubc_dv_mask[sha1_dvs[i].maski]))
+ for (i = 0; sha1_dvs[i].dvType != 0; ++i)
{
- for (j = 0; j < 80; ++j)
- ctx->m2[j] = ctx->m1[j] ^ sha1_dvs[i].dm[j];
- (sha1_recompression_step[sha1_dvs[i].testt])(ctx->ihv2, ihvtmp, ctx->m2, ctx->states[sha1_dvs[i].testt]);
- // to verify SHA-1 collision detection code with collisions for reduced-step SHA-1
- if ((ihvtmp[0] == ctx->ihv[0] && ihvtmp[1] == ctx->ihv[1] && ihvtmp[2] == ctx->ihv[2] && ihvtmp[3] == ctx->ihv[3] && ihvtmp[4] == ctx->ihv[4])
- || (ctx->reduced_round_coll && ctx->ihv1[0] == ctx->ihv2[0] && ctx->ihv1[1] == ctx->ihv2[1] && ctx->ihv1[2] == ctx->ihv2[2] && ctx->ihv1[3] == ctx->ihv2[3] && ctx->ihv1[4] == ctx->ihv2[4]))
+ if (ubc_dv_mask[0] & ((uint32_t)(1) << sha1_dvs[i].maskb))
{
- ctx->found_collision = 1;
- // TODO: call callback
- if (ctx->callback != NULL)
- ctx->callback(ctx->total - 64, ctx->ihv1, ctx->ihv2, ctx->m1, ctx->m2);
+ for (j = 0; j < 80; ++j)
+ ctx->m2[j] = ctx->m1[j] ^ sha1_dvs[i].dm[j];
- if (ctx->safe_hash)
+ sha1_recompression_step(sha1_dvs[i].testt, ctx->ihv2, ihvtmp, ctx->m2, ctx->states[sha1_dvs[i].testt]);
+
+ /* to verify SHA-1 collision detection code with collisions for reduced-step SHA-1 */
+ if ((0 == ((ihvtmp[0] ^ ctx->ihv[0]) | (ihvtmp[1] ^ ctx->ihv[1]) | (ihvtmp[2] ^ ctx->ihv[2]) | (ihvtmp[3] ^ ctx->ihv[3]) | (ihvtmp[4] ^ ctx->ihv[4])))
+ || (ctx->reduced_round_coll && 0==((ctx->ihv1[0] ^ ctx->ihv2[0]) | (ctx->ihv1[1] ^ ctx->ihv2[1]) | (ctx->ihv1[2] ^ ctx->ihv2[2]) | (ctx->ihv1[3] ^ ctx->ihv2[3]) | (ctx->ihv1[4] ^ ctx->ihv2[4]))))
{
- sha1_compression_W(ctx->ihv, ctx->m1);
- sha1_compression_W(ctx->ihv, ctx->m1);
- }
+ ctx->found_collision = 1;
- break;
+ if (ctx->safe_hash)
+ {
+ sha1_compression_W(ctx->ihv, ctx->m1);
+ sha1_compression_W(ctx->ihv, ctx->m1);
+ }
+
+ break;
+ }
}
}
}
}
}
-
-
-
-
-void swap_bytes(uint32_t val[16])
-{
- unsigned i;
- for (i = 0; i < 16; ++i)
- {
- val[i] = ((val[i] << 8) & 0xFF00FF00) | ((val[i] >> 8) & 0xFF00FF);
- val[i] = (val[i] << 16) | (val[i] >> 16);
- }
-}
-
-void SHA1DCInit(SHA1_CTX* ctx)
+void SHA1DCInit(SHA1_CTX* ctx)
{
- static const union { unsigned char bytes[4]; uint32_t value; } endianness = { { 0, 1, 2, 3 } };
- static const uint32_t littleendian = 0x03020100;
ctx->total = 0;
ctx->ihv[0] = 0x67452301;
ctx->ihv[1] = 0xEFCDAB89;
@@ -1014,7 +1669,6 @@ void SHA1DCInit(SHA1_CTX* ctx)
ctx->ubc_check = 1;
ctx->detect_coll = 1;
ctx->reduced_round_coll = 0;
- ctx->bigendian = (endianness.value != littleendian);
ctx->callback = NULL;
}
@@ -1056,41 +1710,32 @@ void SHA1DCSetCallback(SHA1_CTX* ctx, collision_block_callback callback)
ctx->callback = callback;
}
-void SHA1DCUpdate(SHA1_CTX* ctx, const char* buf, unsigned len)
+void SHA1DCUpdate(SHA1_CTX* ctx, const char* buf, size_t len)
{
unsigned left, fill;
- if (len == 0)
+ if (len == 0)
return;
left = ctx->total & 63;
fill = 64 - left;
- if (left && len >= fill)
+ if (left && len >= fill)
{
ctx->total += fill;
memcpy(ctx->buffer + left, buf, fill);
- if (!ctx->bigendian)
- swap_bytes((uint32_t*)(ctx->buffer));
sha1_process(ctx, (uint32_t*)(ctx->buffer));
buf += fill;
len -= fill;
left = 0;
}
- while (len >= 64)
+ while (len >= 64)
{
ctx->total += 64;
- if (!ctx->bigendian)
- {
- memcpy(ctx->buffer, buf, 64);
- swap_bytes((uint32_t*)(ctx->buffer));
- sha1_process(ctx, (uint32_t*)(ctx->buffer));
- }
- else
- sha1_process(ctx, (uint32_t*)(buf));
+ sha1_process(ctx, (uint32_t*)(buf));
buf += 64;
len -= 64;
}
- if (len > 0)
+ if (len > 0)
{
ctx->total += len;
memcpy(ctx->buffer + left, buf, len);
@@ -1111,7 +1756,7 @@ int SHA1DCFinal(unsigned char output[20], SHA1_CTX *ctx)
uint32_t padn = (last < 56) ? (56 - last) : (120 - last);
uint64_t total;
SHA1DCUpdate(ctx, (const char*)(sha1_padding), padn);
-
+
total = ctx->total - padn;
total <<= 3;
ctx->buffer[56] = (unsigned char)(total >> 56);
@@ -1122,8 +1767,6 @@ int SHA1DCFinal(unsigned char output[20], SHA1_CTX *ctx)
ctx->buffer[61] = (unsigned char)(total >> 16);
ctx->buffer[62] = (unsigned char)(total >> 8);
ctx->buffer[63] = (unsigned char)(total);
- if (!ctx->bigendian)
- swap_bytes((uint32_t*)(ctx->buffer));
sha1_process(ctx, (uint32_t*)(ctx->buffer));
output[0] = (unsigned char)(ctx->ihv[0] >> 24);
output[1] = (unsigned char)(ctx->ihv[0] >> 16);
diff --git a/src/hash/sha1dc/sha1.h b/src/hash/sha1dc/sha1.h
index 8b522f9d2..e867724c0 100644
--- a/src/hash/sha1dc/sha1.h
+++ b/src/hash/sha1dc/sha1.h
@@ -5,19 +5,24 @@
* https://opensource.org/licenses/MIT
***/
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
#include <stdint.h>
-// uses SHA-1 message expansion to expand the first 16 words of W[] to 80 words
-void sha1_message_expansion(uint32_t W[80]);
+/* uses SHA-1 message expansion to expand the first 16 words of W[] to 80 words */
+/* void sha1_message_expansion(uint32_t W[80]); */
-// sha-1 compression function; first version takes a message block pre-parsed as 16 32-bit integers, second version takes an already expanded message)
-void sha1_compression(uint32_t ihv[5], const uint32_t m[16]);
-void sha1_compression_W(uint32_t ihv[5], const uint32_t W[80]);
+/* sha-1 compression function; first version takes a message block pre-parsed as 16 32-bit integers, second version takes an already expanded message) */
+/* void sha1_compression(uint32_t ihv[5], const uint32_t m[16]);
+void sha1_compression_W(uint32_t ihv[5], const uint32_t W[80]); */
-// same as sha1_compression_W, but additionally store intermediate states
-// only stores states ii (the state between step ii-1 and step ii) when DOSTORESTATEii is defined in ubc_check.h
-void sha1_compression_states(uint32_t ihv[5], const uint32_t W[80], uint32_t states[80][5]);
+/* same as sha1_compression_W, but additionally store intermediate states */
+/* only stores states ii (the state between step ii-1 and step ii) when DOSTORESTATEii is defined in ubc_check.h */
+void sha1_compression_states(uint32_t[5], const uint32_t[16], uint32_t[80], uint32_t[80][5]);
+/*
// function type for sha1_recompression_step_T (uint32_t ihvin[5], uint32_t ihvout[5], const uint32_t me2[80], const uint32_t state[5])
// where 0 <= T < 80
// me2 is an expanded message (the expansion of an original message block XOR'ed with a disturbance vector's message block difference)
@@ -25,21 +30,21 @@ void sha1_compression_states(uint32_t ihv[5], const uint32_t W[80], uint32_t sta
// the function will return:
// ihvin: the reconstructed input chaining value
// ihvout: the reconstructed output chaining value
+*/
typedef void(*sha1_recompression_type)(uint32_t*, uint32_t*, const uint32_t*, const uint32_t*);
-// table of sha1_recompression_step_0, ... , sha1_recompression_step_79
-extern sha1_recompression_type sha1_recompression_step[80];
+/* table of sha1_recompression_step_0, ... , sha1_recompression_step_79 */
+/* extern sha1_recompression_type sha1_recompression_step[80];*/
-// a callback function type that can be set to be called when a collision block has been found:
-// void collision_block_callback(uint64_t byteoffset, const uint32_t ihvin1[5], const uint32_t ihvin2[5], const uint32_t m1[80], const uint32_t m2[80])
+/* a callback function type that can be set to be called when a collision block has been found: */
+/* void collision_block_callback(uint64_t byteoffset, const uint32_t ihvin1[5], const uint32_t ihvin2[5], const uint32_t m1[80], const uint32_t m2[80]) */
typedef void(*collision_block_callback)(uint64_t, const uint32_t*, const uint32_t*, const uint32_t*, const uint32_t*);
-// the SHA-1 context
+/* the SHA-1 context */
typedef struct {
uint64_t total;
uint32_t ihv[5];
unsigned char buffer[64];
- int bigendian;
int found_collision;
int safe_hash;
int detect_coll;
@@ -54,41 +59,47 @@ typedef struct {
uint32_t states[80][5];
} SHA1_CTX;
-// initialize SHA-1 context
-void SHA1DCInit(SHA1_CTX*);
+/* initialize SHA-1 context */
+void SHA1DCInit(SHA1_CTX*);
+/*
// function to enable safe SHA-1 hashing:
// collision attacks are thwarted by hashing a detected near-collision block 3 times
// think of it as extending SHA-1 from 80-steps to 240-steps for such blocks:
-// the best collision attacks against SHA-1 have complexity about 2^60,
+// the best collision attacks against SHA-1 have complexity about 2^60,
// thus for 240-steps an immediate lower-bound for the best cryptanalytic attacks would 2^180
// an attacker would be better off using a generic birthday search of complexity 2^80
//
// enabling safe SHA-1 hashing will result in the correct SHA-1 hash for messages where no collision attack was detected
-// but it will result in a different SHA-1 hash for messages where a collision attack was detected
+// but it will result in a different SHA-1 hash for messages where a collision attack was detected
// this will automatically invalidate SHA-1 based digital signature forgeries
// enabled by default
+*/
void SHA1DCSetSafeHash(SHA1_CTX*, int);
-// function to disable or enable the use of Unavoidable Bitconditions (provides a significant speed up)
-// enabled by default
+/* function to disable or enable the use of Unavoidable Bitconditions (provides a significant speed up) */
+/* enabled by default */
void SHA1DCSetUseUBC(SHA1_CTX*, int);
-// function to disable or enable the use of Collision Detection
-// enabled by default
-void SHA1DCSetUseDetectColl(SHA1_CTX* ctx, int detect_coll);
+/* function to disable or enable the use of Collision Detection */
+/* enabled by default */
+void SHA1DCSetUseDetectColl(SHA1_CTX*, int);
-// function to disable or enable the detection of reduced-round SHA-1 collisions
-// disabled by default
+/* function to disable or enable the detection of reduced-round SHA-1 collisions */
+/* disabled by default */
void SHA1DCSetDetectReducedRoundCollision(SHA1_CTX*, int);
-// function to set a callback function, pass NULL to disable
-// by default no callback set
+/* function to set a callback function, pass NULL to disable */
+/* by default no callback set */
void SHA1DCSetCallback(SHA1_CTX*, collision_block_callback);
-// update SHA-1 context with buffer contents
-void SHA1DCUpdate(SHA1_CTX*, const char*, unsigned);
+/* update SHA-1 context with buffer contents */
+void SHA1DCUpdate(SHA1_CTX*, const char*, size_t);
-// obtain SHA-1 hash from SHA-1 context
-// returns: 0 = no collision detected, otherwise = collision found => warn user for active attack
+/* obtain SHA-1 hash from SHA-1 context */
+/* returns: 0 = no collision detected, otherwise = collision found => warn user for active attack */
int SHA1DCFinal(unsigned char[20], SHA1_CTX*);
+
+#if defined(__cplusplus)
+}
+#endif
diff --git a/src/hash/sha1dc/ubc_check.c b/src/hash/sha1dc/ubc_check.c
index 556aaf3c5..27d0976da 100644
--- a/src/hash/sha1dc/ubc_check.c
+++ b/src/hash/sha1dc/ubc_check.c
@@ -5,6 +5,7 @@
* https://opensource.org/licenses/MIT
***/
+/*
// this file was generated by the 'parse_bitrel' program in the tools section
// using the data files from directory 'tools/data/3565'
//
@@ -17,10 +18,11 @@
// ubc_check takes as input an expanded message block and verifies the unavoidable bitconditions for all listed DVs
// it returns a dvmask where each bit belonging to a DV is set if all unavoidable bitconditions for that DV have been met
// thus one needs to do the recompression check for each DV that has its bit set
-//
+//
// ubc_check is programmatically generated and the unavoidable bitconditions have been hardcoded
// a directly verifiable version named ubc_check_verify can be found in ubc_check_verify.c
// ubc_check has been verified against ubc_check_verify using the 'ubc_check_test' program in the tools section
+*/
#include <stdint.h>
#include "ubc_check.h"
@@ -58,7 +60,7 @@ static const uint32_t DV_II_54_0_bit = (uint32_t)(1) << 29;
static const uint32_t DV_II_55_0_bit = (uint32_t)(1) << 30;
static const uint32_t DV_II_56_0_bit = (uint32_t)(1) << 31;
-dv_info_t sha1_dvs[] =
+dv_info_t sha1_dvs[] =
{
{1,43,0,58,0,0, { 0x08000000,0x9800000c,0xd8000010,0x08000010,0xb8000010,0x98000000,0x60000000,0x00000008,0xc0000000,0x90000014,0x10000010,0xb8000014,0x28000000,0x20000010,0x48000000,0x08000018,0x60000000,0x90000010,0xf0000010,0x90000008,0xc0000000,0x90000010,0xf0000010,0xb0000008,0x40000000,0x90000000,0xf0000010,0x90000018,0x60000000,0x90000010,0x90000010,0x90000000,0x80000000,0x00000010,0xa0000000,0x20000000,0xa0000000,0x20000010,0x00000000,0x20000010,0x20000000,0x00000010,0x20000000,0x00000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000040,0x40000002,0x80000004,0x80000080,0x80000006,0x00000049,0x00000103,0x80000009,0x80000012,0x80000202,0x00000018,0x00000164,0x00000408,0x800000e6,0x8000004c,0x00000803,0x80000161,0x80000599 } }
, {1,44,0,58,0,1, { 0xb4000008,0x08000000,0x9800000c,0xd8000010,0x08000010,0xb8000010,0x98000000,0x60000000,0x00000008,0xc0000000,0x90000014,0x10000010,0xb8000014,0x28000000,0x20000010,0x48000000,0x08000018,0x60000000,0x90000010,0xf0000010,0x90000008,0xc0000000,0x90000010,0xf0000010,0xb0000008,0x40000000,0x90000000,0xf0000010,0x90000018,0x60000000,0x90000010,0x90000010,0x90000000,0x80000000,0x00000010,0xa0000000,0x20000000,0xa0000000,0x20000010,0x00000000,0x20000010,0x20000000,0x00000010,0x20000000,0x00000010,0xa0000000,0x00000000,0x20000000,0x20000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000020,0x00000001,0x40000002,0x40000040,0x40000002,0x80000004,0x80000080,0x80000006,0x00000049,0x00000103,0x80000009,0x80000012,0x80000202,0x00000018,0x00000164,0x00000408,0x800000e6,0x8000004c,0x00000803,0x80000161 } }
diff --git a/src/hash/sha1dc/ubc_check.h b/src/hash/sha1dc/ubc_check.h
index 27285bdf5..b349bed92 100644
--- a/src/hash/sha1dc/ubc_check.h
+++ b/src/hash/sha1dc/ubc_check.h
@@ -5,6 +5,7 @@
* https://opensource.org/licenses/MIT
***/
+/*
// this file was generated by the 'parse_bitrel' program in the tools section
// using the data files from directory 'tools/data/3565'
//
@@ -17,10 +18,15 @@
// ubc_check takes as input an expanded message block and verifies the unavoidable bitconditions for all listed DVs
// it returns a dvmask where each bit belonging to a DV is set if all unavoidable bitconditions for that DV have been met
// thus one needs to do the recompression check for each DV that has its bit set
+*/
#ifndef UBC_CHECK_H
#define UBC_CHECK_H
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
#include <stdint.h>
#define DVMASKSIZE 1
@@ -31,5 +37,10 @@ void ubc_check(const uint32_t W[80], uint32_t dvmask[DVMASKSIZE]);
#define DOSTORESTATE58
#define DOSTORESTATE65
+#define CHECK_DVMASK(_DVMASK) (0 != _DVMASK[0])
+
+#if defined(__cplusplus)
+}
+#endif
-#endif // UBC_CHECK_H
+#endif /* UBC_CHECK_H */
diff --git a/src/indexer.c b/src/indexer.c
index 869e2299f..ce67240ce 100644
--- a/src/indexer.c
+++ b/src/indexer.c
@@ -17,6 +17,7 @@
#include "oid.h"
#include "oidmap.h"
#include "zstream.h"
+#include "object.h"
extern git_mutex git__mwindow_mutex;
@@ -33,7 +34,8 @@ struct git_indexer {
unsigned int parsed_header :1,
pack_committed :1,
have_stream :1,
- have_delta :1;
+ have_delta :1,
+ do_fsync :1;
struct git_pack_header hdr;
struct git_pack_file *pack;
unsigned int mode;
@@ -123,6 +125,9 @@ int git_indexer_new(
git_hash_ctx_init(&idx->hash_ctx);
git_hash_ctx_init(&idx->trailer);
+ if (git_object__synchronous_writing)
+ idx->do_fsync = 1;
+
error = git_buf_joinpath(&path, prefix, suff);
if (error < 0)
goto cleanup;
@@ -161,6 +166,11 @@ cleanup:
return -1;
}
+void git_indexer__set_fsync(git_indexer *idx, int do_fsync)
+{
+ idx->do_fsync = !!do_fsync;
+}
+
/* Try to store the delta so we can try to resolve it later */
static int store_delta(git_indexer *idx)
{
@@ -989,7 +999,9 @@ int git_indexer_commit(git_indexer *idx, git_transfer_progress *stats)
return -1;
if (git_filebuf_open(&index_file, filename.ptr,
- GIT_FILEBUF_HASH_CONTENTS, idx->mode) < 0)
+ GIT_FILEBUF_HASH_CONTENTS |
+ (idx->do_fsync ? GIT_FILEBUF_FSYNC : 0),
+ idx->mode) < 0)
goto on_error;
/* Write out the header */
@@ -1066,6 +1078,11 @@ int git_indexer_commit(git_indexer *idx, git_transfer_progress *stats)
return -1;
}
+ if (idx->do_fsync && p_fsync(idx->pack->mwf.fd) < 0) {
+ giterr_set(GITERR_OS, "failed to fsync packfile");
+ goto on_error;
+ }
+
/* We need to close the descriptor here so Windows doesn't choke on commit_at */
if (p_close(idx->pack->mwf.fd) < 0) {
giterr_set(GITERR_OS, "failed to close packfile");
@@ -1078,7 +1095,14 @@ int git_indexer_commit(git_indexer *idx, git_transfer_progress *stats)
goto on_error;
/* And don't forget to rename the packfile to its new place. */
- p_rename(idx->pack->pack_name, git_buf_cstr(&filename));
+ if (p_rename(idx->pack->pack_name, git_buf_cstr(&filename)) < 0)
+ goto on_error;
+
+ /* And fsync the parent directory if we're asked to. */
+ if (idx->do_fsync &&
+ git_futils_fsync_parent(git_buf_cstr(&filename)) < 0)
+ goto on_error;
+
idx->pack_committed = 1;
git_buf_free(&filename);
diff --git a/src/indexer.h b/src/indexer.h
new file mode 100644
index 000000000..702694bbf
--- /dev/null
+++ b/src/indexer.h
@@ -0,0 +1,12 @@
+/*
+ * 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_indexer_h__
+#define INCLUDE_indexer_h__
+
+extern int git_indexer__set_fsync(git_indexer *idx, int do_fsync);
+
+#endif
diff --git a/src/merge.c b/src/merge.c
index 857d51311..6e00b5adb 100644
--- a/src/merge.c
+++ b/src/merge.c
@@ -2018,6 +2018,26 @@ int git_merge_trees(
git_iterator_options iter_opts = GIT_ITERATOR_OPTIONS_INIT;
int error;
+ assert(out && repo);
+
+ /* if one side is treesame to the ancestor, take the other side */
+ if (ancestor_tree && merge_opts && (merge_opts->flags & GIT_MERGE_SKIP_REUC)) {
+ const git_tree *result = NULL;
+ const git_oid *ancestor_tree_id = git_tree_id(ancestor_tree);
+
+ if (our_tree && !git_oid_cmp(ancestor_tree_id, git_tree_id(our_tree)))
+ result = their_tree;
+ else if (their_tree && !git_oid_cmp(ancestor_tree_id, git_tree_id(their_tree)))
+ result = our_tree;
+
+ if (result) {
+ if ((error = git_index_new(out)) == 0)
+ error = git_index_read_tree(*out, result);
+
+ return error;
+ }
+ }
+
iter_opts.flags = GIT_ITERATOR_DONT_IGNORE_CASE;
if ((error = git_iterator_for_tree(
diff --git a/src/object.c b/src/object.c
index 2da36a2ee..bd87c9310 100644
--- a/src/object.c
+++ b/src/object.c
@@ -16,6 +16,7 @@
#include "tag.h"
bool git_object__strict_input_validation = true;
+bool git_object__synchronous_writing = false;
typedef struct {
const char *str; /* type name string */
diff --git a/src/object.h b/src/object.h
index dd227d16d..13117e4c3 100644
--- a/src/object.h
+++ b/src/object.h
@@ -10,6 +10,7 @@
#include "repository.h"
extern bool git_object__strict_input_validation;
+extern bool git_object__synchronous_writing;
/** Base git object for inheritance */
struct git_object {
diff --git a/src/odb.c b/src/odb.c
index 3f2ac02f3..cf321f51e 100644
--- a/src/odb.c
+++ b/src/odb.c
@@ -496,7 +496,7 @@ int git_odb_get_backend(git_odb_backend **out, git_odb *odb, size_t pos)
return GIT_ENOTFOUND;
}
-static int add_default_backends(
+int git_odb__add_default_backends(
git_odb *db, const char *objects_dir,
bool as_alternates, int alternate_depth)
{
@@ -531,7 +531,7 @@ static int add_default_backends(
#endif
/* add the loose object backend */
- if (git_odb_backend_loose(&loose, objects_dir, -1, 0, 0, 0) < 0 ||
+ if (git_odb_backend_loose(&loose, objects_dir, -1, db->do_fsync, 0, 0) < 0 ||
add_backend_internal(db, loose, GIT_LOOSE_PRIORITY, as_alternates, inode) < 0)
return -1;
@@ -586,7 +586,7 @@ static int load_alternates(git_odb *odb, const char *objects_dir, int alternate_
alternate = git_buf_cstr(&alternates_path);
}
- if ((result = add_default_backends(odb, alternate, true, alternate_depth + 1)) < 0)
+ if ((result = git_odb__add_default_backends(odb, alternate, true, alternate_depth + 1)) < 0)
break;
}
@@ -598,7 +598,7 @@ static int load_alternates(git_odb *odb, const char *objects_dir, int alternate_
int git_odb_add_disk_alternate(git_odb *odb, const char *path)
{
- return add_default_backends(odb, path, true, 0);
+ return git_odb__add_default_backends(odb, path, true, 0);
}
int git_odb_open(git_odb **out, const char *objects_dir)
@@ -612,7 +612,7 @@ int git_odb_open(git_odb **out, const char *objects_dir)
if (git_odb_new(&db) < 0)
return -1;
- if (add_default_backends(db, objects_dir, 0, 0) < 0) {
+ if (git_odb__add_default_backends(db, objects_dir, 0, 0) < 0) {
git_odb_free(db);
return -1;
}
@@ -621,6 +621,24 @@ int git_odb_open(git_odb **out, const char *objects_dir)
return 0;
}
+int git_odb__set_caps(git_odb *odb, int caps)
+{
+ if (caps == GIT_ODB_CAP_FROM_OWNER) {
+ git_repository *repo = odb->rc.owner;
+ int val;
+
+ if (!repo) {
+ giterr_set(GITERR_ODB, "cannot access repository to set odb caps");
+ return -1;
+ }
+
+ if (!git_repository__cvar(&val, repo, GIT_CVAR_FSYNCOBJECTFILES))
+ odb->do_fsync = !!val;
+ }
+
+ return 0;
+}
+
static void odb_free(git_odb *db)
{
size_t i;
diff --git a/src/odb.h b/src/odb.h
index 76e82f1dd..4f548bbba 100644
--- a/src/odb.h
+++ b/src/odb.h
@@ -38,8 +38,25 @@ struct git_odb {
git_refcount rc;
git_vector backends;
git_cache own_cache;
+ unsigned int do_fsync :1;
};
+typedef enum {
+ GIT_ODB_CAP_FROM_OWNER = -1,
+} git_odb_cap_t;
+
+/*
+ * Set the capabilities for the object database.
+ */
+int git_odb__set_caps(git_odb *odb, int caps);
+
+/*
+ * Add the default loose and packed backends for a database.
+ */
+int git_odb__add_default_backends(
+ git_odb *db, const char *objects_dir,
+ bool as_alternates, int alternate_depth);
+
/*
* Hash a git_rawobj internally.
* The `git_rawobj` is supposed to be previously initialized
diff --git a/src/odb_loose.c b/src/odb_loose.c
index b2e2f1fb7..e14af4fab 100644
--- a/src/odb_loose.c
+++ b/src/odb_loose.c
@@ -14,6 +14,7 @@
#include "odb.h"
#include "delta.h"
#include "filebuf.h"
+#include "object.h"
#include "git2/odb_backend.h"
#include "git2/types.h"
@@ -838,6 +839,17 @@ static void loose_backend__stream_free(git_odb_stream *_stream)
git__free(stream);
}
+static int filebuf_flags(loose_backend *backend)
+{
+ int flags = GIT_FILEBUF_TEMPORARY |
+ (backend->object_zlib_level << GIT_FILEBUF_DEFLATE_SHIFT);
+
+ if (backend->fsync_object_files || git_object__synchronous_writing)
+ flags |= GIT_FILEBUF_FSYNC;
+
+ return flags;
+}
+
static int loose_backend__stream(git_odb_stream **stream_out, git_odb_backend *_backend, git_off_t length, git_otype type)
{
loose_backend *backend;
@@ -864,9 +876,7 @@ static int loose_backend__stream(git_odb_stream **stream_out, git_odb_backend *_
stream->stream.mode = GIT_STREAM_WRONLY;
if (git_buf_joinpath(&tmp_path, backend->objects_dir, "tmp_object") < 0 ||
- git_filebuf_open(&stream->fbuf, tmp_path.ptr,
- GIT_FILEBUF_TEMPORARY |
- (backend->object_zlib_level << GIT_FILEBUF_DEFLATE_SHIFT),
+ git_filebuf_open(&stream->fbuf, tmp_path.ptr, filebuf_flags(backend),
backend->object_file_mode) < 0 ||
stream->stream.write((git_odb_stream *)stream, hdr, hdrlen) < 0)
{
@@ -894,9 +904,7 @@ static int loose_backend__write(git_odb_backend *_backend, const git_oid *oid, c
header_len = git_odb__format_object_header(header, sizeof(header), len, type);
if (git_buf_joinpath(&final_path, backend->objects_dir, "tmp_object") < 0 ||
- git_filebuf_open(&fbuf, final_path.ptr,
- GIT_FILEBUF_TEMPORARY |
- (backend->object_zlib_level << GIT_FILEBUF_DEFLATE_SHIFT),
+ git_filebuf_open(&fbuf, final_path.ptr, filebuf_flags(backend),
backend->object_file_mode) < 0)
{
error = -1;
diff --git a/src/odb_pack.c b/src/odb_pack.c
index b80d0337a..51770a88e 100644
--- a/src/odb_pack.c
+++ b/src/odb_pack.c
@@ -428,7 +428,7 @@ static int pack_backend__read_prefix(
git_oid_cpy(out_oid, short_oid);
} else {
struct git_pack_entry e;
- git_rawobj raw;
+ git_rawobj raw = {NULL};
if ((error = pack_entry_find_prefix(
&e, (struct pack_backend *)backend, short_oid, len)) == 0 &&
diff --git a/src/openssl_stream.c b/src/openssl_stream.c
index bb9b32c67..c0a9c3c37 100644
--- a/src/openssl_stream.c
+++ b/src/openssl_stream.c
@@ -66,7 +66,7 @@ static void shutdown_ssl_locking(void)
CRYPTO_set_locking_callback(NULL);
for (i = 0; i < num_locks; ++i)
- git_mutex_free(openssl_locks);
+ git_mutex_free(&openssl_locks[i]);
git__free(openssl_locks);
}
diff --git a/src/pack-objects.c b/src/pack-objects.c
index 58b7b94b3..ef272e8f5 100644
--- a/src/pack-objects.c
+++ b/src/pack-objects.c
@@ -1385,6 +1385,7 @@ int git_packbuilder_write(
git_indexer *indexer;
git_transfer_progress stats;
struct pack_write_context ctx;
+ int t;
PREPARE_PACK;
@@ -1392,6 +1393,9 @@ int git_packbuilder_write(
&indexer, path, mode, pb->odb, progress_cb, progress_cb_payload) < 0)
return -1;
+ if (!git_repository__cvar(&t, pb->repo, GIT_CVAR_FSYNCOBJECTFILES) && t)
+ git_indexer__set_fsync(indexer, 1);
+
ctx.indexer = indexer;
ctx.stats = &stats;
diff --git a/src/pack-objects.h b/src/pack-objects.h
index 5a84f4158..e1e0ee3c8 100644
--- a/src/pack-objects.h
+++ b/src/pack-objects.h
@@ -16,6 +16,7 @@
#include "netops.h"
#include "zstream.h"
#include "pool.h"
+#include "indexer.h"
#include "git2/oid.h"
#include "git2/pack.h"
diff --git a/src/patch_parse.c b/src/patch_parse.c
index d993c0311..0a9edcd18 100644
--- a/src/patch_parse.c
+++ b/src/patch_parse.c
@@ -444,9 +444,9 @@ static int parse_header_git(
goto done;
parse_advance_ws(ctx);
- parse_advance_expected_str(ctx, "\n");
- if (ctx->line_len > 0) {
+ if (parse_advance_expected_str(ctx, "\n") < 0 ||
+ ctx->line_len > 0) {
error = parse_err("trailing data at line %"PRIuZ, ctx->line_num);
goto done;
}
diff --git a/src/posix.c b/src/posix.c
index e68f324f6..94deb6ab0 100644
--- a/src/posix.c
+++ b/src/posix.c
@@ -10,6 +10,8 @@
#include <stdio.h>
#include <ctype.h>
+size_t p_fsync__cnt = 0;
+
#ifndef GIT_WIN32
#ifdef NO_ADDRINFO
diff --git a/src/posix.h b/src/posix.h
index f204751cf..bd5a98e26 100644
--- a/src/posix.h
+++ b/src/posix.h
@@ -111,6 +111,12 @@ extern int p_rename(const char *from, const char *to);
extern int git__page_size(size_t *page_size);
extern int git__mmap_alignment(size_t *page_size);
+/* The number of times `p_fsync` has been called. Note that this is for
+ * test code only; it it not necessarily thread-safe and should not be
+ * relied upon in production.
+ */
+extern size_t p_fsync__cnt;
+
/**
* Platform-dependent methods
*/
diff --git a/src/rebase.c b/src/rebase.c
index bf1d086ba..f528031b3 100644
--- a/src/rebase.c
+++ b/src/rebase.c
@@ -447,8 +447,8 @@ static int rebase_setupfiles_merge(git_rebase *rebase)
size_t i;
int error = 0;
- if ((error = rebase_setupfile(rebase, END_FILE, -1, "%" PRIuZ "\n", git_array_size(rebase->operations))) < 0 ||
- (error = rebase_setupfile(rebase, ONTO_NAME_FILE, -1, "%s\n", rebase->onto_name)) < 0)
+ if ((error = rebase_setupfile(rebase, END_FILE, 0, "%" PRIuZ "\n", git_array_size(rebase->operations))) < 0 ||
+ (error = rebase_setupfile(rebase, ONTO_NAME_FILE, 0, "%s\n", rebase->onto_name)) < 0)
goto done;
for (i = 0; i < git_array_size(rebase->operations); i++) {
@@ -459,7 +459,7 @@ static int rebase_setupfiles_merge(git_rebase *rebase)
git_oid_fmt(id_str, &operation->id);
- if ((error = rebase_setupfile(rebase, commit_filename.ptr, -1,
+ if ((error = rebase_setupfile(rebase, commit_filename.ptr, 0,
"%.*s\n", GIT_OID_HEXSZ, id_str)) < 0)
goto done;
}
@@ -486,10 +486,10 @@ static int rebase_setupfiles(git_rebase *rebase)
rebase->orig_head_name;
if (git_repository__set_orig_head(rebase->repo, &rebase->orig_head_id) < 0 ||
- rebase_setupfile(rebase, HEAD_NAME_FILE, -1, "%s\n", orig_head_name) < 0 ||
- rebase_setupfile(rebase, ONTO_FILE, -1, "%.*s\n", GIT_OID_HEXSZ, onto) < 0 ||
- rebase_setupfile(rebase, ORIG_HEAD_FILE, -1, "%.*s\n", GIT_OID_HEXSZ, orig_head) < 0 ||
- rebase_setupfile(rebase, QUIET_FILE, -1, rebase->quiet ? "t\n" : "\n") < 0)
+ rebase_setupfile(rebase, HEAD_NAME_FILE, 0, "%s\n", orig_head_name) < 0 ||
+ rebase_setupfile(rebase, ONTO_FILE, 0, "%.*s\n", GIT_OID_HEXSZ, onto) < 0 ||
+ rebase_setupfile(rebase, ORIG_HEAD_FILE, 0, "%.*s\n", GIT_OID_HEXSZ, orig_head) < 0 ||
+ rebase_setupfile(rebase, QUIET_FILE, 0, rebase->quiet ? "t\n" : "\n") < 0)
return -1;
return rebase_setupfiles_merge(rebase);
@@ -823,8 +823,8 @@ static int rebase_next_merge(
normalize_checkout_options_for_apply(&checkout_opts, rebase, current_commit);
if ((error = git_indexwriter_init_for_operation(&indexwriter, rebase->repo, &checkout_opts.checkout_strategy)) < 0 ||
- (error = rebase_setupfile(rebase, MSGNUM_FILE, -1, "%" PRIuZ "\n", rebase->current+1)) < 0 ||
- (error = rebase_setupfile(rebase, CURRENT_FILE, -1, "%.*s\n", GIT_OID_HEXSZ, current_idstr)) < 0 ||
+ (error = rebase_setupfile(rebase, MSGNUM_FILE, 0, "%" PRIuZ "\n", rebase->current+1)) < 0 ||
+ (error = rebase_setupfile(rebase, CURRENT_FILE, 0, "%.*s\n", GIT_OID_HEXSZ, current_idstr)) < 0 ||
(error = git_merge_trees(&index, rebase->repo, parent_tree, head_tree, current_tree, &rebase->options.merge_options)) < 0 ||
(error = git_merge__check_result(rebase->repo, index)) < 0 ||
(error = git_checkout_index(rebase->repo, index, &checkout_opts)) < 0 ||
diff --git a/src/refdb_fs.c b/src/refdb_fs.c
index ac5a6a6a5..b325d2763 100644
--- a/src/refdb_fs.c
+++ b/src/refdb_fs.c
@@ -62,6 +62,7 @@ typedef struct refdb_fs_backend {
int peeling_mode;
git_iterator_flag_t iterator_flags;
uint32_t direach_flags;
+ int fsync;
} refdb_fs_backend;
static int refdb_reflog_fs__delete(git_refdb_backend *_backend, const char *name);
@@ -736,8 +737,9 @@ static int reference_path_available(
static int loose_lock(git_filebuf *file, refdb_fs_backend *backend, const char *name)
{
- int error;
+ int error, filebuf_flags;
git_buf ref_path = GIT_BUF_INIT;
+ const char *basedir;
assert(file && backend && name);
@@ -746,16 +748,25 @@ static int loose_lock(git_filebuf *file, refdb_fs_backend *backend, const char *
return GIT_EINVALIDSPEC;
}
+ if (is_per_worktree_ref(name))
+ basedir = backend->gitpath;
+ else
+ basedir = backend->commonpath;
+
/* Remove a possibly existing empty directory hierarchy
* which name would collide with the reference name
*/
- if ((error = git_futils_rmdir_r(name, backend->gitpath, GIT_RMDIR_SKIP_NONEMPTY)) < 0)
+ if ((error = git_futils_rmdir_r(name, basedir, GIT_RMDIR_SKIP_NONEMPTY)) < 0)
return error;
- if (git_buf_joinpath(&ref_path, backend->gitpath, name) < 0)
+ if (git_buf_joinpath(&ref_path, basedir, name) < 0)
return -1;
- error = git_filebuf_open(file, ref_path.ptr, GIT_FILEBUF_FORCE, GIT_REFS_FILE_MODE);
+ filebuf_flags = GIT_FILEBUF_FORCE;
+ if (backend->fsync)
+ filebuf_flags |= GIT_FILEBUF_FSYNC;
+
+ error = git_filebuf_open(file, ref_path.ptr, filebuf_flags, GIT_REFS_FILE_MODE);
if (error == GIT_EDIRECTORY)
giterr_set(GITERR_REFERENCE, "cannot lock ref '%s', there are refs beneath that folder", name);
@@ -990,15 +1001,18 @@ static int packed_write(refdb_fs_backend *backend)
{
git_sortedcache *refcache = backend->refcache;
git_filebuf pack_file = GIT_FILEBUF_INIT;
- int error;
+ int error, open_flags = 0;
size_t i;
/* lock the cache to updates while we do this */
if ((error = git_sortedcache_wlock(refcache)) < 0)
return error;
+ if (backend->fsync)
+ open_flags = GIT_FILEBUF_FSYNC;
+
/* Open the file! */
- if ((error = git_filebuf_open(&pack_file, git_sortedcache_path(refcache), 0, GIT_PACKEDREFS_FILE_MODE)) < 0)
+ if ((error = git_filebuf_open(&pack_file, git_sortedcache_path(refcache), open_flags, GIT_PACKEDREFS_FILE_MODE)) < 0)
goto fail;
/* Packfiles have a header... apparently
@@ -1786,7 +1800,7 @@ success:
/* Append to the reflog, must be called under reference lock */
static int reflog_append(refdb_fs_backend *backend, const git_reference *ref, const git_oid *old, const git_oid *new, const git_signature *who, const char *message)
{
- int error, is_symbolic;
+ int error, is_symbolic, open_flags;
git_oid old_id = {{0}}, new_id = {{0}};
git_buf buf = GIT_BUF_INIT, path = GIT_BUF_INIT;
git_repository *repo = backend->repo;
@@ -1854,7 +1868,12 @@ static int reflog_append(refdb_fs_backend *backend, const git_reference *ref, co
goto cleanup;
}
- error = git_futils_writebuffer(&buf, git_buf_cstr(&path), O_WRONLY|O_CREAT|O_APPEND, GIT_REFLOG_FILE_MODE);
+ open_flags = O_WRONLY | O_CREAT | O_APPEND;
+
+ if (backend->fsync)
+ open_flags |= O_FSYNC;
+
+ error = git_futils_writebuffer(&buf, git_buf_cstr(&path), open_flags, GIT_REFLOG_FILE_MODE);
cleanup:
git_buf_free(&buf);
@@ -2011,6 +2030,9 @@ int git_refdb_backend_fs(
backend->iterator_flags |= GIT_ITERATOR_PRECOMPOSE_UNICODE;
backend->direach_flags |= GIT_PATH_DIR_PRECOMPOSE_UNICODE;
}
+ if ((!git_repository__cvar(&t, backend->repo, GIT_CVAR_FSYNCOBJECTFILES) && t) ||
+ git_object__synchronous_writing)
+ backend->fsync = 1;
backend->parent.exists = &refdb_fs_backend__exists;
backend->parent.lookup = &refdb_fs_backend__lookup;
diff --git a/src/repository.c b/src/repository.c
index 0db481638..425ef796f 100644
--- a/src/repository.c
+++ b/src/repository.c
@@ -1055,18 +1055,22 @@ int git_repository_odb__weakptr(git_odb **out, git_repository *repo)
git_odb *odb;
if ((error = git_repository_item_path(&odb_path, repo,
- GIT_REPOSITORY_ITEM_OBJECTS)) < 0)
+ GIT_REPOSITORY_ITEM_OBJECTS)) < 0 ||
+ (error = git_odb_new(&odb)) < 0)
return error;
- error = git_odb_open(&odb, odb_path.ptr);
- if (!error) {
- GIT_REFCOUNT_OWN(odb, repo);
+ GIT_REFCOUNT_OWN(odb, repo);
- odb = git__compare_and_swap(&repo->_odb, NULL, odb);
- if (odb != NULL) {
- GIT_REFCOUNT_OWN(odb, NULL);
- git_odb_free(odb);
- }
+ if ((error = git_odb__set_caps(odb, GIT_ODB_CAP_FROM_OWNER)) < 0 ||
+ (error = git_odb__add_default_backends(odb, odb_path.ptr, 0, 0)) < 0) {
+ git_odb_free(odb);
+ return error;
+ }
+
+ odb = git__compare_and_swap(&repo->_odb, NULL, odb);
+ if (odb != NULL) {
+ GIT_REFCOUNT_OWN(odb, NULL);
+ git_odb_free(odb);
}
git_buf_free(&odb_path);
diff --git a/src/repository.h b/src/repository.h
index c328ecd21..33adfa60a 100644
--- a/src/repository.h
+++ b/src/repository.h
@@ -46,6 +46,7 @@ typedef enum {
GIT_CVAR_LOGALLREFUPDATES, /* core.logallrefupdates */
GIT_CVAR_PROTECTHFS, /* core.protectHFS */
GIT_CVAR_PROTECTNTFS, /* core.protectNTFS */
+ GIT_CVAR_FSYNCOBJECTFILES, /* core.fsyncObjectFiles */
GIT_CVAR_CACHE_MAX
} git_cvar_cached;
@@ -106,6 +107,8 @@ typedef enum {
GIT_PROTECTHFS_DEFAULT = GIT_CVAR_FALSE,
/* core.protectNTFS */
GIT_PROTECTNTFS_DEFAULT = GIT_CVAR_FALSE,
+ /* core.fsyncObjectFiles */
+ GIT_FSYNCOBJECTFILES_DEFAULT = GIT_CVAR_FALSE,
} git_cvar_value;
/* internal repository init flags */
diff --git a/src/settings.c b/src/settings.c
index 21585672c..24e549ec1 100644
--- a/src/settings.c
+++ b/src/settings.c
@@ -227,6 +227,10 @@ int git_libgit2_opts(int key, ...)
git_smart__ofs_delta_enabled = (va_arg(ap, int) != 0);
break;
+ case GIT_OPT_ENABLE_SYNCHRONOUS_OBJECT_CREATION:
+ git_object__synchronous_writing = (va_arg(ap, int) != 0);
+ break;
+
default:
giterr_set(GITERR_INVALID, "invalid option key");
error = -1;
diff --git a/src/submodule.c b/src/submodule.c
index 191cdf3dd..ddd4b0663 100644
--- a/src/submodule.c
+++ b/src/submodule.c
@@ -22,6 +22,7 @@
#include "iterator.h"
#include "path.h"
#include "index.h"
+#include "worktree.h"
#define GIT_MODULES_FILE ".gitmodules"
@@ -2038,17 +2039,28 @@ static int lookup_default_remote(git_remote **remote, git_repository *repo)
static int get_url_base(git_buf *url, git_repository *repo)
{
int error;
+ git_worktree *wt = NULL;
git_remote *remote = NULL;
- if (!(error = lookup_default_remote(&remote, repo))) {
+ if ((error = lookup_default_remote(&remote, repo)) == 0) {
error = git_buf_sets(url, git_remote_url(remote));
- git_remote_free(remote);
- }
- else if (error == GIT_ENOTFOUND) {
- /* if repository does not have a default remote, use workdir instead */
+ goto out;
+ } else if (error != GIT_ENOTFOUND)
+ goto out;
+ else
giterr_clear();
+
+ /* if repository does not have a default remote, use workdir instead */
+ if (git_repository_is_worktree(repo)) {
+ if ((error = git_worktree_open_from_repository(&wt, repo)) < 0)
+ goto out;
+ error = git_buf_sets(url, wt->parent_path);
+ } else
error = git_buf_sets(url, git_repository_workdir(repo));
- }
+
+out:
+ git_remote_free(remote);
+ git_worktree_free(wt);
return error;
}
diff --git a/src/unix/posix.h b/src/unix/posix.h
index b4786403f..52985fd8a 100644
--- a/src/unix/posix.h
+++ b/src/unix/posix.h
@@ -40,9 +40,14 @@ typedef int GIT_SOCKET;
#define p_link(o,n) link(o, n)
#define p_unlink(p) unlink(p)
#define p_mkdir(p,m) mkdir(p, m)
-#define p_fsync(fd) fsync(fd)
extern char *p_realpath(const char *, char *);
+GIT_INLINE(int) p_fsync(int fd)
+{
+ p_fsync__cnt++;
+ return fsync(fd);
+}
+
#define p_recv(s,b,l,f) recv(s,b,l,f)
#define p_send(s,b,l,f) send(s,b,l,f)
#define p_inet_pton(a, b, c) inet_pton(a, b, c)
diff --git a/src/win32/posix_w32.c b/src/win32/posix_w32.c
index fea634b00..5172627b0 100644
--- a/src/win32/posix_w32.c
+++ b/src/win32/posix_w32.c
@@ -113,6 +113,8 @@ int p_fsync(int fd)
{
HANDLE fh = (HANDLE)_get_osfhandle(fd);
+ p_fsync__cnt++;
+
if (fh == INVALID_HANDLE_VALUE) {
errno = EBADF;
return -1;
diff --git a/src/worktree.c b/src/worktree.c
index 5abc98945..393a088fe 100644
--- a/src/worktree.c
+++ b/src/worktree.c
@@ -14,11 +14,20 @@
#include "repository.h"
#include "worktree.h"
-static bool is_worktree_dir(git_buf *dir)
+static bool is_worktree_dir(const char *dir)
{
- return git_path_contains_file(dir, "commondir")
- && git_path_contains_file(dir, "gitdir")
- && git_path_contains_file(dir, "HEAD");
+ git_buf buf = GIT_BUF_INIT;
+ int error;
+
+ if (git_buf_sets(&buf, dir) < 0)
+ return -1;
+
+ error = git_path_contains_file(&buf, "commondir")
+ && git_path_contains_file(&buf, "gitdir")
+ && git_path_contains_file(&buf, "HEAD");
+
+ git_buf_free(&buf);
+ return error;
}
int git_worktree_list(git_strarray *wts, git_repository *repo)
@@ -47,7 +56,7 @@ int git_worktree_list(git_strarray *wts, git_repository *repo)
git_buf_truncate(&path, len);
git_buf_puts(&path, worktree);
- if (!is_worktree_dir(&path)) {
+ if (!is_worktree_dir(path.ptr)) {
git_vector_remove(&worktrees, i);
git__free(worktree);
}
@@ -112,6 +121,46 @@ out:
return err;
}
+static int open_worktree_dir(git_worktree **out, const char *parent, const char *dir, const char *name)
+{
+ git_buf gitdir = GIT_BUF_INIT;
+ git_worktree *wt = NULL;
+ int error = 0;
+
+ if (!is_worktree_dir(dir)) {
+ error = -1;
+ goto out;
+ }
+
+ if ((wt = git__calloc(1, sizeof(struct git_repository))) == NULL) {
+ error = -1;
+ goto out;
+ }
+
+ if ((wt->name = git__strdup(name)) == NULL
+ || (wt->commondir_path = git_worktree__read_link(dir, "commondir")) == NULL
+ || (wt->gitlink_path = git_worktree__read_link(dir, "gitdir")) == NULL
+ || (wt->parent_path = git__strdup(parent)) == NULL) {
+ error = -1;
+ goto out;
+ }
+
+ if ((error = git_path_prettify_dir(&gitdir, dir, NULL)) < 0)
+ goto out;
+ wt->gitdir_path = git_buf_detach(&gitdir);
+
+ wt->locked = !!git_worktree_is_locked(NULL, wt);
+
+ *out = wt;
+
+out:
+ if (error)
+ git_worktree_free(wt);
+ git_buf_free(&gitdir);
+
+ return error;
+}
+
int git_worktree_lookup(git_worktree **out, git_repository *repo, const char *name)
{
git_buf path = GIT_BUF_INIT;
@@ -125,33 +174,47 @@ int git_worktree_lookup(git_worktree **out, git_repository *repo, const char *na
if ((error = git_buf_printf(&path, "%s/worktrees/%s", repo->commondir, name)) < 0)
goto out;
- if (!is_worktree_dir(&path)) {
- error = -1;
+ if ((error = (open_worktree_dir(out, git_repository_workdir(repo), path.ptr, name))) < 0)
goto out;
- }
- if ((wt = git__malloc(sizeof(struct git_repository))) == NULL) {
+out:
+ git_buf_free(&path);
+
+ if (error)
+ git_worktree_free(wt);
+
+ return error;
+}
+
+int git_worktree_open_from_repository(git_worktree **out, git_repository *repo)
+{
+ git_buf parent = GIT_BUF_INIT;
+ const char *gitdir, *commondir;
+ char *name = NULL;
+ int error = 0;
+
+ if (!git_repository_is_worktree(repo)) {
+ giterr_set(GITERR_WORKTREE, "cannot open worktree of a non-worktree repo");
error = -1;
goto out;
}
- if ((wt->name = git__strdup(name)) == NULL
- || (wt->commondir_path = git_worktree__read_link(path.ptr, "commondir")) == NULL
- || (wt->gitlink_path = git_worktree__read_link(path.ptr, "gitdir")) == NULL
- || (wt->parent_path = git__strdup(git_repository_path(repo))) == NULL) {
- error = -1;
+ gitdir = git_repository_path(repo);
+ commondir = git_repository_commondir(repo);
+
+ if ((error = git_path_prettify_dir(&parent, "..", commondir)) < 0)
goto out;
- }
- wt->gitdir_path = git_buf_detach(&path);
- wt->locked = !!git_worktree_is_locked(NULL, wt);
- (*out) = wt;
+ /* The name is defined by the last component in '.git/worktree/%s' */
+ name = git_path_basename(gitdir);
-out:
- git_buf_free(&path);
+ if ((error = open_worktree_dir(out, parent.ptr, gitdir, name)) < 0)
+ goto out;
+out:
if (error)
- git_worktree_free(wt);
+ free(name);
+ git_buf_free(&parent);
return error;
}
@@ -177,7 +240,7 @@ int git_worktree_validate(const git_worktree *wt)
assert(wt);
git_buf_puts(&buf, wt->gitdir_path);
- if (!is_worktree_dir(&buf)) {
+ if (!is_worktree_dir(buf.ptr)) {
giterr_set(GITERR_WORKTREE,
"Worktree gitdir ('%s') is not valid",
wt->gitlink_path);
@@ -209,7 +272,7 @@ out:
int git_worktree_add(git_worktree **out, git_repository *repo, const char *name, const char *worktree)
{
- git_buf path = GIT_BUF_INIT, buf = GIT_BUF_INIT;
+ git_buf gitdir = GIT_BUF_INIT, wddir = GIT_BUF_INIT, buf = GIT_BUF_INIT;
git_reference *ref = NULL, *head = NULL;
git_commit *commit = NULL;
git_repository *wt = NULL;
@@ -220,35 +283,39 @@ int git_worktree_add(git_worktree **out, git_repository *repo, const char *name,
*out = NULL;
- /* Create worktree related files in commondir */
- if ((err = git_buf_joinpath(&path, repo->commondir, "worktrees")) < 0)
+ /* Create gitdir directory ".git/worktrees/<name>" */
+ if ((err = git_buf_joinpath(&gitdir, repo->commondir, "worktrees")) < 0)
goto out;
- if (!git_path_exists(path.ptr))
- if ((err = git_futils_mkdir(path.ptr, 0755, GIT_MKDIR_EXCL)) < 0)
+ if (!git_path_exists(gitdir.ptr))
+ if ((err = git_futils_mkdir(gitdir.ptr, 0755, GIT_MKDIR_EXCL)) < 0)
goto out;
- if ((err = git_buf_joinpath(&path, path.ptr, name)) < 0)
+ if ((err = git_buf_joinpath(&gitdir, gitdir.ptr, name)) < 0)
+ goto out;
+ if ((err = git_futils_mkdir(gitdir.ptr, 0755, GIT_MKDIR_EXCL)) < 0)
goto out;
- if ((err = git_futils_mkdir(path.ptr, 0755, GIT_MKDIR_EXCL)) < 0)
+ if ((err = git_path_prettify_dir(&gitdir, gitdir.ptr, NULL)) < 0)
goto out;
/* Create worktree work dir */
if ((err = git_futils_mkdir(worktree, 0755, GIT_MKDIR_EXCL)) < 0)
goto out;
+ if ((err = git_path_prettify_dir(&wddir, worktree, NULL)) < 0)
+ goto out;
/* Create worktree .git file */
- if ((err = git_buf_printf(&buf, "gitdir: %s\n", path.ptr)) < 0)
+ if ((err = git_buf_printf(&buf, "gitdir: %s\n", gitdir.ptr)) < 0)
goto out;
- if ((err = write_wtfile(worktree, ".git", &buf)) < 0)
+ if ((err = write_wtfile(wddir.ptr, ".git", &buf)) < 0)
goto out;
- /* Create commondir files */
- if ((err = git_buf_sets(&buf, repo->commondir)) < 0
+ /* Create gitdir files */
+ if ((err = git_path_prettify_dir(&buf, repo->commondir, NULL) < 0)
|| (err = git_buf_putc(&buf, '\n')) < 0
- || (err = write_wtfile(path.ptr, "commondir", &buf)) < 0)
+ || (err = write_wtfile(gitdir.ptr, "commondir", &buf)) < 0)
goto out;
- if ((err = git_buf_joinpath(&buf, worktree, ".git")) < 0
+ if ((err = git_buf_joinpath(&buf, wddir.ptr, ".git")) < 0
|| (err = git_buf_putc(&buf, '\n')) < 0
- || (err = write_wtfile(path.ptr, "gitdir", &buf)) < 0)
+ || (err = write_wtfile(gitdir.ptr, "gitdir", &buf)) < 0)
goto out;
/* Create new branch */
@@ -260,9 +327,9 @@ int git_worktree_add(git_worktree **out, git_repository *repo, const char *name,
goto out;
/* Set worktree's HEAD */
- if ((err = git_repository_create_head(path.ptr, name)) < 0)
+ if ((err = git_repository_create_head(gitdir.ptr, git_reference_name(ref))) < 0)
goto out;
- if ((err = git_repository_open(&wt, worktree)) < 0)
+ if ((err = git_repository_open(&wt, wddir.ptr)) < 0)
goto out;
/* Checkout worktree's HEAD */
@@ -275,7 +342,8 @@ int git_worktree_add(git_worktree **out, git_repository *repo, const char *name,
goto out;
out:
- git_buf_free(&path);
+ git_buf_free(&gitdir);
+ git_buf_free(&wddir);
git_buf_free(&buf);
git_reference_free(ref);
git_reference_free(head);
@@ -394,7 +462,7 @@ int git_worktree_prune(git_worktree *wt, unsigned flags)
}
/* Delete gitdir in parent repository */
- if ((err = git_buf_printf(&path, "%s/worktrees/%s", wt->parent_path, wt->name)) < 0)
+ if ((err = git_buf_printf(&path, "%s/worktrees/%s", wt->commondir_path, wt->name)) < 0)
goto out;
if (!git_path_exists(path.ptr))
{
diff --git a/src/worktree.h b/src/worktree.h
index b8e527968..57c2e65f0 100644
--- a/src/worktree.h
+++ b/src/worktree.h
@@ -24,7 +24,7 @@ struct git_worktree {
/* Path to the common directory contained in the parent
* repository */
char *commondir_path;
- /* Path to the parent's .git directory */
+ /* Path to the parent's working directory */
char *parent_path;
int locked:1;
diff --git a/tests/core/posix.c b/tests/core/posix.c
index 018d0c8ba..172462073 100644
--- a/tests/core/posix.c
+++ b/tests/core/posix.c
@@ -94,10 +94,7 @@ void test_core_posix__inet_pton(void)
cl_assert(p_inet_pton(AF_INET, "10.foo.bar.1", &addr) == 0);
/* Test unsupported address families */
- cl_git_fail(p_inet_pton(12, "52.472", &addr)); /* AF_DECnet */
- cl_assert_equal_i(EAFNOSUPPORT, errno);
-
- cl_git_fail(p_inet_pton(5, "315.124", &addr)); /* AF_CHAOS */
+ cl_git_fail(p_inet_pton(INT_MAX-1, "52.472", &addr));
cl_assert_equal_i(EAFNOSUPPORT, errno);
}
diff --git a/tests/odb/loose.c b/tests/odb/loose.c
index c91927c4a..dd686aa01 100644
--- a/tests/odb/loose.c
+++ b/tests/odb/loose.c
@@ -3,6 +3,7 @@
#include "git2/odb_backend.h"
#include "posix.h"
#include "loose_data.h"
+#include "repository.h"
#ifdef __ANDROID_API__
# define S_IREAD S_IRUSR
@@ -56,11 +57,13 @@ static void test_read_object(object_data *data)
void test_odb_loose__initialize(void)
{
+ p_fsync__cnt = 0;
cl_must_pass(p_mkdir("test-objects", GIT_OBJECT_DIR_MODE));
}
void test_odb_loose__cleanup(void)
{
+ cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_SYNCHRONOUS_OBJECT_CREATION, 0));
cl_fixture_cleanup("test-objects");
}
@@ -150,3 +153,55 @@ void test_odb_loose__permissions_readwrite(void)
{
test_write_object_permission(0777, 0666, 0777, 0666);
}
+
+static void write_object_to_loose_odb(int fsync)
+{
+ git_odb *odb;
+ git_odb_backend *backend;
+ git_oid oid;
+
+ cl_git_pass(git_odb_new(&odb));
+ cl_git_pass(git_odb_backend_loose(&backend, "test-objects", -1, fsync, 0777, 0666));
+ cl_git_pass(git_odb_add_backend(odb, backend, 1));
+ cl_git_pass(git_odb_write(&oid, odb, "Test data\n", 10, GIT_OBJ_BLOB));
+ git_odb_free(odb);
+}
+
+void test_odb_loose__does_not_fsync_by_default(void)
+{
+ write_object_to_loose_odb(0);
+ cl_assert_equal_sz(0, p_fsync__cnt);
+}
+
+void test_odb_loose__fsync_obeys_odb_option(void)
+{
+ write_object_to_loose_odb(1);
+ cl_assert(p_fsync__cnt > 0);
+}
+
+void test_odb_loose__fsync_obeys_global_setting(void)
+{
+ cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_SYNCHRONOUS_OBJECT_CREATION, 1));
+ write_object_to_loose_odb(0);
+ cl_assert(p_fsync__cnt > 0);
+}
+
+void test_odb_loose__fsync_obeys_repo_setting(void)
+{
+ git_repository *repo;
+ git_odb *odb;
+ git_oid oid;
+
+ cl_git_pass(git_repository_init(&repo, "test-objects", 1));
+ cl_git_pass(git_repository_odb__weakptr(&odb, repo));
+ cl_git_pass(git_odb_write(&oid, odb, "No fsync here\n", 14, GIT_OBJ_BLOB));
+ cl_assert(p_fsync__cnt == 0);
+ git_repository_free(repo);
+
+ cl_git_pass(git_repository_open(&repo, "test-objects"));
+ cl_repo_set_bool(repo, "core.fsyncObjectFiles", true);
+ cl_git_pass(git_repository_odb__weakptr(&odb, repo));
+ cl_git_pass(git_odb_write(&oid, odb, "Now fsync\n", 10, GIT_OBJ_BLOB));
+ cl_assert(p_fsync__cnt > 0);
+ git_repository_free(repo);
+}
diff --git a/tests/pack/packbuilder.c b/tests/pack/packbuilder.c
index 29f3e2d64..1d7becef7 100644
--- a/tests/pack/packbuilder.c
+++ b/tests/pack/packbuilder.c
@@ -23,6 +23,7 @@ void test_pack_packbuilder__initialize(void)
cl_git_pass(git_vector_init(&_commits, 0, NULL));
_commits_is_initialized = 1;
memset(&_stats, 0, sizeof(_stats));
+ p_fsync__cnt = 0;
}
void test_pack_packbuilder__cleanup(void)
@@ -30,6 +31,8 @@ void test_pack_packbuilder__cleanup(void)
git_oid *o;
unsigned int i;
+ cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_SYNCHRONOUS_OBJECT_CREATION, 0));
+
if (_commits_is_initialized) {
_commits_is_initialized = 0;
git_vector_foreach(&_commits, i, o) {
@@ -188,6 +191,40 @@ void test_pack_packbuilder__permissions_readwrite(void)
test_write_pack_permission(0666, 0666);
}
+void test_pack_packbuilder__does_not_fsync_by_default(void)
+{
+ seed_packbuilder();
+ git_packbuilder_write(_packbuilder, ".", 0666, NULL, NULL);
+ cl_assert_equal_sz(0, p_fsync__cnt);
+}
+
+/* We fsync the packfile and index. On non-Windows, we also fsync
+ * the parent directories.
+ */
+#ifdef GIT_WIN32
+static int expected_fsyncs = 2;
+#else
+static int expected_fsyncs = 4;
+#endif
+
+void test_pack_packbuilder__fsync_global_setting(void)
+{
+ cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_SYNCHRONOUS_OBJECT_CREATION, 1));
+ p_fsync__cnt = 0;
+ seed_packbuilder();
+ git_packbuilder_write(_packbuilder, ".", 0666, NULL, NULL);
+ cl_assert_equal_sz(expected_fsyncs, p_fsync__cnt);
+}
+
+void test_pack_packbuilder__fsync_repo_setting(void)
+{
+ cl_repo_set_bool(_repo, "core.fsyncObjectFiles", true);
+ p_fsync__cnt = 0;
+ seed_packbuilder();
+ git_packbuilder_write(_packbuilder, ".", 0666, NULL, NULL);
+ cl_assert_equal_sz(expected_fsyncs, p_fsync__cnt);
+}
+
static int foreach_cb(void *buf, size_t len, void *payload)
{
git_indexer *idx = (git_indexer *) payload;
diff --git a/tests/refs/create.c b/tests/refs/create.c
index aca808c8c..4ecc60565 100644
--- a/tests/refs/create.c
+++ b/tests/refs/create.c
@@ -13,6 +13,7 @@ static git_repository *g_repo;
void test_refs_create__initialize(void)
{
g_repo = cl_git_sandbox_init("testrepo");
+ p_fsync__cnt = 0;
}
void test_refs_create__cleanup(void)
@@ -21,6 +22,7 @@ void test_refs_create__cleanup(void)
cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_STRICT_OBJECT_CREATION, 1));
cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_STRICT_SYMBOLIC_REF_CREATION, 1));
+ cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_SYNCHRONOUS_OBJECT_CREATION, 0));
}
void test_refs_create__symbolic(void)
@@ -297,3 +299,69 @@ void test_refs_create__creating_a_loose_ref_with_invalid_windows_name(void)
test_win32_name("refs/heads/com1");
}
+
+/* Creating a loose ref involves fsync'ing the reference, the
+ * reflog and (on non-Windows) the containing directories.
+ * Creating a packed ref involves fsync'ing the packed ref file
+ * and (on non-Windows) the containing directory.
+ */
+#ifdef GIT_WIN32
+static int expected_fsyncs_create = 2, expected_fsyncs_compress = 1;
+#else
+static int expected_fsyncs_create = 4, expected_fsyncs_compress = 2;
+#endif
+
+static void count_fsyncs(size_t *create_count, size_t *compress_count)
+{
+ git_reference *ref = NULL;
+ git_refdb *refdb;
+ git_oid id;
+
+ p_fsync__cnt = 0;
+
+ git_oid_fromstr(&id, current_master_tip);
+ cl_git_pass(git_reference_create(&ref, g_repo, "refs/heads/fsync_test", &id, 0, "log message"));
+ git_reference_free(ref);
+
+ *create_count = p_fsync__cnt;
+ p_fsync__cnt = 0;
+
+ cl_git_pass(git_repository_refdb(&refdb, g_repo));
+ cl_git_pass(git_refdb_compress(refdb));
+ git_refdb_free(refdb);
+
+ *compress_count = p_fsync__cnt;
+ p_fsync__cnt = 0;
+}
+
+void test_refs_create__does_not_fsync_by_default(void)
+{
+ size_t create_count, compress_count;
+ count_fsyncs(&create_count, &compress_count);
+
+ cl_assert_equal_i(0, create_count);
+ cl_assert_equal_i(0, compress_count);
+}
+
+void test_refs_create__fsyncs_when_global_opt_set(void)
+{
+ size_t create_count, compress_count;
+
+ cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_SYNCHRONOUS_OBJECT_CREATION, 1));
+ count_fsyncs(&create_count, &compress_count);
+
+ cl_assert_equal_i(expected_fsyncs_create, create_count);
+ cl_assert_equal_i(expected_fsyncs_compress, compress_count);
+}
+
+void test_refs_create__fsyncs_when_repo_config_set(void)
+{
+ size_t create_count, compress_count;
+
+ cl_repo_set_bool(g_repo, "core.fsyncObjectFiles", true);
+
+ count_fsyncs(&create_count, &compress_count);
+
+ cl_assert_equal_i(expected_fsyncs_create, create_count);
+ cl_assert_equal_i(expected_fsyncs_compress, compress_count);
+}
diff --git a/tests/resources/submodules/testrepo/.gitted/config b/tests/resources/submodules/testrepo/.gitted/config
index d6dcad12b..8e5571191 100644
--- a/tests/resources/submodules/testrepo/.gitted/config
+++ b/tests/resources/submodules/testrepo/.gitted/config
@@ -4,9 +4,6 @@
bare = false
logallrefupdates = true
ignorecase = true
-[remote "origin"]
- fetch = +refs/heads/*:refs/remotes/origin/*
- url = /Users/rb/src/libgit2/tests/resources/testrepo.git
[branch "master"]
remote = origin
merge = refs/heads/master
diff --git a/tests/worktree/open.c b/tests/worktree/open.c
index bdc8bcf9d..74b9007d9 100644
--- a/tests/worktree/open.c
+++ b/tests/worktree/open.c
@@ -1,13 +1,14 @@
#include "clar_libgit2.h"
#include "repository.h"
+#include "worktree.h"
#include "worktree_helpers.h"
-#define WORKTREE_PARENT "submodules-worktree-parent"
-#define WORKTREE_CHILD "submodules-worktree-child"
-
#define COMMON_REPO "testrepo"
#define WORKTREE_REPO "testrepo-worktree"
+static worktree_fixture fixture =
+ WORKTREE_FIXTURE_INIT(COMMON_REPO, WORKTREE_REPO);
+
static void assert_worktree_valid(git_repository *wt, const char *parentdir, const char *wtdir)
{
git_buf path = GIT_BUF_INIT;
@@ -34,56 +35,46 @@ static void assert_worktree_valid(git_repository *wt, const char *parentdir, con
git_buf_free(&path);
}
-void test_worktree_open__repository(void)
+void test_worktree_open__initialize(void)
{
- worktree_fixture fixture =
- WORKTREE_FIXTURE_INIT(COMMON_REPO, WORKTREE_REPO);
setup_fixture_worktree(&fixture);
+}
- assert_worktree_valid(fixture.worktree, COMMON_REPO, WORKTREE_REPO);
-
+void test_worktree_open__cleanup(void)
+{
cleanup_fixture_worktree(&fixture);
}
+void test_worktree_open__repository(void)
+{
+ assert_worktree_valid(fixture.worktree, COMMON_REPO, WORKTREE_REPO);
+}
+
void test_worktree_open__repository_through_workdir(void)
{
- worktree_fixture fixture =
- WORKTREE_FIXTURE_INIT(COMMON_REPO, WORKTREE_REPO);
git_repository *wt;
- setup_fixture_worktree(&fixture);
-
cl_git_pass(git_repository_open(&wt, WORKTREE_REPO));
assert_worktree_valid(wt, COMMON_REPO, WORKTREE_REPO);
git_repository_free(wt);
- cleanup_fixture_worktree(&fixture);
}
void test_worktree_open__repository_through_gitlink(void)
{
- worktree_fixture fixture =
- WORKTREE_FIXTURE_INIT(COMMON_REPO, WORKTREE_REPO);
git_repository *wt;
- setup_fixture_worktree(&fixture);
-
cl_git_pass(git_repository_open(&wt, WORKTREE_REPO "/.git"));
assert_worktree_valid(wt, COMMON_REPO, WORKTREE_REPO);
git_repository_free(wt);
- cleanup_fixture_worktree(&fixture);
}
void test_worktree_open__repository_through_gitdir(void)
{
- worktree_fixture fixture =
- WORKTREE_FIXTURE_INIT(COMMON_REPO, WORKTREE_REPO);
git_buf gitdir_path = GIT_BUF_INIT;
git_repository *wt;
- setup_fixture_worktree(&fixture);
-
cl_git_pass(git_buf_joinpath(&gitdir_path, COMMON_REPO, ".git"));
cl_git_pass(git_buf_joinpath(&gitdir_path, gitdir_path.ptr, "worktrees"));
cl_git_pass(git_buf_joinpath(&gitdir_path, gitdir_path.ptr, "testrepo-worktree"));
@@ -93,18 +84,13 @@ void test_worktree_open__repository_through_gitdir(void)
git_buf_free(&gitdir_path);
git_repository_free(wt);
- cleanup_fixture_worktree(&fixture);
}
void test_worktree_open__open_discovered_worktree(void)
{
- worktree_fixture fixture =
- WORKTREE_FIXTURE_INIT(COMMON_REPO, WORKTREE_REPO);
git_buf path = GIT_BUF_INIT;
git_repository *repo;
- setup_fixture_worktree(&fixture);
-
cl_git_pass(git_repository_discover(&path,
git_repository_workdir(fixture.worktree), false, NULL));
cl_git_pass(git_repository_open(&repo, path.ptr));
@@ -113,13 +99,14 @@ void test_worktree_open__open_discovered_worktree(void)
git_buf_free(&path);
git_repository_free(repo);
- cleanup_fixture_worktree(&fixture);
}
void test_worktree_open__repository_with_nonexistent_parent(void)
{
git_repository *repo;
+ cleanup_fixture_worktree(&fixture);
+
cl_fixture_sandbox(WORKTREE_REPO);
cl_git_pass(p_chdir(WORKTREE_REPO));
cl_git_pass(cl_rename(".gitted", ".git"));
@@ -130,65 +117,27 @@ void test_worktree_open__repository_with_nonexistent_parent(void)
cl_fixture_cleanup(WORKTREE_REPO);
}
-void test_worktree_open__submodule_worktree_parent(void)
+void test_worktree_open__open_from_repository(void)
{
- worktree_fixture fixture =
- WORKTREE_FIXTURE_INIT("submodules", WORKTREE_PARENT);
- setup_fixture_worktree(&fixture);
-
- cl_assert(git_repository_path(fixture.worktree) != NULL);
- cl_assert(git_repository_workdir(fixture.worktree) != NULL);
+ git_worktree *opened, *lookedup;
- cl_assert(!fixture.repo->is_worktree);
- cl_assert(fixture.worktree->is_worktree);
+ cl_git_pass(git_worktree_open_from_repository(&opened, fixture.worktree));
+ cl_git_pass(git_worktree_lookup(&lookedup, fixture.repo, WORKTREE_REPO));
- cleanup_fixture_worktree(&fixture);
-}
+ cl_assert_equal_s(opened->name, lookedup->name);
+ cl_assert_equal_s(opened->gitdir_path, lookedup->gitdir_path);
+ cl_assert_equal_s(opened->gitlink_path, lookedup->gitlink_path);
+ cl_assert_equal_s(opened->parent_path, lookedup->parent_path);
+ cl_assert_equal_s(opened->commondir_path, lookedup->commondir_path);
+ cl_assert_equal_i(opened->locked, lookedup->locked);
-void test_worktree_open__submodule_worktree_child(void)
-{
- worktree_fixture parent_fixture =
- WORKTREE_FIXTURE_INIT("submodules", WORKTREE_PARENT);
- worktree_fixture child_fixture =
- WORKTREE_FIXTURE_INIT(NULL, WORKTREE_CHILD);
-
- setup_fixture_worktree(&parent_fixture);
- cl_git_pass(p_rename(
- "submodules/testrepo/.gitted",
- "submodules/testrepo/.git"));
- setup_fixture_worktree(&child_fixture);
-
- cl_assert(!parent_fixture.repo->is_worktree);
- cl_assert(parent_fixture.worktree->is_worktree);
- cl_assert(child_fixture.worktree->is_worktree);
-
- cleanup_fixture_worktree(&child_fixture);
- cleanup_fixture_worktree(&parent_fixture);
+ git_worktree_free(opened);
+ git_worktree_free(lookedup);
}
-void test_worktree_open__open_discovered_submodule_worktree(void)
+void test_worktree_open__open_from_nonworktree_fails(void)
{
- worktree_fixture parent_fixture =
- WORKTREE_FIXTURE_INIT("submodules", WORKTREE_PARENT);
- worktree_fixture child_fixture =
- WORKTREE_FIXTURE_INIT(NULL, WORKTREE_CHILD);
- git_buf path = GIT_BUF_INIT;
- git_repository *repo;
-
- setup_fixture_worktree(&parent_fixture);
- cl_git_pass(p_rename(
- "submodules/testrepo/.gitted",
- "submodules/testrepo/.git"));
- setup_fixture_worktree(&child_fixture);
-
- cl_git_pass(git_repository_discover(&path,
- git_repository_workdir(child_fixture.worktree), false, NULL));
- cl_git_pass(git_repository_open(&repo, path.ptr));
- cl_assert_equal_s(git_repository_workdir(child_fixture.worktree),
- git_repository_workdir(repo));
+ git_worktree *wt;
- git_buf_free(&path);
- git_repository_free(repo);
- cleanup_fixture_worktree(&child_fixture);
- cleanup_fixture_worktree(&parent_fixture);
+ cl_git_fail(git_worktree_open_from_repository(&wt, fixture.repo));
}
diff --git a/tests/worktree/refs.c b/tests/worktree/refs.c
index ccac8be29..b9a05606d 100644
--- a/tests/worktree/refs.c
+++ b/tests/worktree/refs.c
@@ -1,4 +1,6 @@
#include "clar_libgit2.h"
+#include "path.h"
+#include "refs.h"
#include "worktree.h"
#include "worktree_helpers.h"
@@ -128,3 +130,27 @@ void test_worktree_refs__delete_succeeds_after_pruning_worktree(void)
cl_git_pass(git_branch_delete(branch));
git_reference_free(branch);
}
+
+void test_worktree_refs__creating_refs_uses_commondir(void)
+{
+ git_reference *head, *branch, *lookup;
+ git_commit *commit;
+ git_buf refpath = GIT_BUF_INIT;
+
+ cl_git_pass(git_buf_joinpath(&refpath,
+ git_repository_commondir(fixture.worktree), "refs/heads/testbranch"));
+ cl_assert(!git_path_exists(refpath.ptr));
+
+ cl_git_pass(git_repository_head(&head, fixture.worktree));
+ cl_git_pass(git_commit_lookup(&commit, fixture.worktree, git_reference_target(head)));
+ cl_git_pass(git_branch_create(&branch, fixture.worktree, "testbranch", commit, 0));
+ cl_git_pass(git_branch_lookup(&lookup, fixture.worktree, "testbranch", GIT_BRANCH_LOCAL));
+ cl_assert(git_reference_cmp(branch, lookup) == 0);
+ cl_assert(git_path_exists(refpath.ptr));
+
+ git_reference_free(lookup);
+ git_reference_free(branch);
+ git_reference_free(head);
+ git_commit_free(commit);
+ git_buf_free(&refpath);
+}
diff --git a/tests/worktree/submodule.c b/tests/worktree/submodule.c
new file mode 100644
index 000000000..562077597
--- /dev/null
+++ b/tests/worktree/submodule.c
@@ -0,0 +1,92 @@
+#include "clar_libgit2.h"
+#include "repository.h"
+#include "worktree.h"
+#include "worktree_helpers.h"
+
+#define WORKTREE_PARENT "submodules-worktree-parent"
+#define WORKTREE_CHILD "submodules-worktree-child"
+
+static worktree_fixture parent
+ = WORKTREE_FIXTURE_INIT("submodules", WORKTREE_PARENT);
+static worktree_fixture child
+ = WORKTREE_FIXTURE_INIT(NULL, WORKTREE_CHILD);
+
+void test_worktree_submodule__initialize(void)
+{
+ setup_fixture_worktree(&parent);
+
+ cl_git_pass(p_rename(
+ "submodules/testrepo/.gitted",
+ "submodules/testrepo/.git"));
+
+ setup_fixture_worktree(&child);
+}
+
+void test_worktree_submodule__cleanup(void)
+{
+ cleanup_fixture_worktree(&child);
+ cleanup_fixture_worktree(&parent);
+}
+
+void test_worktree_submodule__submodule_worktree_parent(void)
+{
+ cl_assert(git_repository_path(parent.worktree) != NULL);
+ cl_assert(git_repository_workdir(parent.worktree) != NULL);
+
+ cl_assert(!parent.repo->is_worktree);
+ cl_assert(parent.worktree->is_worktree);
+}
+
+void test_worktree_submodule__submodule_worktree_child(void)
+{
+ cl_assert(!parent.repo->is_worktree);
+ cl_assert(parent.worktree->is_worktree);
+ cl_assert(child.worktree->is_worktree);
+}
+
+void test_worktree_submodule__open_discovered_submodule_worktree(void)
+{
+ git_buf path = GIT_BUF_INIT;
+ git_repository *repo;
+
+ cl_git_pass(git_repository_discover(&path,
+ git_repository_workdir(child.worktree), false, NULL));
+ cl_git_pass(git_repository_open(&repo, path.ptr));
+ cl_assert_equal_s(git_repository_workdir(child.worktree),
+ git_repository_workdir(repo));
+
+ git_buf_free(&path);
+ git_repository_free(repo);
+}
+
+void test_worktree_submodule__resolve_relative_url(void)
+{
+ git_buf wt_path = GIT_BUF_INIT;
+ git_buf sm_relative_path = GIT_BUF_INIT, wt_relative_path = GIT_BUF_INIT;
+ git_repository *repo;
+ git_worktree *wt;
+
+ cl_git_pass(git_futils_mkdir("subdir", 0755, GIT_MKDIR_PATH));
+ cl_git_pass(git_path_prettify_dir(&wt_path, "subdir", NULL));
+ cl_git_pass(git_buf_joinpath(&wt_path, wt_path.ptr, "wt"));
+
+ /* Open child repository, which is a submodule */
+ cl_git_pass(git_repository_open(&child.repo, WORKTREE_CHILD));
+
+ /* Create worktree of submodule repository */
+ cl_git_pass(git_worktree_add(&wt, child.repo, "subdir", wt_path.ptr));
+ cl_git_pass(git_repository_open_from_worktree(&repo, wt));
+
+ cl_git_pass(git_submodule_resolve_url(&sm_relative_path, repo,
+ "../" WORKTREE_CHILD));
+ cl_git_pass(git_submodule_resolve_url(&wt_relative_path, child.repo,
+ "../" WORKTREE_CHILD));
+
+ cl_assert_equal_s(sm_relative_path.ptr, wt_relative_path.ptr);
+
+ git_worktree_free(wt);
+ git_repository_free(repo);
+ git_buf_free(&wt_path);
+ git_buf_free(&sm_relative_path);
+ git_buf_free(&wt_relative_path);
+}
diff --git a/tests/worktree/worktree.c b/tests/worktree/worktree.c
index f0c423599..6e90e6ac0 100644
--- a/tests/worktree/worktree.c
+++ b/tests/worktree/worktree.c
@@ -115,11 +115,12 @@ void test_worktree_worktree__lookup(void)
cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
- git_buf_printf(&gitdir_path, "%s/worktrees/%s", fixture.repo->commondir, "testrepo-worktree");
+ cl_git_pass(git_buf_joinpath(&gitdir_path, fixture.repo->commondir, "worktrees/testrepo-worktree/"));
cl_assert_equal_s(wt->gitdir_path, gitdir_path.ptr);
- cl_assert_equal_s(wt->parent_path, fixture.repo->gitdir);
+ cl_assert_equal_s(wt->parent_path, fixture.repo->workdir);
cl_assert_equal_s(wt->gitlink_path, fixture.worktree->gitlink);
+ cl_assert_equal_s(wt->commondir_path, fixture.repo->gitdir);
cl_assert_equal_s(wt->commondir_path, fixture.repo->commondir);
git_buf_free(&gitdir_path);
@@ -305,7 +306,9 @@ void test_worktree_worktree__init_submodule(void)
cl_git_pass(git_worktree_add(&worktree, sm, "repo-worktree", path.ptr));
cl_git_pass(git_repository_open_from_worktree(&wt, worktree));
+ cl_git_pass(git_path_prettify_dir(&path, path.ptr, NULL));
cl_assert_equal_s(path.ptr, wt->workdir);
+ cl_git_pass(git_path_prettify_dir(&path, sm->commondir, NULL));
cl_assert_equal_s(sm->commondir, wt->commondir);
cl_git_pass(git_buf_joinpath(&path, sm->gitdir, "worktrees/repo-worktree/"));