153 lines
2.7 KiB
C
153 lines
2.7 KiB
C
#include <git2/repository.h>
|
|
#include <git2/types.h>
|
|
#include <linux/limits.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sys/stat.h>
|
|
#include <stdint.h>
|
|
#include <errno.h>
|
|
|
|
#include "hash.h"
|
|
#include "helpers.h"
|
|
|
|
#ifdef GITHASH
|
|
static uint64_t
|
|
murmur64(uint64_t k)
|
|
{
|
|
PS();
|
|
k ^= k >> 33;
|
|
k *= 0xff51afd7ed558ccdLLU;
|
|
k ^= k >> 33;
|
|
k *= 0xc4ceb9fe1a85ec53LLU;
|
|
k ^= k >> 33;
|
|
|
|
PE();
|
|
return k;
|
|
}
|
|
|
|
uint64_t
|
|
generate_hash(git_repository *repo)
|
|
{
|
|
PS();
|
|
struct stat dir, index;
|
|
char path[PATH_MAX] = { 0 };
|
|
|
|
const char *gitpath = git_repository_path(repo);
|
|
if (strlen(gitpath) + strlen("/..") > PATH_MAX - 1) {
|
|
L("strlen: %s", strerror(errno));
|
|
PE();
|
|
return -1;
|
|
}
|
|
|
|
strcat(path, gitpath);
|
|
if (stat(path, &index) < 0) {
|
|
PE();
|
|
return -1;
|
|
}
|
|
strcat(path, "/..");
|
|
if (stat(path, &dir) < 0) {
|
|
PE();
|
|
return -1;
|
|
}
|
|
PE();
|
|
return murmur64(dir.st_mtim.tv_nsec ^ index.st_mtim.tv_nsec);
|
|
}
|
|
|
|
repohash
|
|
*read_hash(git_repository *repo)
|
|
{
|
|
PS();
|
|
FILE *f;
|
|
uint64_t data;
|
|
uint8_t changes;
|
|
repohash *hash = malloc(sizeof(repohash));
|
|
char path[PATH_MAX] = { 0 };
|
|
|
|
const char *gitpath = git_repository_path(repo);
|
|
if (strlen(gitpath) + strlen(XD_HASH_PATH) > PATH_MAX - 1) {
|
|
L("strlen: %s", strerror(errno));
|
|
PE();
|
|
return NULL;
|
|
}
|
|
strcat(path, gitpath);
|
|
strcat(path, XD_HASH_PATH);
|
|
|
|
f = fopen(path, "r");
|
|
if (!f) {
|
|
L("fopen: %s", strerror(errno));
|
|
PE();
|
|
return NULL;
|
|
}
|
|
|
|
if (fread(&data, sizeof(uint64_t), 1, f) != 1) {
|
|
L("fread: %s", strerror(errno));
|
|
PE();
|
|
return NULL;
|
|
}
|
|
|
|
if (fseek(f, sizeof(uint64_t), SEEK_SET) < 0) {
|
|
L("fseek: %s", strerror(errno));
|
|
PE();
|
|
return NULL;
|
|
}
|
|
|
|
if (fread(&changes, sizeof(uint8_t), 1, f) != 1) {
|
|
L("fread: %s", strerror(errno));
|
|
PE();
|
|
return NULL;
|
|
}
|
|
fclose(f);
|
|
|
|
hash->hash = data;
|
|
hash->changes = changes;
|
|
PE();
|
|
return hash;
|
|
}
|
|
|
|
int
|
|
write_hash(git_repository *repo, repohash hash)
|
|
{
|
|
PS();
|
|
FILE *f;
|
|
char path[PATH_MAX] = { 0 };
|
|
|
|
const char *gitpath = git_repository_path(repo);
|
|
if (strlen(gitpath) + strlen(XD_HASH_PATH) > PATH_MAX - 1) {
|
|
L("strlen: %s", strerror(errno));
|
|
PE();
|
|
return 1;
|
|
}
|
|
strcat(path, gitpath);
|
|
strcat(path, XD_HASH_PATH);
|
|
|
|
f = fopen(path, "wb");
|
|
if (!f) {
|
|
L("fopen: %s", strerror(errno));
|
|
PE();
|
|
return 1;
|
|
}
|
|
|
|
if (fwrite(&hash.hash, sizeof(uint64_t), 1, f) != 1) {
|
|
L("fwrite: %s", strerror(errno));
|
|
PE();
|
|
return 1;
|
|
}
|
|
|
|
if (fseek(f, sizeof(uint64_t), SEEK_SET) < 0) {
|
|
L("fseek: %s", strerror(errno));
|
|
PE();
|
|
return 1;
|
|
}
|
|
|
|
if (fwrite(&hash.changes, sizeof(uint8_t), 1, f) != 1) {
|
|
L("fwrite: %s", strerror(errno));
|
|
PE();
|
|
return 1;
|
|
}
|
|
|
|
fclose(f);
|
|
PE();
|
|
return 0;
|
|
}
|
|
#endif
|