Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Git prompt using libgit2 (again) #55

Merged
merged 36 commits into from
Oct 30, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
ca7da17
Added simple Git repository parsing code
tfpf Oct 26, 2024
4b0f479
Workflow: install libgit2 on Linux
tfpf Oct 26, 2024
6e2bf9d
Merge and rebase status
tfpf Oct 26, 2024
1d513ec
Cherry-picking and reverting statuses
tfpf Oct 26, 2024
8aabb90
Reverted workflow change
tfpf Oct 26, 2024
40c3a21
Bisecting status
tfpf Oct 26, 2024
b26338a
Full handling of (unborn) branch name, commit ID and tag
tfpf Oct 27, 2024
0ce33f4
No need to check if reference is branch
tfpf Oct 27, 2024
3cf7081
Status listing with callback
tfpf Oct 27, 2024
2c79469
Moved callback function explanation to declaration
tfpf Oct 27, 2024
7078293
Replaced state `bool`s with single `std::string`
tfpf Oct 28, 2024
0329967
Added `bare` member
tfpf Oct 28, 2024
779c8e2
Renamed `set_*` methods as `establish_*` because they are not setters
tfpf Oct 28, 2024
9b024ce
Skip ignored files in status detection
tfpf Oct 28, 2024
d34b6e4
Completed status detection code
tfpf Oct 28, 2024
1b14bf9
Use git information from libgit2 instead of `__git_ps1`
tfpf Oct 28, 2024
74ec24c
Updated Bash and Zsh to not pass `__git_ps1` output
tfpf Oct 28, 2024
29aa066
Initialise all primitive members
tfpf Oct 28, 2024
5da796e
Fixed edge case: a file can be new and modified both
tfpf Oct 28, 2024
4cdf16e
Removed static linking on Windows
tfpf Oct 28, 2024
9e84074
Renames and minor fixes
tfpf Oct 28, 2024
4fcd5a7
Moved tag detection to separate method
tfpf Oct 29, 2024
440574f
Detect annotated and unannotated tags both
tfpf Oct 29, 2024
7ee0bc5
Bit-fiddling to set dirty, staged and untracked statuses
tfpf Oct 29, 2024
11a0a93
Removed parameter names from method declarations
tfpf Oct 29, 2024
8197bf6
Merged with `main`
tfpf Oct 29, 2024
c1bd247
Updated documentation
tfpf Oct 30, 2024
32b417b
Merge branch 'libgit2-git-ps1-impl' of https://github.com/tfpf/dotfil…
tfpf Oct 30, 2024
82fd168
Added Windows workflow to build libgit2 statically
tfpf Oct 30, 2024
e6a4325
Use Git instead of GitHub CLI, which requires a token
tfpf Oct 30, 2024
783ba6d
Install to target
tfpf Oct 30, 2024
e339c64
Fixed `make` command
tfpf Oct 30, 2024
93e4ab0
Windows has `mkdir`
tfpf Oct 30, 2024
9788817
Install pkg-onfig
tfpf Oct 30, 2024
27cbf0a
Removed package workflow
tfpf Oct 30, 2024
5719a28
Removed code to load `__git_ps1` in Bash and Zsh
tfpf Oct 30, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion custom-prompt/.clang-format
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ BreakBeforeInheritanceComma: false
BreakInheritanceList: BeforeColon
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeComma
BreakConstructorInitializers: AfterColon
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 119
Expand Down
3 changes: 2 additions & 1 deletion custom-prompt/Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
CC = gcc
CPPFLAGS = $(shell pkg-config --cflags libgit2)
CFLAGS = -fstrict-aliasing -std=c11 -Wall -Wextra
CXXFLAGS = -fstrict-aliasing -std=c++17 -Wall -Wextra
LDLIBS = -lstdc++
LDLIBS = -lstdc++ $(shell pkg-config --libs libgit2)

MainSource = custom-prompt.cc
MainBashObject = custom-bash-prompt.o
Expand Down
101 changes: 99 additions & 2 deletions custom-prompt/custom-prompt.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,20 @@
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <filesystem>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <string>

