diff --git a/CalculatorCInterface/CalculatorCInterface.pro b/CalculatorCInterface/CalculatorCInterface.pro index d697ba8..e5ffaec 100644 --- a/CalculatorCInterface/CalculatorCInterface.pro +++ b/CalculatorCInterface/CalculatorCInterface.pro @@ -28,12 +28,14 @@ CONFIG += c++20 console SOURCES += \ calculator_c_interface_lib.cpp \ + git_library.cpp \ tariff_calculator.cpp \ local_git_repository.cpp HEADERS += \ calculator_c_interface_lib.h \ calculator_c_interface_lib_global.h \ + git_library.h \ tariff_calculator.h \ local_git_repository.h diff --git a/CalculatorCInterface/calculator_c_interface_lib.cpp b/CalculatorCInterface/calculator_c_interface_lib.cpp index 5ffbeb3..f79f7b6 100644 --- a/CalculatorCInterface/calculator_c_interface_lib.cpp +++ b/CalculatorCInterface/calculator_c_interface_lib.cpp @@ -1,4 +1,6 @@ #include "calculator_c_interface_lib.h" +#include "local_git_repository.h" +#include "git_library.h" //#include @@ -275,51 +277,17 @@ void DeleteTariffCalculator(TariffCalculatorHandle handle) { delete handle; } -int InitGitLibrary(void) { - return git_libgit2_init(); +int InitGitLibraryInternal(void) { + return GitLibrary::Init(); } -int ShutdownGitLibrary(void) { - - for (auto key : customerRepoMap.keys()) { - git_repository_free(customerRepoMap.value(key)); - } - customerRepoMap.clear(); - return git_libgit2_shutdown(); +int ShutdownGitLibraryInternal(void) { + LocalGitRepository::DestroyAllRepositories(); + return GitLibrary::Shutdown(); } -int CloneRepository(char const *url, char const *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; - git_clone_options opts; - 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 CloneRepositoryInternal(char const *url, char const *local_path) { + return GitLibrary::CloneRepository(url, local_path); } int CheckoutLocalBranch(char const *local_path, char const *branch_name) { @@ -596,38 +564,25 @@ int PushLocalRepository(char const *local_path, char const *branch_name, char co #include -static QMap localGitRepos; void SetReposRootDirectoryInternal(char const *p) { LocalGitRepository::SetReposRootDirectory(QString::fromUtf8(p)); } char const *GetReposRootDirectoryInternal() { - return LocalGitRepository::GetReposRootDirectory().toUtf8().constData(); + return (char const *)LocalGitRepository::GetReposRootDirectory().constData(); } char const *GetLocalRepositoryPathInternal(char const *localGitRepo) { - if (localGitRepos.count(localGitRepo) == 0) { - localGitRepos.insert(localGitRepo, - new LocalGitRepository(localGitRepo)); - } - return localGitRepos[localGitRepo]->localRepositoryPath().toUtf8().constData(); + return (char const *)LocalGitRepository::GetInstance(localGitRepo)->localRepositoryPath().constData(); } int32_t GetFileMenuSizeInternal(char const *localGitRepo) { - if (localGitRepos.count(localGitRepo) == 0) { - localGitRepos.insert(localGitRepo, - new LocalGitRepository(localGitRepo)); - } - return localGitRepos[localGitRepo]->GetFileMenuSizeInternal(); + return LocalGitRepository::GetInstance(localGitRepo)->GetFileMenuSizeInternal(); } char const *GetFileMenuInternal(const char *localGitRepo) { - if (localGitRepos.count(localGitRepo) == 0) { - localGitRepos.insert(localGitRepo, - new LocalGitRepository(localGitRepo)); - } - QByteArray const &a = localGitRepos[localGitRepo]->GetFileMenuInternal().constData(); + QByteArray const &a = LocalGitRepository::GetInstance(localGitRepo)->GetFileMenuInternal().constData(); if (a.isValidUtf8()) { int const len = GetFileMenuSizeInternal(localGitRepo); if (len > 0) { @@ -643,11 +598,7 @@ char const *GetFileMenuInternal(const char *localGitRepo) { char const *GetFileNameInternal(char const *localGitRepo, char const *fileId) { - if (localGitRepos.count(localGitRepo) == 0) { - localGitRepos.insert(localGitRepo, - new LocalGitRepository(localGitRepo)); - } - QByteArray const &a = localGitRepos[localGitRepo]->GetFileNameInternal(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); @@ -658,19 +609,11 @@ char const *GetFileNameInternal(char const *localGitRepo, char const *fileId) { } int32_t GetFileSize(char const *localGitRepo, char const *fileId) { - if (localGitRepos.count(localGitRepo) == 0) { - localGitRepos.insert(localGitRepo, - new LocalGitRepository(localGitRepo)); - } - return localGitRepos[localGitRepo]->GetFileSize(fileId); + return LocalGitRepository::GetInstance(localGitRepo)->GetFileSize(fileId); } char const *GetFileInternal(char const *localGitRepo, char const *fileId) { - if (localGitRepos.count(localGitRepo) == 0) { - localGitRepos.insert(localGitRepo, - new LocalGitRepository(localGitRepo)); - } - QByteArray const &a = localGitRepos[localGitRepo]->GetFileInternal(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); @@ -681,11 +624,7 @@ char const *GetFileInternal(char const *localGitRepo, char const *fileId) { } bool SetFileInternal(char const *localGitRepo, char const *fileId, char const *json, int size) { - if (localGitRepos.count(localGitRepo) == 0) { - localGitRepos.insert(localGitRepo, - new LocalGitRepository(localGitRepo)); - } - return localGitRepos[localGitRepo]->SetFileInternal(QString(fileId), QByteArray(json, size)); + return LocalGitRepository::GetInstance(localGitRepo)->SetFileInternal(QString(fileId), QByteArray(json, size)); } void DeleteMem(char *p) { diff --git a/CalculatorCInterface/calculator_c_interface_lib.h b/CalculatorCInterface/calculator_c_interface_lib.h index 404ccc5..2c58df6 100644 --- a/CalculatorCInterface/calculator_c_interface_lib.h +++ b/CalculatorCInterface/calculator_c_interface_lib.h @@ -27,9 +27,9 @@ TariffCalculatorHandle NewTariffCalculator(void) CALCULATOR_C_INTERFACE_LIB_EXPO void DeleteTariffCalculator(TariffCalculatorHandle handle) CALCULATOR_C_INTERFACE_LIB_EXPORT; // libgit2 -int InitGitLibrary(void) CALCULATOR_C_INTERFACE_LIB_EXPORT; -int ShutdownGitLibrary(void) CALCULATOR_C_INTERFACE_LIB_EXPORT; -int CloneRepository(char const *url, char const *local_path) CALCULATOR_C_INTERFACE_LIB_EXPORT; +int InitGitLibraryInternal(void) CALCULATOR_C_INTERFACE_LIB_EXPORT; +int ShutdownGitLibraryInternal(void) 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 CommitFile(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; diff --git a/CalculatorCInterface/git_library.cpp b/CalculatorCInterface/git_library.cpp new file mode 100644 index 0000000..f5bba66 --- /dev/null +++ b/CalculatorCInterface/git_library.cpp @@ -0,0 +1,93 @@ +#include "git_library.h" +#include "local_git_repository.h" + +#include +#include + +#include + +int GitLibrary::Init() { + return git_libgit2_init(); +} + +int GitLibrary::Shutdown() { + return git_libgit2_shutdown(); +} + +int GitLibrary::CheckoutRepository(char const *localRepoName, char const *branchName) { + QString localRepo(localRepoName); + QDir localRepoDir; + + if (strstr(localRepoName, "customer_") == localRepoName) { // localRepoPath starts with 'customer_' + QString const &p = QDir::cleanPath(LocalGitRepository::GetReposRootDirectory() + + QDir::separator() + localRepoName); + localRepoDir.setPath(p); + } else { + qCritical() << __func__ << ":" << __LINE__ + << "localRepoPath" << localRepoDir.path() << "either not absolute" + << "or not starting with customer_*"; + return -1; + } +} + +int GitLibrary::CloneRepository(char const *url, char const *localRepoPath /* absolute path or repo-name */) { + QString localRepoName; + QDir localRepoDir; + + if (strstr(localRepoPath, "customer_") == localRepoPath) { // localRepoPath starts with 'customer_' + QString const &p = QDir::cleanPath(LocalGitRepository::GetReposRootDirectory() + + QDir::separator() + localRepoPath); + localRepoDir.setPath(p); + localRepoName = localRepoPath; + } else if (QDir::isAbsolutePath(localRepoPath) && + strstr(localRepoPath, "/customer_") != localRepoPath) { + localRepoDir.setPath(localRepoPath); + localRepoName = localRepoDir.dirName(); // extract e.g. customer_999 + } else { + qCritical() << __func__ << ":" << __LINE__ + << "localRepoPath" << localRepoPath << "either not absolute" + << "or not starting with customer_*"; + return -1; + } + + if (!QDir(localRepoDir).exists()) { + if (!QDir().mkpath(localRepoDir.absolutePath())) { + qCritical() << __func__ << ":" << __LINE__ + << "can not create git-repositories-root-dir" << localRepoDir; + return -1; + } + } + + QDir gitDir(QDir::cleanPath(localRepoDir.absolutePath() + QDir::separator() + ".git")); + + if (gitDir.exists()) { + qCritical() << __func__ << ":" << __LINE__ + << "local repository" << gitDir.path() << "already exists," + << "no clone necessary"; + return -1; + } + + int res = 0; + QDir const ¤t = QDir::current(); + + git_clone_options opts; + if ((res = git_clone_options_init(&opts, GIT_CLONE_OPTIONS_VERSION)) == 0) { + opts.checkout_branch = "master"; + if (QDir::setCurrent(localRepoDir.absolutePath())) { + git_repository *out = LocalGitRepository::GetInstance(localRepoName)->GetGitRepository(); + if ((res = git_clone(&out, url, ".", &opts)) < 0) { + git_error const *error = git_error_last(); + qCritical() << __func__ << ":" << __LINE__ << error->message << localRepoDir.absolutePath(); + } + QDir::setCurrent(current.absolutePath()); + } else { + qCritical() << __func__ << ":" << __LINE__ + << "ERROR setCurrent" << localRepoDir.absolutePath(); + res = -1; + } + } else { + git_error const *error = git_error_last(); + qCritical() << __func__ << ":" << __LINE__ << error->message; + } + return res; +} diff --git a/CalculatorCInterface/git_library.h b/CalculatorCInterface/git_library.h new file mode 100644 index 0000000..003ef8a --- /dev/null +++ b/CalculatorCInterface/git_library.h @@ -0,0 +1,24 @@ +#ifndef GIT_LIBRARY_H_INCLUDED +#define GIT_LIBRARY_H_INCLUDED + +#include +#include +#include +#include +#include +#include +#include + +class GitLibrary { +public: + static int Init(); + static int Shutdown(); + static int CloneRepository(char const *url, char const *localRepoName); + static int CheckoutRepository(char const *localRepoName, char const *branchName); + + + // explicit GitLibrary(); + // ~GitLibrary(); +}; + +#endif // #define GIT_LIBRARY_H_INCLUDED diff --git a/CalculatorCInterface/local_git_repository.cpp b/CalculatorCInterface/local_git_repository.cpp index 8f6a3e4..ea0a5c0 100644 --- a/CalculatorCInterface/local_git_repository.cpp +++ b/CalculatorCInterface/local_git_repository.cpp @@ -1,5 +1,7 @@ #include "local_git_repository.h" +#include "git_library.h" +#include #include #include #include @@ -10,20 +12,107 @@ #include -QString LocalGitRepository::m_repoRootDirectory = "H:\\"; +QString LocalGitRepository::repoRootDirectory = ""; +QMap LocalGitRepository::localGitRepos; + +QMap &LocalGitRepository::GetLocalGitRepos() { + return localGitRepos; +} void LocalGitRepository::SetReposRootDirectory(QString s) { - m_repoRootDirectory = s; + if (repoRootDirectory.isEmpty()) { + repoRootDirectory = s; + return; + } + qCritical() << __func__ << ":" << __LINE__ + << "ERROR git-repository-root-directory already set" + << repoRootDirectory; } QString LocalGitRepository::GetReposRootDirectory() { - return m_repoRootDirectory; + return repoRootDirectory; } LocalGitRepository::LocalGitRepository(QString const &localRepository) : m_localRepository(localRepository) , m_fileMenu("{}") - , m_fileMenuSize(-1) { + , 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 { @@ -32,7 +121,7 @@ int32_t LocalGitRepository::GetFileMenuSizeInternal() const { QByteArray LocalGitRepository::GetFileMenuInternal() { if (m_fileMenuSize == -1) { - QFile f(QDir::cleanPath(m_repoRootDirectory + QDir::separator() + QFile f(QDir::cleanPath(repoRootDirectory + QDir::separator() + m_localRepository + QDir::separator() + "etc/psa_webinterface/menu_config.json")); if (f.exists()) { @@ -63,7 +152,7 @@ QByteArray LocalGitRepository::GetFileNameInternal(QString const &fId) { if (s != "master") { if (fId.contains("psa_tariff")) { QString fn(QDir::cleanPath( - m_repoRootDirectory + QDir::separator() + + repoRootDirectory + QDir::separator() + QString(m_localRepository) + QDir::separator() + path + QDir::separator() + QString("tariff%1.json").arg(s.toUInt(), 2, 10, QChar('0')))); diff --git a/CalculatorCInterface/local_git_repository.h b/CalculatorCInterface/local_git_repository.h index 2211ccd..1b6f3c1 100644 --- a/CalculatorCInterface/local_git_repository.h +++ b/CalculatorCInterface/local_git_repository.h @@ -7,25 +7,43 @@ #include #include #include +#include +#include + +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 localGitRepos; + +protected: // force heap-based objects + LocalGitRepository(QString const &localRepository); + ~LocalGitRepository(); - static QString m_repoRootDirectory; public: static void SetReposRootDirectory(QString s); static QString GetReposRootDirectory(); - LocalGitRepository(QString const &localRepository); + static LocalGitRepository *GetInstance(QString const &localRepository); + static bool DestroyInstance(QString const &localRepository); + static void DestroyAllRepositories(); - QString localRepository() const { return m_localRepository; } + static QMap &GetLocalGitRepos(); - QString localRepositoryPath() { - return QDir::cleanPath( - m_repoRootDirectory + QDir::separator() + m_localRepository); - } + 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;