summaryrefslogtreecommitdiff
path: root/src/git.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/git.cc')
-rw-r--r--src/git.cc242
1 files changed, 0 insertions, 242 deletions
diff --git a/src/git.cc b/src/git.cc
deleted file mode 100644
index 029b02bf..00000000
--- a/src/git.cc
+++ /dev/null
@@ -1,242 +0,0 @@
-// Copyright 2019 Roman Perepelitsa.
-//
-// This file is part of GitStatus.
-//
-// GitStatus is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// GitStatus is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with GitStatus. If not, see <https://www.gnu.org/licenses/>.
-
-#include "git.h"
-
-#include <cstdlib>
-#include <cstring>
-#include <fstream>
-#include <sstream>
-#include <utility>
-
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include "arena.h"
-#include "check.h"
-#include "print.h"
-#include "scope_guard.h"
-
-namespace gitstatus {
-
-const char* GitError() {
- const git_error* err = git_error_last();
- return err && err->message ? err->message : "unknown error";
-}
-
-std::string RepoState(git_repository* repo) {
- Arena arena;
- StringView gitdir(git_repository_path(repo));
-
- // These names mostly match gitaction in vcs_info:
- // https://github.com/zsh-users/zsh/blob/master/Functions/VCS_Info/Backends/VCS_INFO_get_data_git.
- auto State = [&]() {
- switch (git_repository_state(repo)) {
- case GIT_REPOSITORY_STATE_NONE:
- return "";
- case GIT_REPOSITORY_STATE_MERGE:
- return "merge";
- case GIT_REPOSITORY_STATE_REVERT:
- return "revert";
- case GIT_REPOSITORY_STATE_REVERT_SEQUENCE:
- return "revert-seq";
- case GIT_REPOSITORY_STATE_CHERRYPICK:
- return "cherry";
- case GIT_REPOSITORY_STATE_CHERRYPICK_SEQUENCE:
- return "cherry-seq";
- case GIT_REPOSITORY_STATE_BISECT:
- return "bisect";
- case GIT_REPOSITORY_STATE_REBASE:
- return "rebase";
- case GIT_REPOSITORY_STATE_REBASE_INTERACTIVE:
- return "rebase-i";
- case GIT_REPOSITORY_STATE_REBASE_MERGE:
- return "rebase-m";
- case GIT_REPOSITORY_STATE_APPLY_MAILBOX:
- return "am";
- case GIT_REPOSITORY_STATE_APPLY_MAILBOX_OR_REBASE:
- return "am/rebase";
- }
- return "action";
- };
-
- auto DirExists = [&](StringView name) {
- int fd = open(arena.StrCat(gitdir, "/", name), O_DIRECTORY | O_CLOEXEC);
- if (fd < 0) return false;
- CHECK(!close(fd)) << Errno();
- return true;
- };
-
- auto ReadFile = [&](StringView name) {
- std::ifstream strm(arena.StrCat(gitdir, "/", name));
- std::string res;
- strm >> res;
- return res;
- };
-
- std::string next;
- std::string last;
-
- if (DirExists("rebase-merge")) {
- next = ReadFile("rebase-merge/msgnum");
- last = ReadFile("rebase-merge/end");
- } else if (DirExists("rebase-apply")) {
- next = ReadFile("rebase-apply/next");
- last = ReadFile("rebase-apply/last");
- }
-
- std::ostringstream res;
- res << State();
- if (!next.empty() && !last.empty()) res << ' ' << next << '/' << last;
- return res.str();
-}
-
-size_t CountRange(git_repository* repo, const std::string& range) {
- git_revwalk* walk = nullptr;
- VERIFY(!git_revwalk_new(&walk, repo)) << GitError();
- ON_SCOPE_EXIT(=) { git_revwalk_free(walk); };
- VERIFY(!git_revwalk_push_range(walk, range.c_str())) << GitError();
- size_t res = 0;
- while (true) {
- git_oid oid;
- switch (git_revwalk_next(&oid, walk)) {
- case 0:
- ++res;
- break;
- case GIT_ITEROVER:
- return res;
- default:
- LOG(ERROR) << "git_revwalk_next: " << range << ": " << GitError();
- throw Exception();
- }
- }
-}
-
-size_t NumStashes(git_repository* repo) {
- size_t res = 0;
- auto* cb = +[](size_t index, const char* message, const git_oid* stash_id, void* payload) {
- ++*static_cast<size_t*>(payload);
- return 0;
- };
- if (!git_stash_foreach(repo, cb, &res)) return res;
- // Example error: failed to parse signature - malformed e-mail.
- // See https://github.com/romkatv/powerlevel10k/issues/216.
- LOG(WARN) << "git_stash_foreach: " << GitError();
- return 0;
-}
-
-git_reference* Head(git_repository* repo) {
- git_reference* symbolic = nullptr;
- switch (git_reference_lookup(&symbolic, repo, "HEAD")) {
- case 0:
- break;
- case GIT_ENOTFOUND:
- return nullptr;
- default:
- LOG(ERROR) << "git_reference_lookup: " << GitError();
- throw Exception();
- }
-
- git_reference* direct = nullptr;
- if (git_reference_resolve(&direct, symbolic)) {
- LOG(INFO) << "Empty git repo (no HEAD)";
- return symbolic;
- }
- git_reference_free(symbolic);
- return direct;
-}
-
-const char* LocalBranchName(const git_reference* ref) {
- CHECK(ref);
- git_reference_t type = git_reference_type(ref);
- switch (type) {
- case GIT_REFERENCE_DIRECT: {
- return git_reference_is_branch(ref) ? git_reference_shorthand(ref) : "";
- }
- case GIT_REFERENCE_SYMBOLIC: {
- static constexpr char kHeadPrefix[] = "refs/heads/";
- const char* target = git_reference_symbolic_target(ref);
- if (!target) return "";
- size_t len = std::strlen(target);
- if (len < sizeof(kHeadPrefix)) return "";
- if (std::memcmp(target, kHeadPrefix, sizeof(kHeadPrefix) - 1)) return "";
- return target + (sizeof(kHeadPrefix) - 1);
- }
- case GIT_REFERENCE_INVALID:
- case GIT_REFERENCE_ALL:
- break;
- }
- LOG(ERROR) << "Invalid reference type: " << type;
- throw Exception();
-}
-
-RemotePtr GetRemote(git_repository* repo, const git_reference* local) {
- git_remote* remote;
- git_buf symref = {};
- if (git_branch_remote(&remote, &symref, repo, git_reference_name(local))) return nullptr;
- ON_SCOPE_EXIT(&) {
- git_remote_free(remote);
- git_buf_free(&symref);
- };
-
- git_reference* ref;
- if (git_reference_lookup(&ref, repo, symref.ptr)) return nullptr;
- ON_SCOPE_EXIT(&) { if (ref) git_reference_free(ref); };
-
- const char* branch = nullptr;
- std::string name = remote ? git_remote_name(remote) : ".";
- if (git_branch_name(&branch, ref)) {
- branch = "";
- } else if (remote) {
- VERIFY(std::strstr(branch, name.c_str()) == branch);
- VERIFY(branch[name.size()] == '/');
- branch += name.size() + 1;
- }
-
- auto res = std::make_unique<Remote>();
- res->name = std::move(name);
- res->branch = branch;
- res->url = remote ? (git_remote_url(remote) ?: "") : "";
- res->ref = std::exchange(ref, nullptr);
- return RemotePtr(res.release());
-}
-
-PushRemotePtr GetPushRemote(git_repository* repo, const git_reference* local) {
- git_remote* remote;
- git_buf symref = {};
- if (git_branch_push_remote(&remote, &symref, repo, git_reference_name(local))) return nullptr;
- ON_SCOPE_EXIT(&) {
- git_remote_free(remote);
- git_buf_free(&symref);
- };
-
- git_reference* ref;
- if (git_reference_lookup(&ref, repo, symref.ptr)) return nullptr;
- ON_SCOPE_EXIT(&) { if (ref) git_reference_free(ref); };
-
- std::string name = remote ? git_remote_name(remote) : ".";
-
- auto res = std::make_unique<PushRemote>();
- res->name = std::move(name);
- res->url = remote ? (git_remote_url(remote) ?: "") : "";
- res->ref = std::exchange(ref, nullptr);
- return PushRemotePtr(res.release());
-}
-
-} // namespace gitstatus