diff --git a/CalculatorCInterface/calculator_c_interface_lib.cpp b/CalculatorCInterface/calculator_c_interface_lib.cpp index 717a637..2f7a882 100644 --- a/CalculatorCInterface/calculator_c_interface_lib.cpp +++ b/CalculatorCInterface/calculator_c_interface_lib.cpp @@ -41,6 +41,31 @@ typedef struct { unsigned int perf : 1; } checkout_options; + +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) { @@ -333,26 +358,127 @@ int CheckoutLocalBranch(char const *local_path, char const *branch_name) { return err; } -int CommitFile(char const *local_path, char const *file_name) { +int CommitFile(char const *local_path, char const *branch_name, + char const *file_name, char const *comment) { 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(path); - if (!localPath.exists()) { + QString localPath(local_path); + if (!QDir(localPath).exists()) { fprintf(stderr, "local path %s for file %s does not exist\n", - localRepoPath.toUtf8().constData(), file_name); + localPath.toUtf8().constData(), file_name); + QDir::setCurrent(currentWD); return -1; } - if (QDir::setCurrent(localPath)) { + if (!QDir::setCurrent(localPath)) { + fprintf(stderr, "can not set cwd path %s\n", localPath.toUtf8().constData()); + QDir::setCurrent(currentWD); + return -1; + } + fprintf(stderr, "cwd %s\n", QDir::current().absolutePath().toUtf8().constData()); + + git_repository *repo = NULL; + int error = 0; + + 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); + } + } + + 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 0; + return error; } #ifdef __cplusplus diff --git a/CalculatorCInterface/calculator_c_interface_lib.h b/CalculatorCInterface/calculator_c_interface_lib.h index 8f56c73..c565b77 100644 --- a/CalculatorCInterface/calculator_c_interface_lib.h +++ b/CalculatorCInterface/calculator_c_interface_lib.h @@ -18,7 +18,7 @@ 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 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) 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; #ifdef __cplusplus }