StagedFiles PmrWorkspace::stagedFiles() { // Retrieve and return all current staged files StagedFiles res = StagedFiles(); git_index *index; if (git_repository_index(&index, mGitRepository) == GIT_OK) { git_status_options statusOptions; git_status_init_options(&statusOptions, GIT_STATUS_OPTIONS_VERSION); statusOptions.flags = GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX |GIT_STATUS_OPT_SORT_CASE_INSENSITIVELY; statusOptions.show = GIT_STATUS_SHOW_INDEX_ONLY; git_status_list *statusList; if (git_status_list_new(&statusList, mGitRepository, &statusOptions) == GIT_OK) { for (size_t i = 0, iMax = git_status_list_entrycount(statusList); i < iMax; ++i) { const git_status_entry *status = git_status_byindex(statusList, i); const char *filePath = (status->head_to_index != nullptr)? status->head_to_index->old_file.path: (status->index_to_workdir != nullptr)? status->index_to_workdir->old_file.path: nullptr; if (filePath != nullptr) { if ((status->status & GIT_STATUS_INDEX_TYPECHANGE) != 0) { res << StagedFile(filePath, GIT_STATUS_INDEX_TYPECHANGE); } else if ((status->status & GIT_STATUS_INDEX_RENAMED) != 0) { res << StagedFile(filePath, GIT_STATUS_INDEX_RENAMED); } else if ((status->status & GIT_STATUS_INDEX_DELETED) != 0) { res << StagedFile(filePath, GIT_STATUS_INDEX_DELETED); } else if ((status->status & GIT_STATUS_INDEX_MODIFIED) != 0) { res << StagedFile(filePath, GIT_STATUS_INDEX_MODIFIED); } else if ((status->status & GIT_STATUS_INDEX_NEW) != 0) { res << StagedFile(filePath, GIT_STATUS_INDEX_NEW); } } } git_status_list_free(statusList); } git_index_free(index); } return res; }
emacs_value egit_status_foreach(emacs_env *env, emacs_value _repo, emacs_value function, emacs_value show, emacs_value flags, emacs_value pathspec, emacs_value baseline) { EGIT_ASSERT_REPOSITORY(_repo); EM_ASSERT_FUNCTION(function); git_status_options options; git_status_init_options(&options, GIT_STATUS_OPTIONS_VERSION); if (!convert_show_option(&options.show, env, show)) { return em_nil; } if (!convert_flags_option(&options.flags, env, flags)) { return em_nil; } if (!egit_strarray_from_list(&options.pathspec, env, pathspec)) { return em_nil; } if (!convert_baseline_option(&options.baseline, env, baseline)) { egit_strarray_dispose(&options.pathspec); return em_nil; } git_repository *repo = EGIT_EXTRACT(_repo); egit_generic_payload ctx = {.env = env, .func = function}; int rv = git_status_foreach_ext(repo, &options, &foreach_callback, (void *)(&ctx)); egit_strarray_dispose(&options.pathspec); if (rv != GIT_EUSER) { EGIT_CHECK_ERROR(rv); } return em_nil; }
void CGitStatus::Load() { GitStatus status; CriticalSection lock(this->m_critSec); status = this->GetStatus(); if (status == GS_NOTLOADED || status == GS_INVALIDATED) { this->m_waitHandle = CreateEvent(NULL, TRUE, FALSE, NULL); SetStatus(GS_LOADING); } lock.Unlock(); if (status == GS_LOADED || status == GS_ERROR) { return; } // If it is loading just wait for it to complete. if (status == GS_LOADING) { _ASSERT(this->m_waitHandle.IsValid()); WaitForSingleObject(this->m_waitHandle, INFINITE); return; } git_buf buf; git_repository *repo = NULL; wstring_convert<codecvt_utf8<wchar_t>> converter; InitState(); if (!GetRepoRootInternal(this->m_startDir, this->m_repoRoot, buf, repo)) { Logger::LogWarning(_T("Unable to open git repository")); SetStatus(GS_ERROR); ::SetEvent(this->m_waitHandle); return; } // This is temporary. CMutexLock mutexLock(&m_mutex); this->m_gitDir = MyUtils::NormalizePath(converter.from_bytes(buf.ptr)); // Get current state of repo. (merge/rebase in progress etc) this->m_repoState = git_repository_state(repo); // Get branch info. git_reference *ref; if (git_repository_head(&ref, repo)) { Logger::LogError(_T("Unable to retrieve branch")); SetStatus(GS_ERROR); ::SetEvent(this->m_waitHandle); return; } const char* headName = git_reference_shorthand(ref); this->m_branch = converter.from_bytes(headName); // Get the status of the repo. git_status_options opts; git_status_init_options(&opts, GIT_STATUS_OPTIONS_VERSION); opts.flags = GIT_STATUS_OPT_INCLUDE_UNTRACKED | GIT_STATUS_OPT_EXCLUDE_SUBMODULES; git_status_foreach_ext(repo, &opts, &GitStatus_Callack, this); // Free stuff git_buf_free(&buf); git_repository_free(repo); this->SetStatus(GS_LOADED); ::SetEvent(this->m_waitHandle); // Start monitoring for changes. this->MonitorForChanges(); return; }
void PmrWorkspace::refreshStatus() { // Keep track of our 'old' file nodes PmrWorkspaceFileNodes oldFileNodes = mRepositoryStatusMap.values(); // Refresh our status mStagedCount = 0; mUnstagedCount = 0; mRepositoryStatusMap.clear(); if (isOpen()) { git_status_options statusOptions; git_status_init_options(&statusOptions, GIT_STATUS_OPTIONS_VERSION); statusOptions.flags = GIT_STATUS_OPT_INCLUDE_UNTRACKED |GIT_STATUS_OPT_INCLUDE_UNMODIFIED |GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX |GIT_STATUS_OPT_SORT_CASE_INSENSITIVELY |GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS; statusOptions.show = GIT_STATUS_SHOW_INDEX_AND_WORKDIR; git_status_list *statusList; if (git_status_list_new(&statusList, mGitRepository, &statusOptions) == GIT_OK) { // Go through the different entries and keep track of every single // one of them in mRepositoryStatusMap, as well as update // mStagedCount and mUnstagedCount, if needed for (size_t i = 0, iMax = git_status_list_entrycount(statusList); i < iMax; ++i) { const git_status_entry *status = git_status_byindex(statusList, i); const char *filePath = (status->head_to_index != nullptr)? status->head_to_index->old_file.path: (status->index_to_workdir != nullptr)? status->index_to_workdir->old_file.path: nullptr; if (filePath != nullptr) { CharPair statusChars = gitStatusChars(status->status); if (statusChars.first != ' ') { ++mStagedCount; } if (statusChars.second != ' ') { ++mUnstagedCount; } mRepositoryStatusMap.insert(filePath, parentFileNode(filePath)->addChild(QFileInfo(filePath).fileName(), statusChars)); } } git_status_list_free(statusList); } // Delete any 'old' file node that is not being used anymore PmrWorkspaceFileNodes newFileNodes = mRepositoryStatusMap.values(); PmrWorkspaceFileNodes oldFileNodesToDelete = PmrWorkspaceFileNodes(); for (auto oldFileNode : oldFileNodes) { if (!newFileNodes.contains(oldFileNode)) { oldFileNodesToDelete << oldFileNode; } } if (!oldFileNodesToDelete.isEmpty()) { deleteFileNodes(mRootFileNode, oldFileNodesToDelete); } } else if (mRootFileNode->hasChildren()) { // We are not open, so clear our root file node for (auto child : mRootFileNode->children()) { delete child; } } }
static gboolean submain (struct EvTag *self, int argc, char **argv, GError **error) { gboolean ret = FALSE; git_status_options statusopts = GIT_STATUS_OPTIONS_INIT; GCancellable *cancellable = NULL; const char *command_name = NULL; Subcommand *command; char *prgname = NULL; int in, out; int r; /* * Parse the global options. We rearrange the options as * necessary, in order to pass relevant options through * to the commands, but also have them take effect globally. */ for (in = 1, out = 1; in < argc; in++, out++) { /* The non-option is the command, take it out of the arguments */ if (argv[in][0] != '-') { if (command_name == NULL) { command_name = argv[in]; out--; continue; } } else if (g_str_equal (argv[in], "--")) { break; } argv[out] = argv[in]; } argc = out; command = commands; while (command->name) { if (g_strcmp0 (command_name, command->name) == 0) break; command++; } if (!command->fn) { GOptionContext *context; char *help; context = option_context_new_with_commands (commands); /* This will not return for some options (e.g. --version). */ if (option_context_parse (context, NULL, &argc, &argv, cancellable, error)) { if (command_name == NULL) { g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, "No command specified"); } else { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Unknown command '%s'", command_name); } } help = g_option_context_get_help (context, FALSE, NULL); g_printerr ("%s", help); g_option_context_free (context); goto out; } prgname = g_strdup_printf ("%s %s", g_get_prgname (), command_name); g_set_prgname (prgname); r = git_repository_open_ext (&self->top_repo, ".", 0, NULL); if (!handle_libgit_ret (r, error)) goto out; r = git_status_init_options (&statusopts, GIT_STATUS_OPTIONS_VERSION); if (!handle_libgit_ret (r, error)) goto out; { struct TreeWalkData twdata = { FALSE, self, self->top_repo, NULL, cancellable, error }; r = git_status_foreach_ext (self->top_repo, &statusopts, status_cb, &twdata); if (twdata.caught_error) goto out; if (!handle_libgit_ret (r, error)) goto out; } self->checksum = g_checksum_new (G_CHECKSUM_SHA512); if (!command->fn (self, argc, argv, cancellable, error)) goto out; ret = TRUE; out: return ret; }