Compare commits
15 Commits
90853294da
...
master
Author | SHA1 | Date | |
---|---|---|---|
feeaab1ebe | |||
7aed1eed11 | |||
d8de4e070e | |||
fe46da5417 | |||
a3cbb20a53 | |||
1d119cb63e | |||
a336b507fb | |||
84c422ee38 | |||
4ab36ec64f | |||
7ba9cb8147 | |||
5338c30e79 | |||
2d8a947cb4 | |||
f3680754ec | |||
73340cbb7a | |||
65f72eca79 |
@@ -31,11 +31,13 @@ int main(int argc, char *argv[])
|
|||||||
//TariffCalculatorHandle handle = NewTariffCalculator();
|
//TariffCalculatorHandle handle = NewTariffCalculator();
|
||||||
//DeleteTariffCalculator(handle);
|
//DeleteTariffCalculator(handle);
|
||||||
|
|
||||||
if (InitGitLibrary() > 0) {
|
//if (InitGitLibrary() > 0) {
|
||||||
qCritical() << CloneRepository("https://git.mimbach49.de/GerhardHoffmann/customer_999.git", "C:\\tmp\\customer_999");
|
// qCritical() << CloneRepository("https://git.mimbach49.de/GerhardHoffmann/customer_999.git", "C:\\tmp\\customer_999");
|
||||||
qCritical() << CheckoutLocalBranch("C:\\tmp\\customer_999", "master");
|
// qCritical() << CheckoutLocalBranch("C:\\tmp\\customer_999", "master");
|
||||||
ShutdownGitLibrary();
|
// ShutdownGitLibrary();
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
qCritical() << GetFileMenuSize("customer_999");
|
||||||
#else
|
#else
|
||||||
QLibrary library("C:\\build-ATBTariffCalculator-Desktop_Qt_6_5_0_MinGW_64_bit-Release\\CalculatorCInterface\\release\\CalculatorCInterface.dll");
|
QLibrary library("C:\\build-ATBTariffCalculator-Desktop_Qt_6_5_0_MinGW_64_bit-Release\\CalculatorCInterface\\release\\CalculatorCInterface.dll");
|
||||||
if (library.load()) {
|
if (library.load()) {
|
||||||
|
@@ -28,12 +28,17 @@ CONFIG += c++20 console
|
|||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
calculator_c_interface_lib.cpp \
|
calculator_c_interface_lib.cpp \
|
||||||
tariff_calculator.cpp
|
git_library.cpp \
|
||||||
|
tariff_calculator.cpp \
|
||||||
|
local_git_repository.cpp
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
calculator_c_interface_lib.h \
|
calculator_c_interface_lib.h \
|
||||||
calculator_c_interface_lib_global.h \
|
calculator_c_interface_lib_global.h \
|
||||||
tariff_calculator.h
|
git_library.h \
|
||||||
|
tariff_calculator.h \
|
||||||
|
local_git_repository.h \
|
||||||
|
global_defines.h
|
||||||
|
|
||||||
# Default rules for deployment.
|
# Default rules for deployment.
|
||||||
unix {
|
unix {
|
||||||
|
@@ -1,21 +1,26 @@
|
|||||||
#include "calculator_c_interface_lib.h"
|
#include "calculator_c_interface_lib.h"
|
||||||
|
#include "local_git_repository.h"
|
||||||
|
#include "git_library.h"
|
||||||
|
|
||||||
//#include <git2/common.h>
|
//#include <git2/common.h>
|
||||||
|
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
|
#include <QFile>
|
||||||
|
#include <QByteArray>
|
||||||
|
#include <QRegularExpression>
|
||||||
|
#include <QRegularExpressionMatch>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
|
|
||||||
#include <git2.h>
|
#include <git2.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
static QMap<QString, git_repository *> customerRepoMap;
|
//static QMap<QString, git_repository *> customerRepoMap;
|
||||||
static std::mutex m;
|
//static std::mutex m;
|
||||||
static char const *user = NULL;
|
|
||||||
static char const *pass = NULL;
|
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
# include <unistd.h>
|
# include <unistd.h>
|
||||||
@@ -26,241 +31,6 @@ static char const *pass = NULL;
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// see https://libgit2.org/libgit2/ex/HEAD/checkout.html
|
|
||||||
|
|
||||||
/* Define t/he printf format specifier to use for size_t output */
|
|
||||||
#if defined(_MSC_VER) || defined(__MINGW32__)
|
|
||||||
# define PRIuZ "Illu"
|
|
||||||
# define PRIxZ "Illx"
|
|
||||||
# define PRIdZ "Illd"
|
|
||||||
#else
|
|
||||||
# define PRIuZ "zu"
|
|
||||||
# define PRIxZ "zx"
|
|
||||||
# define PRIdZ "zd"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
unsigned int force : 1;
|
|
||||||
unsigned int progress : 1;
|
|
||||||
unsigned int perf : 1;
|
|
||||||
} checkout_options;
|
|
||||||
|
|
||||||
int cred_acquire_cb(git_credential **out,
|
|
||||||
const char *url,
|
|
||||||
const char *username_from_url,
|
|
||||||
unsigned int allowed_types,
|
|
||||||
void *payload)
|
|
||||||
{
|
|
||||||
char const *username = user, *password = pass;
|
|
||||||
|
|
||||||
fprintf(stderr, "%s:%d: opened repository %s %s\n", __func__, __LINE__, username, password);
|
|
||||||
|
|
||||||
Q_UNUSED(url);
|
|
||||||
Q_UNUSED(username_from_url);
|
|
||||||
Q_UNUSED(payload);
|
|
||||||
int error = -1;
|
|
||||||
|
|
||||||
if (allowed_types & GIT_CREDENTIAL_USERPASS_PLAINTEXT) {
|
|
||||||
error = git_credential_userpass_plaintext_new(out, username, password);
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "GIT_CREDENTIAL_USERPASS_PLAINTEXT not supported by protocol (allowed_types=%08x)\n", allowed_types);
|
|
||||||
}
|
|
||||||
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool check(int error, const char *message, const char *extra) {
|
|
||||||
const git_error *lg2err;
|
|
||||||
const char *lg2msg = "", *lg2spacer = "";
|
|
||||||
|
|
||||||
if (!error) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((lg2err = git_error_last()) != NULL && lg2err->message != NULL) {
|
|
||||||
lg2msg = lg2err->message;
|
|
||||||
lg2spacer = " - ";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (extra)
|
|
||||||
fprintf(stderr, "%s '%s' [%d]%s%s\n",
|
|
||||||
message, extra, error, lg2spacer, lg2msg);
|
|
||||||
else
|
|
||||||
fprintf(stderr, "%s [%d]%s%s\n",
|
|
||||||
message, error, lg2spacer, lg2msg);
|
|
||||||
|
|
||||||
// exit(1);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void print_checkout_progress(const char *path, size_t completed_steps, size_t total_steps, void *payload) {
|
|
||||||
(void)payload;
|
|
||||||
if (path == NULL) {
|
|
||||||
printf("checkout started: %" PRIuZ " steps\n", total_steps);
|
|
||||||
} else {
|
|
||||||
printf("checkout: %s %" PRIuZ "/%" PRIuZ "\n", path, completed_steps, total_steps);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void print_perf_data(const git_checkout_perfdata *perfdata, void *payload) {
|
|
||||||
(void)payload;
|
|
||||||
printf("perf: stat: %" PRIuZ " mkdir: %" PRIuZ " chmod: %" PRIuZ "\n",
|
|
||||||
perfdata->stat_calls, perfdata->mkdir_calls, perfdata->chmod_calls);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int resolve_refish(git_annotated_commit **commit, git_repository *repo, const char *refish)
|
|
||||||
{
|
|
||||||
git_reference *ref;
|
|
||||||
git_object *obj;
|
|
||||||
int err = 0;
|
|
||||||
|
|
||||||
assert(commit != NULL);
|
|
||||||
|
|
||||||
err = git_reference_dwim(&ref, repo, refish);
|
|
||||||
if (err == GIT_OK) {
|
|
||||||
git_annotated_commit_from_ref(commit, repo, ref);
|
|
||||||
git_reference_free(ref);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = git_revparse_single(&obj, repo, refish);
|
|
||||||
if (err == GIT_OK) {
|
|
||||||
err = git_annotated_commit_lookup(commit, repo, git_object_id(obj));
|
|
||||||
git_object_free(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int perform_checkout_ref(git_repository *repo,
|
|
||||||
git_annotated_commit *target,
|
|
||||||
const char *target_ref, checkout_options *opts) {
|
|
||||||
git_checkout_options checkout_opts;
|
|
||||||
git_reference *ref = NULL, *branch = NULL;
|
|
||||||
git_commit *target_commit = NULL;
|
|
||||||
int err;
|
|
||||||
|
|
||||||
if ((err = git_checkout_options_init(&checkout_opts, GIT_CHECKOUT_OPTIONS_VERSION)) < 0) {
|
|
||||||
fprintf(stderr, "error checkout options init %s\n", git_error_last()->message);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Setup our checkout options from the parsed options
|
|
||||||
|
|
||||||
checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE;
|
|
||||||
|
|
||||||
// if (opts->force)
|
|
||||||
// checkout_opts.checkout_strategy = GIT_CHECKOUT_FORCE;
|
|
||||||
|
|
||||||
// if (opts->progress)
|
|
||||||
// checkout_opts.progress_cb = print_checkout_progress;
|
|
||||||
|
|
||||||
// if (opts->perf)
|
|
||||||
// checkout_opts.perfdata_cb = print_perf_data;
|
|
||||||
|
|
||||||
// Grab the commit we're interested to move to
|
|
||||||
|
|
||||||
err = git_commit_lookup(&target_commit, repo, git_annotated_commit_id(target));
|
|
||||||
if (err != 0) {
|
|
||||||
fprintf(stderr, "failed to lookup commit: %s\n", git_error_last()->message);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Perform the checkout so the workdir corresponds to what target_commit contains.
|
|
||||||
// Note that it's okay to pass a git_commit here, because it will be peeled to a tree.
|
|
||||||
|
|
||||||
err = git_checkout_tree(repo, (const git_object *)target_commit, &checkout_opts);
|
|
||||||
if (err != 0) {
|
|
||||||
fprintf(stderr, "failed to checkout tree: %s\n", git_error_last()->message);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now that the checkout has completed, we have to update HEAD.
|
|
||||||
// Depending on the "origin" of target (ie. it's an OID or a branch name), we might need to detach HEAD.
|
|
||||||
|
|
||||||
if (git_annotated_commit_ref(target)) {
|
|
||||||
const char *target_head;
|
|
||||||
|
|
||||||
if ((err = git_reference_lookup(&ref, repo, git_annotated_commit_ref(target))) < 0)
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
if (git_reference_is_remote(ref)) {
|
|
||||||
if ((err = git_branch_create_from_annotated(&branch, repo, target_ref, target, 0)) < 0)
|
|
||||||
goto error;
|
|
||||||
target_head = git_reference_name(branch);
|
|
||||||
} else {
|
|
||||||
target_head = git_annotated_commit_ref(target);
|
|
||||||
}
|
|
||||||
|
|
||||||
err = git_repository_set_head(repo, target_head);
|
|
||||||
} else {
|
|
||||||
err = git_repository_set_head_detached_from_annotated(repo, target);
|
|
||||||
}
|
|
||||||
|
|
||||||
error:
|
|
||||||
if (err != 0) {
|
|
||||||
fprintf(stderr, "failed to update HEAD reference: %s\n", git_error_last()->message);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
cleanup:
|
|
||||||
git_commit_free(target_commit);
|
|
||||||
git_reference_free(branch);
|
|
||||||
git_reference_free(ref);
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int guess_refish(git_annotated_commit **out, git_repository *repo, const char *ref) {
|
|
||||||
git_strarray remotes = { NULL, 0 };
|
|
||||||
git_reference *remote_ref = NULL;
|
|
||||||
int error;
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
if ((error = git_remote_list(&remotes, repo)) < 0) {
|
|
||||||
fprintf(stderr, "error git_remote_list %s\n", git_error_last()->message);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < remotes.count; i++) {
|
|
||||||
char *refname = NULL;
|
|
||||||
size_t reflen;
|
|
||||||
|
|
||||||
reflen = snprintf(refname, 0, "refs/remotes/%s/%s", remotes.strings[i], ref);
|
|
||||||
if ((refname = (char *)malloc(reflen + 1)) == NULL) {
|
|
||||||
error = -1;
|
|
||||||
fprintf(stderr, "%s:%d malloc failed\n", __func__, __LINE__);
|
|
||||||
goto next;
|
|
||||||
}
|
|
||||||
snprintf(refname, reflen + 1, "refs/remotes/%s/%s", remotes.strings[i], ref);
|
|
||||||
|
|
||||||
if ((error = git_reference_lookup(&remote_ref, repo, refname)) < 0) {
|
|
||||||
fprintf(stderr, "git reference lookup %s\n", git_error_last()->message);
|
|
||||||
goto next;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
next:
|
|
||||||
free(refname);
|
|
||||||
refname = NULL;
|
|
||||||
if (error < 0 && error != GIT_ENOTFOUND) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!remote_ref) {
|
|
||||||
error = GIT_ENOTFOUND;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((error = git_annotated_commit_from_ref(out, repo, remote_ref)) < 0)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
out:
|
|
||||||
git_reference_free(remote_ref);
|
|
||||||
git_strarray_dispose(&remotes);
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
TariffCalculatorHandle NewTariffCalculator(void) {
|
TariffCalculatorHandle NewTariffCalculator(void) {
|
||||||
return new TariffCalculator();
|
return new TariffCalculator();
|
||||||
@@ -270,326 +40,108 @@ void DeleteTariffCalculator(TariffCalculatorHandle handle) {
|
|||||||
delete handle;
|
delete handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
int InitGitLibrary(void) {
|
int InitGitLibraryInternal(void) {
|
||||||
return git_libgit2_init();
|
return GitLibrary::Init();
|
||||||
}
|
}
|
||||||
|
|
||||||
int ShutdownGitLibrary(void) {
|
int ShutdownGitLibraryInternal(void) {
|
||||||
|
LocalGitRepository::DestroyAllRepositories();
|
||||||
for (auto key : customerRepoMap.keys()) {
|
return GitLibrary::Shutdown();
|
||||||
git_repository_free(customerRepoMap.value(key));
|
|
||||||
}
|
|
||||||
customerRepoMap.clear();
|
|
||||||
return git_libgit2_shutdown();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int CloneRepository(char const *url, char const *local_path) {
|
int CloneRepositoryInternal(char const *url, char const *local_path) {
|
||||||
|
return GitLibrary::CloneRepository(url, local_path);
|
||||||
QString localRepoPath(QDir::cleanPath(QString(local_path) + QDir::separator() + ".git"));
|
|
||||||
QDir localRepoDir(localRepoPath);
|
|
||||||
|
|
||||||
if (localRepoDir.exists()) {
|
|
||||||
fprintf(stderr, "local repository path %s already exists\n",
|
|
||||||
localRepoPath.toUtf8().constData());
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
git_repository *out;
|
int CheckoutRepositoryInternal(char const *url, char const *localRepoName, char const *branchName) {
|
||||||
git_clone_options opts;
|
return GitLibrary::CheckoutRepository(url, localRepoName, branchName);
|
||||||
int res = 0;
|
|
||||||
|
|
||||||
if ((res = git_clone_options_init(&opts, GIT_CLONE_OPTIONS_VERSION)) == 0) {
|
|
||||||
opts.checkout_branch = "master";
|
|
||||||
|
|
||||||
fprintf(stderr, "%s:%d %s %s\n", __func__, __LINE__, url, local_path);
|
|
||||||
|
|
||||||
if ((res = git_clone(&out, url, local_path, &opts)) < 0) {
|
|
||||||
git_error const *error = git_error_last();
|
|
||||||
fprintf(stderr, "%s:%d error: %s\n", __func__, __LINE__, error->message);
|
|
||||||
} else {
|
|
||||||
QString localRepoPath = QDir::cleanPath(QString(local_path) + QDir::separator() + ".git");
|
|
||||||
customerRepoMap.insert(localRepoPath, out);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
git_error const *error = git_error_last();
|
|
||||||
fprintf(stderr, "%s:%d error: %s\n", __func__, __LINE__, error->message);
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int CheckoutLocalBranch(char const *local_path, char const *branch_name) {
|
int CommitFileInternal(char const *localRepoName, char const *branchName,
|
||||||
int err = 0;
|
char const *fName, char const *commitMessage) {
|
||||||
checkout_options opts;
|
return GitLibrary::CommitFile(localRepoName, branchName, fName, commitMessage);
|
||||||
git_repository_state_t state = GIT_REPOSITORY_STATE_NONE;
|
|
||||||
git_annotated_commit *checkout_target = NULL;
|
|
||||||
git_repository *repo = NULL;
|
|
||||||
git_reference *branch_ref = NULL;
|
|
||||||
|
|
||||||
QString localRepoPath(QDir::cleanPath(QString(local_path) + QDir::separator() + ".git"));
|
|
||||||
QDir localRepoDir(localRepoPath);
|
|
||||||
|
|
||||||
if (!localRepoDir.exists()) {
|
|
||||||
fprintf(stderr, "local repository path %s does not exist\n",
|
|
||||||
localRepoPath.toUtf8().constData());
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!customerRepoMap.contains(localRepoPath)) {
|
int PushRepositoryInternal(char const *localRepoName, char const *branchName,
|
||||||
if ((err = git_repository_open(&repo, localRepoPath.toUtf8().constData())) != 0) {
|
char const *userName, char const *userPassword) {
|
||||||
fprintf(stderr, "repository %s cannot be opened: %s\n",
|
return GitLibrary::PushRepository(localRepoName, branchName, userName, userPassword);
|
||||||
localRepoPath.toUtf8().constData(), git_error_last()->message);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
customerRepoMap.insert(localRepoPath, repo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (customerRepoMap.contains(localRepoPath)) {
|
int PullRepositoryInternal(char const *localRepoName, char const *remoteRepoName) {
|
||||||
repo = customerRepoMap[localRepoPath];
|
return GitLibrary::PullRepository(localRepoName, remoteRepoName);
|
||||||
|
|
||||||
// Make sure we're not about to checkout while something else is going on
|
|
||||||
if ((state = (git_repository_state_t)git_repository_state(repo)) != GIT_REPOSITORY_STATE_NONE) {
|
|
||||||
fprintf(stderr, "repository %s is in unexpected state %d\n",
|
|
||||||
localRepoPath.toUtf8().constData(), state);
|
|
||||||
err = -1;
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "repository %s is in state %d\n",
|
|
||||||
localRepoPath.toUtf8().constData(), state);
|
|
||||||
|
|
||||||
if ((err = resolve_refish(&checkout_target, repo, branch_name)) < 0 &&
|
|
||||||
(err = guess_refish(&checkout_target, repo, branch_name)) < 0) {
|
|
||||||
fprintf(stderr, "failed to resolve %s: %s\n", branch_name, git_error_last()->message);
|
|
||||||
} else {
|
|
||||||
if ((err = perform_checkout_ref(repo, checkout_target, branch_name, &opts)) == 0) {
|
|
||||||
fprintf(stderr, "%s:%d checkout ok\n", __func__, __LINE__);
|
|
||||||
if ((err = git_branch_lookup(&branch_ref, repo, branch_name, GIT_BRANCH_LOCAL)) != 0) {
|
|
||||||
if (err == GIT_ENOTFOUND) {
|
|
||||||
fprintf(stderr, "local branch %s not found\n", branch_name);
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "local branch %s not found: %s\n",
|
|
||||||
branch_name, git_error_last()->message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (branch_ref) {
|
#include <local_git_repository.h>
|
||||||
git_reference_free(branch_ref);
|
|
||||||
|
|
||||||
|
void SetReposRootDirectoryInternal(char const *p) {
|
||||||
|
LocalGitRepository::SetReposRootDirectory(QString::fromUtf8(p));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (checkout_target) {
|
char const *GetReposRootDirectoryInternal() {
|
||||||
git_annotated_commit_free(checkout_target);
|
return (char const *)LocalGitRepository::GetReposRootDirectory().constData();
|
||||||
}
|
}
|
||||||
|
|
||||||
return err;
|
char const *GetLocalRepositoryPathInternal(char const *localGitRepo) {
|
||||||
|
return (char const *)LocalGitRepository::GetInstance(localGitRepo)->localRepositoryPath().constData();
|
||||||
}
|
}
|
||||||
|
|
||||||
int CommitFile(char const *local_path, char const *branch_name,
|
int32_t GetFileMenuSizeInternal(char const *localGitRepo) {
|
||||||
char const *file_name, char const *comment) {
|
return LocalGitRepository::GetInstance(localGitRepo)->GetFileMenuSizeInternal();
|
||||||
assert(local_path != NULL);
|
|
||||||
assert(branch_name != NULL);
|
|
||||||
assert(file_name != NULL);
|
|
||||||
assert(comment != NULL);
|
|
||||||
|
|
||||||
fprintf(stderr, "%s %s %s %s\n",
|
|
||||||
local_path, branch_name, file_name, comment);
|
|
||||||
|
|
||||||
QString const currentWD = QDir::currentPath();
|
|
||||||
|
|
||||||
QString localPath(local_path);
|
|
||||||
if (!QDir(localPath).exists()) {
|
|
||||||
fprintf(stderr, "local path %s for file %s does not exist\n",
|
|
||||||
localPath.toUtf8().constData(), file_name);
|
|
||||||
QDir::setCurrent(currentWD);
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!QDir::setCurrent(localPath)) {
|
char const *GetFileMenuInternal(const char *localGitRepo) {
|
||||||
fprintf(stderr, "can not set cwd path %s\n", localPath.toUtf8().constData());
|
QByteArray const &a = LocalGitRepository::GetInstance(localGitRepo)->GetFileMenuInternal().constData();
|
||||||
QDir::setCurrent(currentWD);
|
if (a.isValidUtf8()) {
|
||||||
return -1;
|
int const len = GetFileMenuSizeInternal(localGitRepo);
|
||||||
}
|
if (len > 0) {
|
||||||
|
char *json = new char [len+1];
|
||||||
fprintf(stderr, "cwd %s\n", QDir::current().absolutePath().toUtf8().constData());
|
// fprintf(stderr, "allocate pointer %p\n", json);
|
||||||
|
memset(json, 0x00, len+1);
|
||||||
git_repository *repo = NULL;
|
memcpy(json, a.constData(), std::min(len, (int)a.size()));
|
||||||
int error = 0;
|
return json;
|
||||||
|
|
||||||
QString localRepoPath(QDir::cleanPath(QString(local_path) + QDir::separator() + ".git"));
|
|
||||||
QDir localRepoDir(localRepoPath);
|
|
||||||
|
|
||||||
if (!localRepoDir.exists()) {
|
|
||||||
fprintf(stderr, "local repository path %s does not exist\n",
|
|
||||||
localRepoPath.toUtf8().constData());
|
|
||||||
QDir::setCurrent(currentWD);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!customerRepoMap.contains(localRepoPath)) {
|
|
||||||
if ((error = git_repository_open(&repo, localRepoPath.toUtf8().constData())) != 0) {
|
|
||||||
fprintf(stderr, "repository %s cannot be opened: %s\n",
|
|
||||||
localRepoPath.toUtf8().constData(), git_error_last()->message);
|
|
||||||
QDir::setCurrent(currentWD);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
customerRepoMap.insert(localRepoPath, repo);
|
|
||||||
}
|
|
||||||
|
|
||||||
git_oid commit_oid,tree_oid;
|
|
||||||
git_tree *tree = NULL;
|
|
||||||
git_index *index = NULL;
|
|
||||||
git_object *parent = NULL;
|
|
||||||
git_reference *ref = NULL;
|
|
||||||
git_signature *signature = NULL;
|
|
||||||
git_repository_state_t state = GIT_REPOSITORY_STATE_NONE;
|
|
||||||
|
|
||||||
if (customerRepoMap.contains(localRepoPath)) {
|
|
||||||
repo = customerRepoMap[localRepoPath];
|
|
||||||
|
|
||||||
if (git_repository_head_unborn(repo) == 1) {
|
|
||||||
fprintf(stderr, "HEAD unborn. Create first commit\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure we're not about to checkout while something else is going on
|
|
||||||
if ((state = (git_repository_state_t)git_repository_state(repo)) != GIT_REPOSITORY_STATE_NONE) {
|
|
||||||
fprintf(stderr, "repository %s is in unexpected state %d\n",
|
|
||||||
localRepoPath.toUtf8().constData(), state);
|
|
||||||
error = -1;
|
|
||||||
} else {
|
|
||||||
error = git_revparse_ext(&parent, &ref, repo, "HEAD");
|
|
||||||
if (error == GIT_ENOTFOUND) {
|
|
||||||
fprintf(stderr, "HEAD not found. Creating first commit\n");
|
|
||||||
error = 0;
|
|
||||||
} else if (error != 0) {
|
|
||||||
const git_error *err = git_error_last();
|
|
||||||
if (err) {
|
|
||||||
fprintf(stderr, "ERROR %d: %s\n", err->klass, err->message);
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "ERROR %d: no detailed info\n", error);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return nullptr;
|
||||||
if (error == 0) {
|
|
||||||
if (check(git_repository_index(&index, repo), "Could not open repository index", NULL) &&
|
|
||||||
check(git_index_write_tree(&tree_oid, index), "Could not write tree", NULL) &&
|
|
||||||
check(git_index_write(index), "Could not write index", NULL) &&
|
|
||||||
check(git_tree_lookup(&tree, repo, &tree_oid), "Error looking up tree", NULL) &&
|
|
||||||
check(git_signature_default(&signature, repo), "Error creating signature", NULL) &&
|
|
||||||
check(git_commit_create_v(&commit_oid, repo, "HEAD", signature, signature,
|
|
||||||
NULL, comment, tree, parent ? 1 : 0, parent),
|
|
||||||
"Error creating commit", NULL)) {
|
|
||||||
fprintf(stderr, "%s %s %s %s\n",
|
|
||||||
local_path, branch_name, file_name, comment);
|
|
||||||
fprintf(stderr, "git commit ok\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (index) {
|
|
||||||
git_index_free(index);
|
|
||||||
}
|
|
||||||
if (signature) {
|
|
||||||
git_signature_free(signature);
|
|
||||||
}
|
|
||||||
if (tree) {
|
|
||||||
git_tree_free(tree);
|
|
||||||
}
|
|
||||||
if (parent) {
|
|
||||||
git_object_free(parent);
|
|
||||||
}
|
|
||||||
if (ref) {
|
|
||||||
git_reference_free(ref);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QDir::setCurrent(currentWD);
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
int PushLocalRepository(char const *local_path, char const *branch_name, char const *username, char const *password) {
|
|
||||||
git_repository *repo = NULL;
|
|
||||||
int error = -1;
|
|
||||||
|
|
||||||
fprintf(stderr, "%s:%d: %s %s\n", __func__, __LINE__, local_path, branch_name);
|
|
||||||
|
|
||||||
QString const currentWD = QDir::currentPath();
|
|
||||||
|
|
||||||
QString localRepoPath(QDir::cleanPath(QString(local_path) + QDir::separator() + ".git"));
|
|
||||||
QDir localRepoDir(localRepoPath);
|
|
||||||
|
|
||||||
if (!localRepoDir.exists()) {
|
|
||||||
fprintf(stderr, "local repository path %s does not exist\n",
|
|
||||||
localRepoPath.toUtf8().constData());
|
|
||||||
QDir::setCurrent(currentWD);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!customerRepoMap.contains(localRepoPath)) {
|
|
||||||
if ((error = git_repository_open(&repo, localRepoPath.toUtf8().constData())) != 0) {
|
|
||||||
fprintf(stderr, "repository %s cannot be opened: %s\n",
|
|
||||||
localRepoPath.toUtf8().constData(), git_error_last()->message);
|
|
||||||
QDir::setCurrent(currentWD);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
customerRepoMap.insert(localRepoPath, repo);
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(stderr, "%s:%d: opened repository\n", __func__, __LINE__);
|
|
||||||
|
|
||||||
git_repository_state_t state = GIT_REPOSITORY_STATE_NONE;
|
|
||||||
git_push_options options;
|
|
||||||
git_remote_callbacks callbacks;
|
|
||||||
git_remote* remote = NULL;
|
|
||||||
char refspec_[] = "refs/heads/master";
|
|
||||||
char *refspec = refspec_;
|
|
||||||
const git_strarray refspecs = {
|
|
||||||
&refspec,
|
|
||||||
1
|
|
||||||
};
|
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(m);
|
|
||||||
|
|
||||||
user = username;
|
|
||||||
pass = password;
|
|
||||||
|
|
||||||
fprintf(stderr, "%s:%d: opened repository %s %s\n", __func__, __LINE__, user, pass);
|
|
||||||
|
|
||||||
if (customerRepoMap.contains(localRepoPath)) {
|
|
||||||
repo = customerRepoMap[localRepoPath];
|
|
||||||
|
|
||||||
// Make sure we're not about to checkout while something else is going on
|
|
||||||
if ((state = (git_repository_state_t)git_repository_state(repo)) != GIT_REPOSITORY_STATE_NONE) {
|
|
||||||
fprintf(stderr, "repository %s is in unexpected state %d\n",
|
|
||||||
localRepoPath.toUtf8().constData(), state);
|
|
||||||
} else {
|
|
||||||
if (check(git_remote_lookup(&remote, repo, "origin" ), "Unable to lookup remote", NULL)) {
|
|
||||||
if (check(git_remote_init_callbacks(&callbacks, GIT_REMOTE_CALLBACKS_VERSION),
|
|
||||||
"Error initializing remote callbacks", NULL)) {
|
|
||||||
callbacks.credentials = cred_acquire_cb;
|
|
||||||
if (check(git_push_options_init(&options, GIT_PUSH_OPTIONS_VERSION ),
|
|
||||||
"Error initializing push", NULL)) {
|
|
||||||
options.callbacks = callbacks;
|
|
||||||
if (check(git_remote_push(remote, &refspecs, &options), "Error pushing", NULL)) {
|
|
||||||
fprintf(stderr, "%s:%d: pushed %s (branch: %s)\n", __func__, __LINE__, local_path, branch_name);
|
|
||||||
error = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (remote) {
|
|
||||||
git_remote_free(remote);
|
|
||||||
}
|
|
||||||
|
|
||||||
QDir::setCurrent(currentWD);
|
|
||||||
return error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char const *GetFileNameInternal(char const *localGitRepo, char const *fileId) {
|
||||||
|
QByteArray const &a = LocalGitRepository::GetInstance(localGitRepo)->GetFileNameInternal(fileId);
|
||||||
|
if (a.isValidUtf8()) {
|
||||||
|
char *c = new char[a.size() + 1];
|
||||||
|
memset(c, 0x00, a.size() + 1);
|
||||||
|
memcpy(c, a.constData(), a.size());
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t GetFileSize(char const *localGitRepo, char const *fileId) {
|
||||||
|
return LocalGitRepository::GetInstance(localGitRepo)->GetFileSize(fileId);
|
||||||
|
}
|
||||||
|
|
||||||
|
char const *GetFileInternal(char const *localGitRepo, char const *fileId) {
|
||||||
|
QByteArray const &a = LocalGitRepository::GetInstance(localGitRepo)->GetFileInternal(fileId);
|
||||||
|
if (a.isValidUtf8()) {
|
||||||
|
char *c = new char[a.size() + 1];
|
||||||
|
memset(c, 0x00, a.size() + 1);
|
||||||
|
memcpy(c, a.constData(), a.size());
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SetFileInternal(char const *localGitRepo, char const *fileId, char const *json, int size) {
|
||||||
|
return LocalGitRepository::GetInstance(localGitRepo)->SetFileInternal(QString(fileId), QByteArray(json, size));
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeleteMem(char *p) {
|
||||||
|
if (p) {
|
||||||
|
// fprintf(stderr, "delete pointer %p\n", p);
|
||||||
|
delete p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
#ifndef CALCULATOR_C_INTERFACE_LIB_H_INCLUDED
|
#ifndef CALCULATOR_C_INTERFACE_LIB_H_INCLUDED
|
||||||
#define CALCULATOR_C_INTERFACE_LIB_H_INCLUDED
|
#define CALCULATOR_C_INTERFACE_LIB_H_INCLUDED
|
||||||
|
|
||||||
#include "calculator_c_interface_lib_global.h"
|
#include "calculator_c_interface_lib_global.h"
|
||||||
#include "tariff_calculator.h"
|
#include "tariff_calculator.h"
|
||||||
|
|
||||||
@@ -10,16 +9,31 @@ typedef TariffCalculator *TariffCalculatorHandle;
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void DeleteMem(char *p) CALCULATOR_C_INTERFACE_LIB_EXPORT;
|
||||||
|
void SetReposRootDirectoryInternal(char const *p) CALCULATOR_C_INTERFACE_LIB_EXPORT;
|
||||||
|
char const *GetReposRootDirectoryInternal() CALCULATOR_C_INTERFACE_LIB_EXPORT;
|
||||||
|
char const *GetLocalRepositoryPathInternal(char const *localRepo) CALCULATOR_C_INTERFACE_LIB_EXPORT;
|
||||||
|
|
||||||
|
// interface for menu of webpage
|
||||||
|
char const *GetFileMenuInternal(char const *localRepo) CALCULATOR_C_INTERFACE_LIB_EXPORT;
|
||||||
|
int32_t GetFileMenuSizeInternal(char const *localRepo) CALCULATOR_C_INTERFACE_LIB_EXPORT;
|
||||||
|
|
||||||
|
char const *GetFileNameInternal(char const *localRepo, char const *fileId) CALCULATOR_C_INTERFACE_LIB_EXPORT;
|
||||||
|
int32_t GetFileSize(char const *localRepo, char const *fileId) CALCULATOR_C_INTERFACE_LIB_EXPORT;
|
||||||
|
char const *GetFileInternal(char const *localRepo, char const *fileId) CALCULATOR_C_INTERFACE_LIB_EXPORT;
|
||||||
|
bool SetFileInternal(char const *localRepo, char const *fileId, char const *json, int size) CALCULATOR_C_INTERFACE_LIB_EXPORT;
|
||||||
|
|
||||||
TariffCalculatorHandle NewTariffCalculator(void) CALCULATOR_C_INTERFACE_LIB_EXPORT;
|
TariffCalculatorHandle NewTariffCalculator(void) CALCULATOR_C_INTERFACE_LIB_EXPORT;
|
||||||
void DeleteTariffCalculator(TariffCalculatorHandle handle) CALCULATOR_C_INTERFACE_LIB_EXPORT;
|
void DeleteTariffCalculator(TariffCalculatorHandle handle) CALCULATOR_C_INTERFACE_LIB_EXPORT;
|
||||||
|
|
||||||
// libgit2
|
// libgit2
|
||||||
int InitGitLibrary(void) CALCULATOR_C_INTERFACE_LIB_EXPORT;
|
int InitGitLibraryInternal(void) CALCULATOR_C_INTERFACE_LIB_EXPORT;
|
||||||
int ShutdownGitLibrary(void) CALCULATOR_C_INTERFACE_LIB_EXPORT;
|
int ShutdownGitLibraryInternal(void) CALCULATOR_C_INTERFACE_LIB_EXPORT;
|
||||||
int CloneRepository(char const *url, char const *local_path) CALCULATOR_C_INTERFACE_LIB_EXPORT;
|
int CloneRepositoryInternal(char const *url, char const *local_path) CALCULATOR_C_INTERFACE_LIB_EXPORT;
|
||||||
int CheckoutLocalBranch(char const *local_path, char const *branch) CALCULATOR_C_INTERFACE_LIB_EXPORT;
|
int CheckoutRepositoryInternal(char const *url, char const *localRepoName, char const *branchName) CALCULATOR_C_INTERFACE_LIB_EXPORT;
|
||||||
int CommitFile(char const *local_path, char const *branch_name, char const *file_name, char const *commit_message) CALCULATOR_C_INTERFACE_LIB_EXPORT;
|
int CommitFileInternal(char const *local_path, char const *branch_name, char const *file_name, char const *commit_message) CALCULATOR_C_INTERFACE_LIB_EXPORT;
|
||||||
int PushLocalRepository(char const *local_path, char const *branch_name, char const *user, char const *password) CALCULATOR_C_INTERFACE_LIB_EXPORT;
|
int PushRepositoryInternal(char const *local_path, char const *branch_name, char const *user, char const *password) CALCULATOR_C_INTERFACE_LIB_EXPORT;
|
||||||
|
int PullRepositoryInternal(char const *localRepoName, char const *remoteRepoName) CALCULATOR_C_INTERFACE_LIB_EXPORT;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
1025
CalculatorCInterface/git_library.cpp
Normal file
1025
CalculatorCInterface/git_library.cpp
Normal file
File diff suppressed because it is too large
Load Diff
47
CalculatorCInterface/git_library.h
Normal file
47
CalculatorCInterface/git_library.h
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
#ifndef GIT_LIBRARY_H_INCLUDED
|
||||||
|
#define GIT_LIBRARY_H_INCLUDED
|
||||||
|
|
||||||
|
#include <QByteArray>
|
||||||
|
#include <QString>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QJsonArray>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QDir>
|
||||||
|
#include <git2.h>
|
||||||
|
|
||||||
|
class CWD {
|
||||||
|
QDir m_prev;
|
||||||
|
QDir m_localRepoDir;
|
||||||
|
QDir m_localRepoGitDir;
|
||||||
|
bool m_valid;
|
||||||
|
public:
|
||||||
|
CWD(QString const &localRepoName);
|
||||||
|
~CWD();
|
||||||
|
|
||||||
|
QDir const &localRepoDir() const { return m_localRepoDir; }
|
||||||
|
QDir &localRepoDir() { return m_localRepoDir; }
|
||||||
|
QDir const &localRepoGitDir() const { return m_localRepoGitDir; }
|
||||||
|
QDir &localRepoGitDir() { return m_localRepoGitDir; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class GitLibrary {
|
||||||
|
static QString m_userName;
|
||||||
|
static QString m_userPassword;
|
||||||
|
public:
|
||||||
|
static QString &userName() { return m_userName; }
|
||||||
|
static QString &userPassword() { return m_userPassword; }
|
||||||
|
|
||||||
|
static int Init();
|
||||||
|
static int Shutdown();
|
||||||
|
static int CloneRepository(char const *url, char const *localRepoName);
|
||||||
|
static int CheckoutRepository(char const *url, char const *localRepoName, char const *branchName);
|
||||||
|
static int CommitRepository(char const *localRepoName, char const *branchName, char const *commitMessage);
|
||||||
|
static int CommitFile(char const *localRepoName, char const *branchName, char const *fName, char const *commitMessage);
|
||||||
|
static int PushRepository(char const *localRepoName, char const *branchName, char const *userName, char const *userPassword);
|
||||||
|
static int PullRepository(char const *localRepoName, char const *remoteRepoName);
|
||||||
|
|
||||||
|
// explicit GitLibrary();
|
||||||
|
// ~GitLibrary();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // #define GIT_LIBRARY_H_INCLUDED
|
7
CalculatorCInterface/global_defines.h
Normal file
7
CalculatorCInterface/global_defines.h
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#ifndef GLOBAL_DEFINES_H_INCLUDED
|
||||||
|
#define GLOBAL_DEFINES_H_INCLUDED
|
||||||
|
|
||||||
|
#define HEADER __func__ << "(" << __LINE__ << ")"
|
||||||
|
|
||||||
|
#endif // GLOBAL_DEFINES_H_INCLUDED
|
||||||
|
|
212
CalculatorCInterface/local_git_repository.cpp
Normal file
212
CalculatorCInterface/local_git_repository.cpp
Normal file
@@ -0,0 +1,212 @@
|
|||||||
|
#include "local_git_repository.h"
|
||||||
|
#include "git_library.h"
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QDir>
|
||||||
|
#include <QFile>
|
||||||
|
#include <QTextStream>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QByteArray>
|
||||||
|
#include <QRegularExpression>
|
||||||
|
#include <QRegularExpressionMatch>
|
||||||
|
#include <QFile>
|
||||||
|
|
||||||
|
|
||||||
|
QString LocalGitRepository::repoRootDirectory = "";
|
||||||
|
QMap<QString, LocalGitRepository *> LocalGitRepository::localGitRepos;
|
||||||
|
|
||||||
|
QMap<QString, LocalGitRepository *> &LocalGitRepository::GetLocalGitRepos() {
|
||||||
|
return localGitRepos;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LocalGitRepository::SetReposRootDirectory(QString s) {
|
||||||
|
if (repoRootDirectory.isEmpty()) {
|
||||||
|
repoRootDirectory = s;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
qCritical() << __func__ << ":" << __LINE__
|
||||||
|
<< "ERROR git-repository-root-directory already set"
|
||||||
|
<< repoRootDirectory;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString LocalGitRepository::GetReposRootDirectory() {
|
||||||
|
return repoRootDirectory;
|
||||||
|
}
|
||||||
|
|
||||||
|
LocalGitRepository::LocalGitRepository(QString const &localRepository)
|
||||||
|
: m_localRepository(localRepository)
|
||||||
|
, m_fileMenu("{}")
|
||||||
|
, m_fileMenuSize(-1)
|
||||||
|
, m_git_repository(nullptr) {
|
||||||
|
}
|
||||||
|
|
||||||
|
LocalGitRepository::~LocalGitRepository() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void LocalGitRepository::SetGitRepository(git_repository *git_repo) {
|
||||||
|
m_git_repository = git_repo;
|
||||||
|
}
|
||||||
|
|
||||||
|
git_repository const *LocalGitRepository::GetGitRepository() const {
|
||||||
|
return m_git_repository;
|
||||||
|
}
|
||||||
|
|
||||||
|
git_repository *LocalGitRepository::GetGitRepository() {
|
||||||
|
return m_git_repository;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString LocalGitRepository::localRepositoryName() const { // e.g. customer_999
|
||||||
|
return m_localRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString LocalGitRepository::localRepositoryPath() const {
|
||||||
|
if (!repoRootDirectory.isEmpty()) {
|
||||||
|
return QDir::cleanPath(repoRootDirectory + QDir::separator() + m_localRepository);
|
||||||
|
}
|
||||||
|
qCritical() << __func__ << ":" << __LINE__
|
||||||
|
<< "ERROR git-repository-root-directory not set";
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
QString LocalGitRepository::localRepositoryPath(QString const &localRepository) {
|
||||||
|
if (!repoRootDirectory.isEmpty()) {
|
||||||
|
return QDir::cleanPath(repoRootDirectory + QDir::separator() + localRepository);
|
||||||
|
}
|
||||||
|
qCritical() << __func__ << ":" << __LINE__
|
||||||
|
<< "ERROR git-repository-root-directory not set";
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
LocalGitRepository *LocalGitRepository::GetInstance(QString const& localRepository) {
|
||||||
|
LocalGitRepository *repo = nullptr;
|
||||||
|
if (GetLocalGitRepos().count(localRepository) > 0) {
|
||||||
|
repo = GetLocalGitRepos()[localRepository];
|
||||||
|
} else {
|
||||||
|
repo = new LocalGitRepository(localRepository);
|
||||||
|
qCritical() << "created local git-repository" << localRepository;
|
||||||
|
GetLocalGitRepos().insert(localRepository, repo);
|
||||||
|
}
|
||||||
|
if (repo == nullptr) {
|
||||||
|
qCritical() << __func__ << ":" << __LINE__
|
||||||
|
<< "ERROR: could not find local git-repository" << localRepository;
|
||||||
|
}
|
||||||
|
return repo;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LocalGitRepository::DestroyInstance(QString const &localRepository) {
|
||||||
|
if (GetLocalGitRepos().count(localRepository) > 0) {
|
||||||
|
LocalGitRepository *repo = GetLocalGitRepos().take(localRepository);
|
||||||
|
delete repo;
|
||||||
|
qCritical() << "deleted local git-repository" << localRepository;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
qCritical() << __func__ << ":" << __LINE__
|
||||||
|
<< "ERROR: could not find local git-repository" << localRepository;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LocalGitRepository::DestroyAllRepositories() {
|
||||||
|
for (auto it = GetLocalGitRepos().keyValueBegin(); it != GetLocalGitRepos().keyValueEnd(); ++it) {
|
||||||
|
QString const &key = it->first;
|
||||||
|
LocalGitRepository *repo = GetLocalGitRepos()[key];
|
||||||
|
delete repo;
|
||||||
|
qCritical() << "deleted local git-repository" << key;
|
||||||
|
}
|
||||||
|
GetLocalGitRepos().clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t LocalGitRepository::GetFileMenuSizeInternal() const {
|
||||||
|
return m_fileMenuSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray LocalGitRepository::GetFileMenuInternal() {
|
||||||
|
if (m_fileMenuSize == -1) {
|
||||||
|
QFile f(QDir::cleanPath(repoRootDirectory + QDir::separator()
|
||||||
|
+ m_localRepository + QDir::separator()
|
||||||
|
+ "etc/psa_webinterface/menu_config.json"));
|
||||||
|
if (f.exists()) {
|
||||||
|
if (f.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||||
|
m_fileMenu = QTextStream(&f).readAll().toUtf8();
|
||||||
|
|
||||||
|
if (m_fileMenu.isValidUtf8()) {
|
||||||
|
QString const &s = QString::fromUtf8(m_fileMenu);
|
||||||
|
m_fileMenuSize = s.toLocal8Bit().size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return m_fileMenu;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray LocalGitRepository::GetFileNameInternal(QString const &fId) {
|
||||||
|
QRegularExpressionMatch match;
|
||||||
|
static const QRegularExpression re("(master|[0-9]+)");
|
||||||
|
if (fId.lastIndexOf(re, -1, &match) != -1) {
|
||||||
|
int idx = fId.indexOf("/");
|
||||||
|
if (idx != -1) {
|
||||||
|
QString path = fId.mid(idx);
|
||||||
|
idx = path.indexOf(":");
|
||||||
|
if (idx != -1) {
|
||||||
|
path = path.mid(0, idx);
|
||||||
|
QString s = match.captured(match.lastCapturedIndex());
|
||||||
|
if (s != "master") {
|
||||||
|
if (fId.contains("psa_tariff")) {
|
||||||
|
QString fn(QDir::cleanPath(
|
||||||
|
repoRootDirectory + QDir::separator() +
|
||||||
|
QString(m_localRepository) + QDir::separator()
|
||||||
|
+ path + QDir::separator()
|
||||||
|
+ QString("tariff%1.json").arg(s.toUInt(), 2, 10, QChar('0'))));
|
||||||
|
return fn.toUtf8();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return QByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray LocalGitRepository::GetFileInternal(QString const &fId) {
|
||||||
|
QByteArray a = GetFileNameInternal(fId);
|
||||||
|
if (a.isValidUtf8()) {
|
||||||
|
QFile fn(a);
|
||||||
|
if (fn.exists()) {
|
||||||
|
if (fn.open(QIODevice::ReadOnly)) {
|
||||||
|
return fn.readAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return QByteArray("{}");
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t LocalGitRepository::GetFileSize(QString const &fId) {
|
||||||
|
QByteArray a = GetFileNameInternal(fId);
|
||||||
|
if (a.isValidUtf8()) {
|
||||||
|
QFile fn(a);
|
||||||
|
if (fn.exists()) {
|
||||||
|
return fn.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LocalGitRepository::SetFileInternal(QString const &fId, QByteArray const &json) {
|
||||||
|
QByteArray a = GetFileNameInternal(fId);
|
||||||
|
if (a.isValidUtf8()) {
|
||||||
|
QFile fn(a);
|
||||||
|
if (fn.exists()) {
|
||||||
|
if (fn.open(QIODevice::WriteOnly)) {
|
||||||
|
qint64 bytesWritten = 0;
|
||||||
|
qint64 bytesToWrite = json.size();
|
||||||
|
while (bytesToWrite > 0 &&
|
||||||
|
(bytesWritten = fn.write(json.constData(), bytesToWrite)) != -1) {
|
||||||
|
bytesToWrite -= bytesWritten;
|
||||||
|
}
|
||||||
|
fn.flush();
|
||||||
|
return (bytesToWrite == 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
58
CalculatorCInterface/local_git_repository.h
Normal file
58
CalculatorCInterface/local_git_repository.h
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
#ifndef LOCAL_GIT_REPOSITORY_H_INCLUDED
|
||||||
|
#define LOCAL_GIT_REPOSITORY_H_INCLUDED
|
||||||
|
|
||||||
|
#include <QByteArray>
|
||||||
|
#include <QString>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QJsonArray>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QDir>
|
||||||
|
#include <QMap>
|
||||||
|
|
||||||
|
#include <git2.h>
|
||||||
|
|
||||||
|
class GitLibrary;
|
||||||
|
class LocalGitRepository {
|
||||||
|
friend class GitLibrary;
|
||||||
|
QString m_localRepository;
|
||||||
|
mutable QByteArray m_fileMenu;
|
||||||
|
mutable int32_t m_fileMenuSize;
|
||||||
|
git_repository *m_git_repository;
|
||||||
|
|
||||||
|
static QString repoRootDirectory;
|
||||||
|
static QMap<QString, LocalGitRepository *> localGitRepos;
|
||||||
|
|
||||||
|
protected: // force heap-based objects
|
||||||
|
LocalGitRepository(QString const &localRepository);
|
||||||
|
~LocalGitRepository();
|
||||||
|
|
||||||
|
public:
|
||||||
|
static void SetReposRootDirectory(QString s);
|
||||||
|
static QString GetReposRootDirectory();
|
||||||
|
|
||||||
|
static LocalGitRepository *GetInstance(QString const &localRepository);
|
||||||
|
static bool DestroyInstance(QString const &localRepository);
|
||||||
|
static void DestroyAllRepositories();
|
||||||
|
|
||||||
|
static QMap<QString, LocalGitRepository *> &GetLocalGitRepos();
|
||||||
|
|
||||||
|
QString localRepositoryName() const;
|
||||||
|
QString localRepositoryPath() const;
|
||||||
|
|
||||||
|
void SetGitRepository(git_repository *git_repo);
|
||||||
|
git_repository const *GetGitRepository() const;
|
||||||
|
git_repository *GetGitRepository();
|
||||||
|
|
||||||
|
static QString localRepositoryPath(QString const &localRepository);
|
||||||
|
|
||||||
|
QByteArray GetFileMenuInternal();
|
||||||
|
int32_t GetFileMenuSizeInternal() const;
|
||||||
|
|
||||||
|
QByteArray GetFileNameInternal(QString const &fileId);
|
||||||
|
int32_t GetFileSize(QString const &fileId);
|
||||||
|
QByteArray GetFileInternal(QString const &fileId);
|
||||||
|
|
||||||
|
bool SetFileInternal(QString const &fileId, QByteArray const &json);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // LOCAL_GIT_REPOSITORY_H_INCLUDED
|
Reference in New Issue
Block a user