#ifdef __linux__
namespace C
{
#include <git2.h>
#ifdef __linux__
#include <libnotify/notify.h>
}
#endif
}

#if defined __APPLE__
#define HOST_ICON ""
Expand Down Expand Up @@ -163,6 +166,99 @@ void Interval::print_long(std::ostream& ostream) const
*****************************************************************************/
extern "C" long long unsigned get_active_wid(void);

/******************************************************************************
* Store information about the current Git repository.
*****************************************************************************/
class GitRepository
{
private:
C::git_repository* repo;
std::filesystem::path gitdir;
std::string ref;
bool detached;
tfpf marked this conversation as resolved.
Show resolved Hide resolved
bool bisecting, cherrypicking, merging, rebasing, reverting;
tfpf marked this conversation as resolved.
Show resolved Hide resolved

public:
GitRepository(void);
std::string reference(void);
std::string info(void);
};

/******************************************************************************
* Read the current Git repository.
*****************************************************************************/
GitRepository::GitRepository(void) :
bisecting(false), cherrypicking(false), merging(false), rebasing(false), reverting(false)
{
C::git_libgit2_init();
if (C::git_repository_open_ext(&this->repo, ".", 0, nullptr) != 0)
{
return;
}
this->gitdir = C::git_repository_path(this->repo);
this->ref = this->reference();
this->detached = C::git_repository_head_detached(this->repo);
switch (C::git_repository_state(this->repo))
{
case C::GIT_REPOSITORY_STATE_BISECT:
this->bisecting = true;
break;
case C::GIT_REPOSITORY_STATE_CHERRYPICK:
case C::GIT_REPOSITORY_STATE_CHERRYPICK_SEQUENCE:
this->cherrypicking = true;
break;
case C::GIT_REPOSITORY_STATE_MERGE:
this->merging = true;
break;
case C::GIT_REPOSITORY_STATE_REBASE:
case C::GIT_REPOSITORY_STATE_REBASE_INTERACTIVE:
case C::GIT_REPOSITORY_STATE_REBASE_MERGE:
this->rebasing = true;
break;
case C::GIT_REPOSITORY_STATE_REVERT:
case C::GIT_REPOSITORY_STATE_REVERT_SEQUENCE:
this->reverting = true;
break;
}
}

/******************************************************************************
* Read the reference of the current Git repository.
*
* @return Git reference (branch name or commit hash).
*****************************************************************************/
std::string GitRepository::reference(void)
{
// The head is not resolved correctly if there are no commits yet, so just
// do this manually.
std::ifstream head_file(this->gitdir / "HEAD");
std::string head_contents;
std::getline(head_file, head_contents);
if (head_contents.rfind("ref: refs/heads/", 0) == 0)
{
return head_contents.substr(16);
}
return head_contents.substr(0, 8);
tfpf marked this conversation as resolved.
Show resolved Hide resolved
}

/******************************************************************************
* Provide information about the current Git repository in a manner suitable to
* display in the shell prompt.
*
* @return Git information.
*****************************************************************************/
std::string GitRepository::info(void)
{
LOG_DEBUG("ref=%s", this->ref.data());
LOG_DEBUG("detached=%d", this->detached);
LOG_DEBUG("bisecting=%d", this->bisecting);
LOG_DEBUG("cherrypicking=%d", this->cherrypicking);
LOG_DEBUG("merging=%d", this->merging);
LOG_DEBUG("rebasing=%d", this->rebasing);
LOG_DEBUG("reverting=%d", this->reverting);
return "";
}

/******************************************************************************
* Get the current timestamp.
*
Expand Down Expand Up @@ -384,6 +480,7 @@ int main_internal(int const argc, char const* argv[])
std::size_t columns = std::stoull(argv[5]);
report_command_status(last_command, exit_code, delay, prev_active_wid, columns);

GitRepository().info();
std::string_view git_info(argv[6]);
int shlvl = std::stoi(argv[7]);
display_primary_prompt(git_info, shlvl);
Expand Down
Loading