如何比较 Github API 哈希与本地文件哈希?

问题描述 投票:0回答:1

我正在尝试将本地文件的哈希值与来自

GitHub
API 的哈希值进行比较;

当我拨打

test.txt
时,我已经创建了 compute_sha1_hash 并将其上传到我的
repo
test.txt

2aae6c35c94fcfb415dbe95f408b9ce91ee846ed

GitHub
API 响应:

      "path": "test.txt",
      "mode": "100644",
      "type": "blob",
      "sha": "95d09f2b10159347eece71399a7e2e907ea3df4f",

从我搜索的内容来看,GitHub 使用的是

SHA1
,为什么值不匹配?

我需要在此哈希中进行任何类型的计算来检索“本地文件哈希”吗?

我写了一个工作示例

#include <curl/curl.h>
#include <openssl/evp.h>
#include <fstream>
#include <vector>
#include <sstream>
#include <iomanip>
#include <iostream>
#include <regex>

std::string compute_sha1_hash(const std::string& file_path)
{
    std::ifstream file(file_path, std::ios::binary);
    if (!file) {
        throw std::runtime_error("Could not open file");
    }

    EVP_MD_CTX* mdctx = EVP_MD_CTX_new();
    if (mdctx == NULL) {
        throw std::runtime_error("Failed to create EVP_MD_CTX");
    }

    if (EVP_DigestInit_ex(mdctx, EVP_sha1(), NULL) != 1) {
        throw std::runtime_error("Failed to initialize SHA-1 context");
    }

    std::vector<char> buffer(4096);
    while (file.read(buffer.data(), buffer.size())) {
        if (EVP_DigestUpdate(mdctx, buffer.data(), file.gcount()) != 1) {
            throw std::runtime_error("Failed to update SHA-1 context");
        }
    }

    if (file.gcount() > 0) {
        if (EVP_DigestUpdate(mdctx, buffer.data(), file.gcount()) != 1) {
            throw std::runtime_error("Failed to update SHA-1 context");
        }
    }

    std::vector<unsigned char> hash_value(EVP_MD_size(EVP_sha1()));
    unsigned int digest_len;
    if (EVP_DigestFinal_ex(mdctx, hash_value.data(), &digest_len) != 1) {
        throw std::runtime_error("Failed to finalize SHA-1 context");
    }

    EVP_MD_CTX_free(mdctx);

    // Convert to hex
    std::ostringstream oss;
    for (const auto& byte : hash_value) {
        oss << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(byte);
    }

    return oss.str();
}

static size_t WriteMemoryCallback(void* contents, size_t size, size_t nmemb, void* userp) 
{
    size_t realsize = size * nmemb;
    auto& mem = *static_cast<std::string*>(userp);
    mem.append(static_cast<char*>(contents), realsize);
    return realsize;
}

void curl(std::string& data, const char* url)
{
    CURL* curl_handle = curl_easy_init();
    curl_easy_setopt(curl_handle, CURLOPT_URL, url);
    curl_easy_setopt(curl_handle, CURLOPT_TCP_KEEPALIVE, 0);
    curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
    curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, &data);
    curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0");
    curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1L);  // redirects
    CURLcode res = curl_easy_perform(curl_handle);
    if(res != CURLE_OK)
        std::cerr << "curl_easy_perform failed: " << curl_easy_strerror(res) << '\n';
    curl_easy_cleanup(curl_handle);
    curl_global_cleanup();
}

int main() 
{
    std::string fileHash = compute_sha1_hash("C:/Users/jabu/test.txt");
    std::string jsonString;
    curl(jsonString, "https://api.github.com/repos/jajabu33/test/git/trees/main?recursive=1");

    // just to kick compare the strings
    std::regex shaPattern("\"sha\":\\s*\"([a-fA-F0-9]+)\"");
    std::sregex_iterator shaIterator(jsonString.begin(), jsonString.end(), shaPattern);
    std::sregex_iterator endIterator;

    std::string githubHash;
    for (; shaIterator != endIterator; ++shaIterator)
    {
        std::smatch match = *shaIterator;
        if (match.size() >= 2)
            githubHash = match[1].str();
    }

    if (fileHash == githubHash)
        std::cout << "Hashes are equal\n";
    else
        std::cout << "Hashes are not equal\n";
    return 0;
}
c++ github github-api
1个回答
0
投票

您正在查看 blob 的哈希值,而不是文件的哈希值。除了文件内容之外,Blob 还包含标头。

您可以使用

git hash-object
来计算文件的 blob ID:

git hash-object test.txt

另请参阅 Git 内部 - Git 对象

© www.soinside.com 2019 - 2024. All rights reserved.