diff --git a/CalculatorCInterface/calculator_c_interface_lib.cpp b/CalculatorCInterface/calculator_c_interface_lib.cpp index 2f7a882..4708e9e 100644 --- a/CalculatorCInterface/calculator_c_interface_lib.cpp +++ b/CalculatorCInterface/calculator_c_interface_lib.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include @@ -12,6 +13,9 @@ #include static QMap customerRepoMap; +static std::mutex m; +static char const *user = NULL; +static char const *pass = NULL; #ifndef _WIN32 # include @@ -41,6 +45,29 @@ typedef struct { 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; @@ -481,6 +508,89 @@ int CommitFile(char const *local_path, char const *branch_name, 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 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; +} + + + #ifdef __cplusplus } #endif diff --git a/CalculatorCInterface/calculator_c_interface_lib.h b/CalculatorCInterface/calculator_c_interface_lib.h index c565b77..5df2734 100644 --- a/CalculatorCInterface/calculator_c_interface_lib.h +++ b/CalculatorCInterface/calculator_c_interface_lib.h @@ -19,6 +19,7 @@ int ShutdownGitLibrary(void) CALCULATOR_C_INTERFACE_LIB_EXPORT; int CloneRepository(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; #ifdef __cplusplus }