From ca7da1772e64e54584e5443a483cae629b262a7b Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Sat, 26 Oct 2024 22:14:27 +0530 Subject: [PATCH 01/34] Added simple Git repository parsing code The reference (which can be the branch name or commit hash) is obtained by reading `.git/HEAD` because the suggested way (https://stackoverflow.com/questions/12132862) does not work (`git_repository_head` fails) if there are no commits on the branch yet. --- custom-prompt/Makefile | 3 +- custom-prompt/custom-prompt.cc | 62 ++++++++++++++++++++++++++++++++-- 2 files changed, 62 insertions(+), 3 deletions(-) diff --git a/custom-prompt/Makefile b/custom-prompt/Makefile index 0a5d8e0..e8b07c4 100644 --- a/custom-prompt/Makefile +++ b/custom-prompt/Makefile @@ -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 diff --git a/custom-prompt/custom-prompt.cc b/custom-prompt/custom-prompt.cc index a99a7c8..9469e84 100644 --- a/custom-prompt/custom-prompt.cc +++ b/custom-prompt/custom-prompt.cc @@ -3,17 +3,20 @@ #include #include #include +#include +#include #include #include #include #include -#ifdef __linux__ namespace C { +#include +#ifdef __linux__ #include -} #endif +} #if defined __APPLE__ #define HOST_ICON "" @@ -163,6 +166,60 @@ void Interval::print_long(std::ostream& ostream) const *****************************************************************************/ extern "C" long long unsigned get_active_wid(void); +/****************************************************************************** + * Load the current Git repository. + *****************************************************************************/ +class GitRepository +{ +private: + C::git_repository* repo; + std::filesystem::path gitdir; + std::string ref; + +public: + GitRepository(void); + std::string reference(void); +}; + +/****************************************************************************** + * Read the current Git repository. + *****************************************************************************/ +GitRepository::GitRepository(void) +{ + C::git_libgit2_init(); + if (C::git_repository_open_ext(&this->repo, ".", 0, nullptr) != 0) + { + LOG_DEBUG("Failed to open."); + return; + } + this->gitdir = C::git_repository_path(this->repo); + this->ref = this->reference(); + LOG_DEBUG("ref=%s", this->ref.data()); + // if (C::git_repository_head(&this->ref, this->repo) != 0) + // { + // LOG_DEBUG("Failed to get HEAD."); + // return; + // } + // LOG_DEBUG("ref=%s", git_reference_name(this->ref)); +} + +/****************************************************************************** + * Read the reference of the current Git repository. + * + * @return Git reference (branch name or commit hash). + *****************************************************************************/ +std::string GitRepository::reference(void) +{ + 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); +} + /****************************************************************************** * Get the current timestamp. * @@ -384,6 +441,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(); std::string_view git_info(argv[6]); int shlvl = std::stoi(argv[7]); display_primary_prompt(git_info, shlvl); From 4b0f47956908e6f7e895af3cf309bbb6f871849f Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Sat, 26 Oct 2024 22:21:44 +0530 Subject: [PATCH 02/34] Workflow: install libgit2 on Linux --- .github/workflows/package.yml | 4 ++-- custom-prompt/custom-prompt.cc | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/package.yml b/.github/workflows/package.yml index e55ef2a..6a2ae3e 100644 --- a/.github/workflows/package.yml +++ b/.github/workflows/package.yml @@ -32,9 +32,9 @@ jobs: os: [{name: 'alpine', tag: '3.20', libc: 'musl'}, {name: 'debian', tag: '12', libc: 'gnu'}] steps: - if: matrix.os.name == 'alpine' - run: apk add build-base libnotify-dev libx11-dev + run: apk add build-base libgit2 libnotify-dev libx11-dev - if: matrix.os.name == 'debian' - run: apt-get update && apt-get install -y build-essential libnotify-dev libx11-dev + run: apt-get update && apt-get install -y build-essential libgit2-dev libnotify-dev libx11-dev - uses: actions/checkout@v1 - run: make -j release working-directory: custom-prompt diff --git a/custom-prompt/custom-prompt.cc b/custom-prompt/custom-prompt.cc index 9469e84..2023dba 100644 --- a/custom-prompt/custom-prompt.cc +++ b/custom-prompt/custom-prompt.cc @@ -167,7 +167,7 @@ void Interval::print_long(std::ostream& ostream) const extern "C" long long unsigned get_active_wid(void); /****************************************************************************** - * Load the current Git repository. + * Store information about the current Git repository. *****************************************************************************/ class GitRepository { From 6e2bf9dd86dbd7483eeb0a26501c679e3f4e3cc5 Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Sun, 27 Oct 2024 00:16:33 +0530 Subject: [PATCH 03/34] Merge and rebase status --- custom-prompt/.clang-format | 2 +- custom-prompt/custom-prompt.cc | 42 ++++++++++++++++++++++++++-------- 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/custom-prompt/.clang-format b/custom-prompt/.clang-format index d425cfb..5401274 100644 --- a/custom-prompt/.clang-format +++ b/custom-prompt/.clang-format @@ -54,7 +54,7 @@ BreakBeforeInheritanceComma: false BreakInheritanceList: BeforeColon BreakBeforeTernaryOperators: true BreakConstructorInitializersBeforeComma: false -BreakConstructorInitializers: BeforeComma +BreakConstructorInitializers: AfterColon BreakAfterJavaFieldAnnotations: false BreakStringLiterals: true ColumnLimit: 119 diff --git a/custom-prompt/custom-prompt.cc b/custom-prompt/custom-prompt.cc index 2023dba..7fee8b3 100644 --- a/custom-prompt/custom-prompt.cc +++ b/custom-prompt/custom-prompt.cc @@ -175,16 +175,19 @@ class GitRepository C::git_repository* repo; std::filesystem::path gitdir; std::string ref; + bool detached; + bool merging, rebasing; public: GitRepository(void); std::string reference(void); + std::string info(void); }; /****************************************************************************** * Read the current Git repository. *****************************************************************************/ -GitRepository::GitRepository(void) +GitRepository::GitRepository(void) : merging(false), rebasing(false) { C::git_libgit2_init(); if (C::git_repository_open_ext(&this->repo, ".", 0, nullptr) != 0) @@ -194,13 +197,17 @@ GitRepository::GitRepository(void) } this->gitdir = C::git_repository_path(this->repo); this->ref = this->reference(); - LOG_DEBUG("ref=%s", this->ref.data()); - // if (C::git_repository_head(&this->ref, this->repo) != 0) - // { - // LOG_DEBUG("Failed to get HEAD."); - // return; - // } - // LOG_DEBUG("ref=%s", git_reference_name(this->ref)); + this->detached = C::git_repository_head_detached(this->repo); + switch (C::git_repository_state(this->repo)) + { + 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; + } } /****************************************************************************** @@ -210,6 +217,8 @@ GitRepository::GitRepository(void) *****************************************************************************/ 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); @@ -220,6 +229,21 @@ std::string GitRepository::reference(void) return head_contents.substr(0, 8); } +/****************************************************************************** + * 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("merging=%d", this->merging); + LOG_DEBUG("rebasing=%d", this->rebasing); + return ""; +} + /****************************************************************************** * Get the current timestamp. * @@ -441,7 +465,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(); + GitRepository().info(); std::string_view git_info(argv[6]); int shlvl = std::stoi(argv[7]); display_primary_prompt(git_info, shlvl); From 1d513ec0896009c6f856eece1d8654d0b1ab19a3 Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Sun, 27 Oct 2024 00:27:18 +0530 Subject: [PATCH 04/34] Cherry-picking and reverting statuses --- custom-prompt/custom-prompt.cc | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/custom-prompt/custom-prompt.cc b/custom-prompt/custom-prompt.cc index 7fee8b3..3422d74 100644 --- a/custom-prompt/custom-prompt.cc +++ b/custom-prompt/custom-prompt.cc @@ -176,7 +176,7 @@ class GitRepository std::filesystem::path gitdir; std::string ref; bool detached; - bool merging, rebasing; + bool cherrypicking, merging, rebasing, reverting; public: GitRepository(void); @@ -187,7 +187,7 @@ class GitRepository /****************************************************************************** * Read the current Git repository. *****************************************************************************/ -GitRepository::GitRepository(void) : merging(false), rebasing(false) +GitRepository::GitRepository(void) : cherrypicking(false), merging(false), rebasing(false), reverting(false) { C::git_libgit2_init(); if (C::git_repository_open_ext(&this->repo, ".", 0, nullptr) != 0) @@ -200,6 +200,10 @@ GitRepository::GitRepository(void) : merging(false), rebasing(false) this->detached = C::git_repository_head_detached(this->repo); switch (C::git_repository_state(this->repo)) { + 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; @@ -207,6 +211,11 @@ GitRepository::GitRepository(void) : merging(false), rebasing(false) 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; } } @@ -239,8 +248,10 @@ std::string GitRepository::info(void) { LOG_DEBUG("ref=%s", this->ref.data()); LOG_DEBUG("detached=%d", this->detached); + 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 ""; } From 8aabb90a3194810d3fc7566a648383e99cc4e5df Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Sun, 27 Oct 2024 00:27:59 +0530 Subject: [PATCH 05/34] Reverted workflow change --- .github/workflows/package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/package.yml b/.github/workflows/package.yml index 6a2ae3e..e55ef2a 100644 --- a/.github/workflows/package.yml +++ b/.github/workflows/package.yml @@ -32,9 +32,9 @@ jobs: os: [{name: 'alpine', tag: '3.20', libc: 'musl'}, {name: 'debian', tag: '12', libc: 'gnu'}] steps: - if: matrix.os.name == 'alpine' - run: apk add build-base libgit2 libnotify-dev libx11-dev + run: apk add build-base libnotify-dev libx11-dev - if: matrix.os.name == 'debian' - run: apt-get update && apt-get install -y build-essential libgit2-dev libnotify-dev libx11-dev + run: apt-get update && apt-get install -y build-essential libnotify-dev libx11-dev - uses: actions/checkout@v1 - run: make -j release working-directory: custom-prompt From 40c3a21c71ecb93bcbe04999999b29811921b77a Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Sun, 27 Oct 2024 00:37:02 +0530 Subject: [PATCH 06/34] Bisecting status --- custom-prompt/custom-prompt.cc | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/custom-prompt/custom-prompt.cc b/custom-prompt/custom-prompt.cc index 3422d74..a0f3206 100644 --- a/custom-prompt/custom-prompt.cc +++ b/custom-prompt/custom-prompt.cc @@ -176,7 +176,7 @@ class GitRepository std::filesystem::path gitdir; std::string ref; bool detached; - bool cherrypicking, merging, rebasing, reverting; + bool bisecting, cherrypicking, merging, rebasing, reverting; public: GitRepository(void); @@ -187,12 +187,12 @@ class GitRepository /****************************************************************************** * Read the current Git repository. *****************************************************************************/ -GitRepository::GitRepository(void) : cherrypicking(false), merging(false), rebasing(false), reverting(false) +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) { - LOG_DEBUG("Failed to open."); return; } this->gitdir = C::git_repository_path(this->repo); @@ -200,6 +200,9 @@ GitRepository::GitRepository(void) : cherrypicking(false), merging(false), rebas 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; @@ -248,6 +251,7 @@ 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); From b26338a01c10ee44984e7379a47fc1f942aeb2e4 Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Sun, 27 Oct 2024 22:51:44 +0530 Subject: [PATCH 07/34] Full handling of (unborn) branch name, commit ID and tag --- custom-prompt/custom-prompt.cc | 104 +++++++++++++++++++++++++++------ 1 file changed, 85 insertions(+), 19 deletions(-) diff --git a/custom-prompt/custom-prompt.cc b/custom-prompt/custom-prompt.cc index a0f3206..a56f286 100644 --- a/custom-prompt/custom-prompt.cc +++ b/custom-prompt/custom-prompt.cc @@ -174,14 +174,20 @@ class GitRepository private: C::git_repository* repo; std::filesystem::path gitdir; - std::string ref; + C::git_reference* ref; + C::git_oid const* oid; + std::string description; bool detached; bool bisecting, cherrypicking, merging, rebasing, reverting; public: GitRepository(void); - std::string reference(void); - std::string info(void); + std::string get_information(void); + +private: + void set_description(void); + void set_state(void); + static int compare_tag_update_description(char const* name, C::git_oid* oid, void* self_); }; /****************************************************************************** @@ -190,14 +196,63 @@ class GitRepository GitRepository::GitRepository(void) : bisecting(false), cherrypicking(false), merging(false), rebasing(false), reverting(false) { - C::git_libgit2_init(); + if (C::git_libgit2_init() <= 0) + { + return; + } 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->set_description(); this->detached = C::git_repository_head_detached(this->repo); + this->set_state(); +} + +/****************************************************************************** + * Obtain a human-readable description of the current working tree of the + * current Git repository. This shall be the branch name, commit hash or tag. + *****************************************************************************/ +void GitRepository::set_description(void) +{ + if (C::git_repository_head(&this->ref, this->repo) == 0) + { + if (C::git_reference_is_branch(this->ref)) + { + char const* branch_name; + if (C::git_branch_name(&branch_name, this->ref) == 0) + { + this->description = branch_name; + return; + }; + } + + // If not on a branch, use the commit hash and the tag (if there is + // one). + this->oid = C::git_reference_target(this->ref); + this->description = C::git_oid_tostr_s(this->oid); + this->description.erase(7); + C::git_tag_foreach(this->repo, this->compare_tag_update_description, this); + return; + } + + // If we are here, we must be on a branch with no commits. Obtain the + // required information manually. + std::ifstream head_file(this->gitdir / "HEAD"); + if (!head_file.good()) + { + return; + } + std::getline(head_file, this->description); +} + +/****************************************************************************** + * Obtain the current state (operation in progress) of the current Git + * repository. + *****************************************************************************/ +void GitRepository::set_state(void) +{ switch (C::git_repository_state(this->repo)) { case C::GIT_REPOSITORY_STATE_BISECT: @@ -223,22 +278,33 @@ GitRepository::GitRepository(void) : } /****************************************************************************** - * Read the reference of the current Git repository. + * Check whether the given tag matches the reference of the given + * `GitRepository` instance. If it does, update the description of the latter + * with the tag name. + * + * This is a static method because otherwise, its signature does not match the + * required signature for use as a callback function. + * + * @param name Tag name. + * @param oid Tag object ID. + * @param self_ `GitRepository` instance whose description should be updated. * - * @return Git reference (branch name or commit hash). + * @return 1 if the tag matches the reference, 0 otherwise. *****************************************************************************/ -std::string GitRepository::reference(void) +int GitRepository::compare_tag_update_description(char const* name, C::git_oid* oid, void* self_) { - // 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) + GitRepository* self = static_cast(self_); + if (C::git_oid_cmp(oid, self->oid) != 0) + { + return 0; + } + std::string tag_name = name; + if (tag_name.rfind("refs/tags/", 0) == 0) { - return head_contents.substr(16); + tag_name = tag_name.substr(10); } - return head_contents.substr(0, 8); + self->description += " 󰓼 " + tag_name; + return 1; } /****************************************************************************** @@ -247,9 +313,9 @@ std::string GitRepository::reference(void) * * @return Git information. *****************************************************************************/ -std::string GitRepository::info(void) +std::string GitRepository::get_information(void) { - LOG_DEBUG("ref=%s", this->ref.data()); + LOG_DEBUG("description=%s", this->description.data()); LOG_DEBUG("detached=%d", this->detached); LOG_DEBUG("bisecting=%d", this->bisecting); LOG_DEBUG("cherrypicking=%d", this->cherrypicking); @@ -480,7 +546,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(); + GitRepository().get_information(); std::string_view git_info(argv[6]); int shlvl = std::stoi(argv[7]); display_primary_prompt(git_info, shlvl); From 0ce33f4ce3041a2c60ef0e3c0d631313aa47271f Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Sun, 27 Oct 2024 23:00:34 +0530 Subject: [PATCH 08/34] No need to check if reference is branch `git_branch_name` already does that --- custom-prompt/custom-prompt.cc | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/custom-prompt/custom-prompt.cc b/custom-prompt/custom-prompt.cc index a56f286..0345535 100644 --- a/custom-prompt/custom-prompt.cc +++ b/custom-prompt/custom-prompt.cc @@ -218,15 +218,12 @@ void GitRepository::set_description(void) { if (C::git_repository_head(&this->ref, this->repo) == 0) { - if (C::git_reference_is_branch(this->ref)) + char const* branch_name; + if (C::git_branch_name(&branch_name, this->ref) == 0) { - char const* branch_name; - if (C::git_branch_name(&branch_name, this->ref) == 0) - { - this->description = branch_name; - return; - }; - } + this->description = branch_name; + return; + }; // If not on a branch, use the commit hash and the tag (if there is // one). From 3cf7081812975558dc4a0cc4195f8e928e758875 Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Sun, 27 Oct 2024 23:29:58 +0530 Subject: [PATCH 09/34] Status listing with callback --- custom-prompt/custom-prompt.cc | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/custom-prompt/custom-prompt.cc b/custom-prompt/custom-prompt.cc index 0345535..e6a1b9b 100644 --- a/custom-prompt/custom-prompt.cc +++ b/custom-prompt/custom-prompt.cc @@ -187,7 +187,9 @@ class GitRepository private: void set_description(void); void set_state(void); + void set_status(void); static int compare_tag_update_description(char const* name, C::git_oid* oid, void* self_); + static int update_status(char const* path, unsigned status_flags, void* self_); }; /****************************************************************************** @@ -208,6 +210,7 @@ GitRepository::GitRepository(void) : this->set_description(); this->detached = C::git_repository_head_detached(this->repo); this->set_state(); + this->set_status(); } /****************************************************************************** @@ -274,6 +277,15 @@ void GitRepository::set_state(void) } } +/****************************************************************************** + * Obtain the current status of the index and working tree of the current Git + * repository. + *****************************************************************************/ +void GitRepository::set_status(void) +{ + C::git_status_foreach(this->repo, this->update_status, this); +} + /****************************************************************************** * Check whether the given tag matches the reference of the given * `GitRepository` instance. If it does, update the description of the latter @@ -304,6 +316,23 @@ int GitRepository::compare_tag_update_description(char const* name, C::git_oid* return 1; } +/****************************************************************************** + * Check whether the given file is modified, staged or untracked, and update + * the corresponding members of the given `GitRepository` instance. + * + * @param path File path. + * @param status_flags Flags indicating the status of the file. + * @param self_ `GitRepository` instance whose members should be updated. + * + * @return 1 if all statuses are recorded, 0 otherwise. + *****************************************************************************/ +int GitRepository::update_status(char const* path, unsigned status_flags, void* self_) +{ + GitRepository* self = static_cast(self_); + LOG_DEBUG("path=%s", path); + return 0; +} + /****************************************************************************** * Provide information about the current Git repository in a manner suitable to * display in the shell prompt. From 2c794690a88d725fa3f2a524b62c76179c472a80 Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Mon, 28 Oct 2024 00:34:06 +0530 Subject: [PATCH 10/34] Moved callback function explanation to declaration --- custom-prompt/custom-prompt.cc | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/custom-prompt/custom-prompt.cc b/custom-prompt/custom-prompt.cc index e6a1b9b..1e40edc 100644 --- a/custom-prompt/custom-prompt.cc +++ b/custom-prompt/custom-prompt.cc @@ -188,6 +188,8 @@ class GitRepository void set_description(void); void set_state(void); void set_status(void); + // These are static methods because otherwise, their signatures do not + // match the required signatures for use as callback functions. static int compare_tag_update_description(char const* name, C::git_oid* oid, void* self_); static int update_status(char const* path, unsigned status_flags, void* self_); }; @@ -291,9 +293,6 @@ void GitRepository::set_status(void) * `GitRepository` instance. If it does, update the description of the latter * with the tag name. * - * This is a static method because otherwise, its signature does not match the - * required signature for use as a callback function. - * * @param name Tag name. * @param oid Tag object ID. * @param self_ `GitRepository` instance whose description should be updated. From 7078293a42abfb954878b80a41d1ed0f32cbe607 Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Mon, 28 Oct 2024 22:40:51 +0530 Subject: [PATCH 11/34] Replaced state `bool`s with single `std::string` --- custom-prompt/custom-prompt.cc | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/custom-prompt/custom-prompt.cc b/custom-prompt/custom-prompt.cc index 1e40edc..dd66fbd 100644 --- a/custom-prompt/custom-prompt.cc +++ b/custom-prompt/custom-prompt.cc @@ -178,7 +178,7 @@ class GitRepository C::git_oid const* oid; std::string description; bool detached; - bool bisecting, cherrypicking, merging, rebasing, reverting; + std::string state; public: GitRepository(void); @@ -197,8 +197,7 @@ class GitRepository /****************************************************************************** * Read the current Git repository. *****************************************************************************/ -GitRepository::GitRepository(void) : - bisecting(false), cherrypicking(false), merging(false), rebasing(false), reverting(false) +GitRepository::GitRepository(void) { if (C::git_libgit2_init() <= 0) { @@ -247,6 +246,10 @@ void GitRepository::set_description(void) return; } std::getline(head_file, this->description); + if (this->description.rfind("ref: refs/heads/", 0) == 0) + { + this->description.erase(0, 16); + } } /****************************************************************************** @@ -258,23 +261,23 @@ void GitRepository::set_state(void) switch (C::git_repository_state(this->repo)) { case C::GIT_REPOSITORY_STATE_BISECT: - this->bisecting = true; + this->state = "bisecting"; break; case C::GIT_REPOSITORY_STATE_CHERRYPICK: case C::GIT_REPOSITORY_STATE_CHERRYPICK_SEQUENCE: - this->cherrypicking = true; + this->state = "cherrypicking"; break; case C::GIT_REPOSITORY_STATE_MERGE: - this->merging = true; + this->state = "merging"; break; case C::GIT_REPOSITORY_STATE_REBASE: case C::GIT_REPOSITORY_STATE_REBASE_INTERACTIVE: case C::GIT_REPOSITORY_STATE_REBASE_MERGE: - this->rebasing = true; + this->state = "rebasing"; break; case C::GIT_REPOSITORY_STATE_REVERT: case C::GIT_REPOSITORY_STATE_REVERT_SEQUENCE: - this->reverting = true; + this->state = "reverting"; break; } } @@ -342,11 +345,7 @@ std::string GitRepository::get_information(void) { LOG_DEBUG("description=%s", this->description.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); + LOG_DEBUG("state=%s", this->state.data()); return ""; } From 03299671a6dda3aa2d0e1b985918796d50bef52e Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Mon, 28 Oct 2024 22:45:26 +0530 Subject: [PATCH 12/34] Added `bare` member --- custom-prompt/custom-prompt.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/custom-prompt/custom-prompt.cc b/custom-prompt/custom-prompt.cc index dd66fbd..58a666d 100644 --- a/custom-prompt/custom-prompt.cc +++ b/custom-prompt/custom-prompt.cc @@ -177,7 +177,7 @@ class GitRepository C::git_reference* ref; C::git_oid const* oid; std::string description; - bool detached; + bool bare, detached; std::string state; public: @@ -209,6 +209,7 @@ GitRepository::GitRepository(void) } this->gitdir = C::git_repository_path(this->repo); this->set_description(); + this->bare = C::git_repository_is_bare(this->repo); this->detached = C::git_repository_head_detached(this->repo); this->set_state(); this->set_status(); @@ -344,6 +345,7 @@ int GitRepository::update_status(char const* path, unsigned status_flags, void* std::string GitRepository::get_information(void) { LOG_DEBUG("description=%s", this->description.data()); + LOG_DEBUG("bare=%d", this->bare); LOG_DEBUG("detached=%d", this->detached); LOG_DEBUG("state=%s", this->state.data()); return ""; From 779c8e2b4ed70750420a2206fda1f07ed726d932 Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Mon, 28 Oct 2024 23:01:43 +0530 Subject: [PATCH 13/34] Renamed `set_*` methods as `establish_*` because they are not setters --- custom-prompt/custom-prompt.cc | 36 ++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/custom-prompt/custom-prompt.cc b/custom-prompt/custom-prompt.cc index 58a666d..0dcdeb9 100644 --- a/custom-prompt/custom-prompt.cc +++ b/custom-prompt/custom-prompt.cc @@ -185,13 +185,13 @@ class GitRepository std::string get_information(void); private: - void set_description(void); - void set_state(void); - void set_status(void); + void establish_description(void); + void establish_state(void); + void establish_dirty_staged_untracked(void); // These are static methods because otherwise, their signatures do not // match the required signatures for use as callback functions. static int compare_tag_update_description(char const* name, C::git_oid* oid, void* self_); - static int update_status(char const* path, unsigned status_flags, void* self_); + static int update_dirty_staged_untracked(char const* path, unsigned status_flags, void* self_); }; /****************************************************************************** @@ -208,18 +208,20 @@ GitRepository::GitRepository(void) return; } this->gitdir = C::git_repository_path(this->repo); - this->set_description(); + this->establish_description(); this->bare = C::git_repository_is_bare(this->repo); this->detached = C::git_repository_head_detached(this->repo); - this->set_state(); - this->set_status(); + this->establish_state(); + this->establish_dirty_staged_untracked(); } /****************************************************************************** - * Obtain a human-readable description of the current working tree of the - * current Git repository. This shall be the branch name, commit hash or tag. + * Obtain a human-readable description of the working tree of the current Git + * repository. This shall be the name of the current branch if it is available. + * Otherwise, it shall be the hash of the most recent commit (and possibly its + * tag). *****************************************************************************/ -void GitRepository::set_description(void) +void GitRepository::establish_description(void) { if (C::git_repository_head(&this->ref, this->repo) == 0) { @@ -254,10 +256,10 @@ void GitRepository::set_description(void) } /****************************************************************************** - * Obtain the current state (operation in progress) of the current Git - * repository. + * Obtain the state of the working tree of the current Git repository. This + * shall be the name of the operation currently in progress (if any). *****************************************************************************/ -void GitRepository::set_state(void) +void GitRepository::establish_state(void) { switch (C::git_repository_state(this->repo)) { @@ -284,12 +286,12 @@ void GitRepository::set_state(void) } /****************************************************************************** - * Obtain the current status of the index and working tree of the current Git + * Obtain the status of the index and working tree of the current Git * repository. *****************************************************************************/ -void GitRepository::set_status(void) +void GitRepository::establish_dirty_staged_untracked(void) { - C::git_status_foreach(this->repo, this->update_status, this); + C::git_status_foreach(this->repo, this->update_dirty_staged_untracked, this); } /****************************************************************************** @@ -329,7 +331,7 @@ int GitRepository::compare_tag_update_description(char const* name, C::git_oid* * * @return 1 if all statuses are recorded, 0 otherwise. *****************************************************************************/ -int GitRepository::update_status(char const* path, unsigned status_flags, void* self_) +int GitRepository::update_dirty_staged_untracked(char const* path, unsigned status_flags, void* self_) { GitRepository* self = static_cast(self_); LOG_DEBUG("path=%s", path); From 9b024cee7760ba784d6d23af13b990687309e594 Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Mon, 28 Oct 2024 23:18:33 +0530 Subject: [PATCH 14/34] Skip ignored files in status detection --- custom-prompt/custom-prompt.cc | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/custom-prompt/custom-prompt.cc b/custom-prompt/custom-prompt.cc index 0dcdeb9..86181cf 100644 --- a/custom-prompt/custom-prompt.cc +++ b/custom-prompt/custom-prompt.cc @@ -179,6 +179,7 @@ class GitRepository std::string description; bool bare, detached; std::string state; + bool dirty, staged, untracked; public: GitRepository(void); @@ -197,7 +198,7 @@ class GitRepository /****************************************************************************** * Read the current Git repository. *****************************************************************************/ -GitRepository::GitRepository(void) +GitRepository::GitRepository(void) : dirty(false), staged(false), untracked(false) { if (C::git_libgit2_init() <= 0) { @@ -291,7 +292,9 @@ void GitRepository::establish_state(void) *****************************************************************************/ void GitRepository::establish_dirty_staged_untracked(void) { - C::git_status_foreach(this->repo, this->update_dirty_staged_untracked, this); + C::git_status_options opts = GIT_STATUS_OPTIONS_INIT; + opts.flags = C::GIT_STATUS_OPT_INCLUDE_UNTRACKED | C::GIT_STATUS_OPT_EXCLUDE_SUBMODULES; + C::git_status_foreach_ext(this->repo, &opts, this->update_dirty_staged_untracked, this); } /****************************************************************************** From d34b6e419c436288116ec3d5dfbc0b2244d2aeea Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Mon, 28 Oct 2024 23:39:28 +0530 Subject: [PATCH 15/34] Completed status detection code --- custom-prompt/custom-prompt.cc | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/custom-prompt/custom-prompt.cc b/custom-prompt/custom-prompt.cc index 86181cf..c7d053a 100644 --- a/custom-prompt/custom-prompt.cc +++ b/custom-prompt/custom-prompt.cc @@ -321,6 +321,7 @@ int GitRepository::compare_tag_update_description(char const* name, C::git_oid* tag_name = tag_name.substr(10); } self->description += " 󰓼 " + tag_name; + // Found a match. Stop iterating. return 1; } @@ -337,7 +338,28 @@ int GitRepository::compare_tag_update_description(char const* name, C::git_oid* int GitRepository::update_dirty_staged_untracked(char const* path, unsigned status_flags, void* self_) { GitRepository* self = static_cast(self_); - LOG_DEBUG("path=%s", path); + if (status_flags + & (C::GIT_STATUS_WT_DELETED | C::GIT_STATUS_WT_MODIFIED | C::GIT_STATUS_WT_RENAMED + | C::GIT_STATUS_WT_TYPECHANGE)) + { + self->dirty = true; + } + else if (status_flags + & (C::GIT_STATUS_INDEX_DELETED | C::GIT_STATUS_INDEX_MODIFIED | C::GIT_STATUS_INDEX_NEW + | C::GIT_STATUS_INDEX_RENAMED | C::GIT_STATUS_INDEX_TYPECHANGE)) + { + self->staged = true; + } + else if (status_flags & C::GIT_STATUS_WT_NEW) + { + self->untracked = true; + } + if (self->dirty && self->staged && self->untracked) + { + // Found all possible statuses. No use searching further. Stop + // iterating. + return 1; + } return 0; } From 1b14bf900823872a2cd520bea1c8e47b050ba54c Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Tue, 29 Oct 2024 00:57:16 +0530 Subject: [PATCH 16/34] Use git information from libgit2 instead of `__git_ps1` --- custom-prompt/custom-prompt.cc | 65 +++++++++++++++++++++++++--------- 1 file changed, 49 insertions(+), 16 deletions(-) diff --git a/custom-prompt/custom-prompt.cc b/custom-prompt/custom-prompt.cc index c7d053a..7e63c30 100644 --- a/custom-prompt/custom-prompt.cc +++ b/custom-prompt/custom-prompt.cc @@ -71,13 +71,18 @@ namespace C // Bright. #define B_BLUE BEGIN_INVISIBLE ESCAPE LEFT_SQUARE_BRACKET "94m" END_INVISIBLE +#define B_GREEN BEGIN_INVISIBLE ESCAPE LEFT_SQUARE_BRACKET "92m" END_INVISIBLE #define B_GREEN_RAW ESCAPE LEFT_SQUARE_BRACKET "92m" #define B_GREY_RAW ESCAPE LEFT_SQUARE_BRACKET "90m" +#define B_RED BEGIN_INVISIBLE ESCAPE LEFT_SQUARE_BRACKET "91m" END_INVISIBLE #define B_RED_RAW ESCAPE LEFT_SQUARE_BRACKET "91m" +#define B_YELLOW BEGIN_INVISIBLE ESCAPE LEFT_SQUARE_BRACKET "93m" END_INVISIBLE // Dark. #define D_CYAN_RAW ESCAPE LEFT_SQUARE_BRACKET "36m" +#define D_GREEN BEGIN_INVISIBLE ESCAPE LEFT_SQUARE_BRACKET "32m" END_INVISIBLE #define D_GREEN_RAW ESCAPE LEFT_SQUARE_BRACKET "32m" +#define D_RED BEGIN_INVISIBLE ESCAPE LEFT_SQUARE_BRACKET "31m" END_INVISIBLE #define D_RED_RAW ESCAPE LEFT_SQUARE_BRACKET "31m" // No formatting. @@ -269,7 +274,7 @@ void GitRepository::establish_state(void) break; case C::GIT_REPOSITORY_STATE_CHERRYPICK: case C::GIT_REPOSITORY_STATE_CHERRYPICK_SEQUENCE: - this->state = "cherrypicking"; + this->state = "cherry-picking"; break; case C::GIT_REPOSITORY_STATE_MERGE: this->state = "merging"; @@ -329,14 +334,15 @@ int GitRepository::compare_tag_update_description(char const* name, C::git_oid* * Check whether the given file is modified, staged or untracked, and update * the corresponding members of the given `GitRepository` instance. * - * @param path File path. + * @param _path File path. * @param status_flags Flags indicating the status of the file. * @param self_ `GitRepository` instance whose members should be updated. * * @return 1 if all statuses are recorded, 0 otherwise. *****************************************************************************/ -int GitRepository::update_dirty_staged_untracked(char const* path, unsigned status_flags, void* self_) +int GitRepository::update_dirty_staged_untracked(char const* _path, unsigned status_flags, void* self_) { + _path = _path; // Suppress unused parameter warning. GitRepository* self = static_cast(self_); if (status_flags & (C::GIT_STATUS_WT_DELETED | C::GIT_STATUS_WT_MODIFIED | C::GIT_STATUS_WT_RENAMED @@ -371,11 +377,40 @@ int GitRepository::update_dirty_staged_untracked(char const* path, unsigned stat *****************************************************************************/ std::string GitRepository::get_information(void) { - LOG_DEBUG("description=%s", this->description.data()); - LOG_DEBUG("bare=%d", this->bare); - LOG_DEBUG("detached=%d", this->detached); - LOG_DEBUG("state=%s", this->state.data()); - return ""; + std::ostringstream information_stream; + if (this->bare) + { + information_stream << "bare | "; + } + if (this->detached) + { + information_stream << D_RED << this->description << RESET; + } + else + { + information_stream << D_GREEN << this->description << RESET; + } + if (this->dirty || this->staged || this->untracked) + { + information_stream << ' '; + } + if (this->dirty) + { + information_stream << B_YELLOW "*" RESET; + } + if (this->staged) + { + information_stream << B_GREEN "+" RESET; + } + if (this->untracked) + { + information_stream << B_RED "!" RESET; + } + if (!this->state.empty()) + { + information_stream << " | " << this->state; + } + return information_stream.str(); } /****************************************************************************** @@ -523,18 +558,18 @@ void report_command_status(std::string_view& last_command, int exit_code, long l /****************************************************************************** * Show the primary prompt. * - * @param git_info Description of the status of the current Git repository. * @param shlvl Current shell level. *****************************************************************************/ -void display_primary_prompt(std::string_view const& git_info, int shlvl) +void display_primary_prompt(int shlvl) { - LOG_DEBUG("Current Git repository state is '%s'.", git_info.data()); + std::string git_repository_information = GitRepository().get_information(); + LOG_DEBUG("Current Git repository information is '%s'.", git_repository_information.data()); char const* venv = std::getenv("VIRTUAL_ENV_PROMPT"); LOG_DEBUG("Current Python virtual environment is '%s'.", venv); std::cout << "\n┌[" BB_GREEN USER RESET " " BBI_YELLOW HOST_ICON " " HOST RESET " " BB_CYAN DIRECTORY RESET "]"; - if (!git_info.empty()) + if (!git_repository_information.empty()) { - std::cout << "  " << git_info; + std::cout << "  " << git_repository_information; } if (venv != nullptr) { @@ -599,10 +634,8 @@ 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().get_information(); - std::string_view git_info(argv[6]); int shlvl = std::stoi(argv[7]); - display_primary_prompt(git_info, shlvl); + display_primary_prompt(shlvl); std::string_view pwd(argv[8]); set_terminal_title(pwd); From 74ec24c1dae8f1e735e6b90f6fad6a601a819036 Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Tue, 29 Oct 2024 01:07:19 +0530 Subject: [PATCH 17/34] Updated Bash and Zsh to not pass `__git_ps1` output --- .bash_aliases | 2 +- .zshrc | 2 +- custom-prompt/custom-prompt.cc | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.bash_aliases b/.bash_aliases index 1af540b..f96bcd8 100644 --- a/.bash_aliases +++ b/.bash_aliases @@ -117,7 +117,7 @@ _after_command() local exit_code=$? [ -z "${__begin_window+.}" ] && return local last_command=$(history 1) - PS1=$(custom-bash-prompt "$last_command" $exit_code $__begin_window $COLUMNS "$(__git_ps1 %s)" $SHLVL "$PWD") + PS1=$(custom-bash-prompt "$last_command" $exit_code $__begin_window $COLUMNS $SHLVL "$PWD") unset __begin_window } diff --git a/.zshrc b/.zshrc index 564d8c9..a9bc111 100644 --- a/.zshrc +++ b/.zshrc @@ -6,7 +6,7 @@ _after_command() local exit_code=$? [ -z "${__begin_window+.}" ] && return local last_command=$(history -n -1 2>/dev/null) - PS1=$(custom-zsh-prompt "$last_command" $exit_code $=__begin_window $COLUMNS "$(__git_ps1 %s)" $SHLVL $PWD) + PS1=$(custom-zsh-prompt "$last_command" $exit_code $=__begin_window $COLUMNS $SHLVL $PWD) unset __begin_window } diff --git a/custom-prompt/custom-prompt.cc b/custom-prompt/custom-prompt.cc index 7e63c30..357bef9 100644 --- a/custom-prompt/custom-prompt.cc +++ b/custom-prompt/custom-prompt.cc @@ -622,7 +622,7 @@ int main_internal(int const argc, char const* argv[]) // null-terminated. if (argc == 2) { - char const* argv[] = { "custom-prompt", "[] last_command", "0", "0", "0", "79", "main", "1", "/", nullptr }; + char const* argv[] = { "custom-prompt", "[] last_command", "0", "0", "0", "79", "1", "/", nullptr }; int constexpr argc = sizeof argv / sizeof *argv - 1; return main_internal(argc, argv); } @@ -634,10 +634,10 @@ 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); - int shlvl = std::stoi(argv[7]); + int shlvl = std::stoi(argv[6]); display_primary_prompt(shlvl); - std::string_view pwd(argv[8]); + std::string_view pwd(argv[7]); set_terminal_title(pwd); return EXIT_SUCCESS; From 29aa066ce99e46c69cc1a85590c0dcb5122ebe06 Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Tue, 29 Oct 2024 01:15:37 +0530 Subject: [PATCH 18/34] Initialise all primitive members Use this to detect if there is no Git repository. --- custom-prompt/custom-prompt.cc | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/custom-prompt/custom-prompt.cc b/custom-prompt/custom-prompt.cc index 357bef9..edd0961 100644 --- a/custom-prompt/custom-prompt.cc +++ b/custom-prompt/custom-prompt.cc @@ -203,7 +203,9 @@ class GitRepository /****************************************************************************** * Read the current Git repository. *****************************************************************************/ -GitRepository::GitRepository(void) : dirty(false), staged(false), untracked(false) +GitRepository::GitRepository(void) : + repo(nullptr), ref(nullptr), oid(nullptr), bare(false), detached(false), dirty(false), staged(false), + untracked(false) { if (C::git_libgit2_init() <= 0) { @@ -377,6 +379,10 @@ int GitRepository::update_dirty_staged_untracked(char const* _path, unsigned sta *****************************************************************************/ std::string GitRepository::get_information(void) { + if (this->repo == nullptr) + { + return ""; + } std::ostringstream information_stream; if (this->bare) { From 5da796edc8dd6bf8d1ba22114e99431f1a0c6e1b Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Tue, 29 Oct 2024 01:30:05 +0530 Subject: [PATCH 19/34] Fixed edge case: a file can be new and modified both --- custom-prompt/custom-prompt.cc | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/custom-prompt/custom-prompt.cc b/custom-prompt/custom-prompt.cc index edd0961..00dc66c 100644 --- a/custom-prompt/custom-prompt.cc +++ b/custom-prompt/custom-prompt.cc @@ -346,22 +346,25 @@ int GitRepository::update_dirty_staged_untracked(char const* _path, unsigned sta { _path = _path; // Suppress unused parameter warning. GitRepository* self = static_cast(self_); + + // The first two branches below are mutually exclusive. The third is not + // mutually exclusive with either of them. if (status_flags & (C::GIT_STATUS_WT_DELETED | C::GIT_STATUS_WT_MODIFIED | C::GIT_STATUS_WT_RENAMED | C::GIT_STATUS_WT_TYPECHANGE)) { self->dirty = true; } - else if (status_flags + else if (status_flags & C::GIT_STATUS_WT_NEW) + { + self->untracked = true; + } + if (status_flags & (C::GIT_STATUS_INDEX_DELETED | C::GIT_STATUS_INDEX_MODIFIED | C::GIT_STATUS_INDEX_NEW | C::GIT_STATUS_INDEX_RENAMED | C::GIT_STATUS_INDEX_TYPECHANGE)) { self->staged = true; } - else if (status_flags & C::GIT_STATUS_WT_NEW) - { - self->untracked = true; - } if (self->dirty && self->staged && self->untracked) { // Found all possible statuses. No use searching further. Stop From 4cdf16ee3c181be50ccc6c78f11eec3e1576b6cd Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Tue, 29 Oct 2024 01:44:17 +0530 Subject: [PATCH 20/34] Removed static linking on Windows Cannot link libgit2 statically --- custom-prompt/Makefile | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/custom-prompt/Makefile b/custom-prompt/Makefile index e8b07c4..725a818 100644 --- a/custom-prompt/Makefile +++ b/custom-prompt/Makefile @@ -11,12 +11,7 @@ MainZshObject = custom-zsh-prompt.o MainZshExecutable = bin/$(MainZshObject:.o=) GetActiveWidObjects = get_active_wid_linux.o get_active_wid_windows.o -ifeq "$(OS)" "Windows_NT" - # When building using something other than Visual Studio, the shared - # libraries the executables are linked with may lie in folders Windows does - # not typically search. Avoid the hassle of fixing that. - LDFLAGS += -static -else +ifneq "$(OS)" "Windows_NT" UNAME = $(shell uname) ifeq "$(UNAME)" "Linux" CPPFLAGS += $(shell pkg-config --cflags glib-2.0 libnotify x11) From 9e84074a2488fcc91df3d1204ec2d3220e10ea37 Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Tue, 29 Oct 2024 02:17:15 +0530 Subject: [PATCH 21/34] Renames and minor fixes --- custom-prompt/custom-prompt.cc | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/custom-prompt/custom-prompt.cc b/custom-prompt/custom-prompt.cc index 00dc66c..6c9d02c 100644 --- a/custom-prompt/custom-prompt.cc +++ b/custom-prompt/custom-prompt.cc @@ -196,7 +196,7 @@ class GitRepository void establish_dirty_staged_untracked(void); // These are static methods because otherwise, their signatures do not // match the required signatures for use as callback functions. - static int compare_tag_update_description(char const* name, C::git_oid* oid, void* self_); + static int update_description(char const* name, C::git_oid* oid, void* self_); static int update_dirty_staged_untracked(char const* path, unsigned status_flags, void* self_); }; @@ -240,12 +240,13 @@ void GitRepository::establish_description(void) return; }; - // If not on a branch, use the commit hash and the tag (if there is - // one). + // If not on a branch, use the commit hash and the tag, if there is + // one. Unannotated tags cannot be looked up, so the only way to check + // is to iterate over all tags. this->oid = C::git_reference_target(this->ref); this->description = C::git_oid_tostr_s(this->oid); this->description.erase(7); - C::git_tag_foreach(this->repo, this->compare_tag_update_description, this); + C::git_tag_foreach(this->repo, this->update_description, this); return; } @@ -315,7 +316,7 @@ void GitRepository::establish_dirty_staged_untracked(void) * * @return 1 if the tag matches the reference, 0 otherwise. *****************************************************************************/ -int GitRepository::compare_tag_update_description(char const* name, C::git_oid* oid, void* self_) +int GitRepository::update_description(char const* name, C::git_oid* oid, void* self_) { GitRepository* self = static_cast(self_); if (C::git_oid_cmp(oid, self->oid) != 0) @@ -333,8 +334,8 @@ int GitRepository::compare_tag_update_description(char const* name, C::git_oid* } /****************************************************************************** - * Check whether the given file is modified, staged or untracked, and update - * the corresponding members of the given `GitRepository` instance. + * Check whether the given file is modified, staged or untracked. If it is, + * update the corresponding members of the given `GitRepository` instance. * * @param _path File path. * @param status_flags Flags indicating the status of the file. @@ -365,13 +366,9 @@ int GitRepository::update_dirty_staged_untracked(char const* _path, unsigned sta { self->staged = true; } - if (self->dirty && self->staged && self->untracked) - { - // Found all possible statuses. No use searching further. Stop - // iterating. - return 1; - } - return 0; + + // Stop iterating if all possible statuses were found. + return self->dirty && self->staged && self->untracked; } /****************************************************************************** From 4fcd5a71a1fbc331ea02326d6f65f1ddb2450652 Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Tue, 29 Oct 2024 19:38:05 +0530 Subject: [PATCH 22/34] Moved tag detection to separate method --- custom-prompt/custom-prompt.cc | 58 +++++++++++++++++++++++----------- 1 file changed, 40 insertions(+), 18 deletions(-) diff --git a/custom-prompt/custom-prompt.cc b/custom-prompt/custom-prompt.cc index 6c9d02c..db24d1a 100644 --- a/custom-prompt/custom-prompt.cc +++ b/custom-prompt/custom-prompt.cc @@ -181,7 +181,7 @@ class GitRepository std::filesystem::path gitdir; C::git_reference* ref; C::git_oid const* oid; - std::string description; + std::string description, tag; bool bare, detached; std::string state; bool dirty, staged, untracked; @@ -192,11 +192,12 @@ class GitRepository private: void establish_description(void); + void establish_tag(void); void establish_state(void); void establish_dirty_staged_untracked(void); // These are static methods because otherwise, their signatures do not // match the required signatures for use as callback functions. - static int update_description(char const* name, C::git_oid* oid, void* self_); + static int update_tag(char const* name, C::git_oid* oid, void* self_); static int update_dirty_staged_untracked(char const* path, unsigned status_flags, void* self_); }; @@ -217,6 +218,7 @@ GitRepository::GitRepository(void) : } this->gitdir = C::git_repository_path(this->repo); this->establish_description(); + this->establish_tag(); this->bare = C::git_repository_is_bare(this->repo); this->detached = C::git_repository_head_detached(this->repo); this->establish_state(); @@ -226,13 +228,19 @@ GitRepository::GitRepository(void) : /****************************************************************************** * Obtain a human-readable description of the working tree of the current Git * repository. This shall be the name of the current branch if it is available. - * Otherwise, it shall be the hash of the most recent commit (and possibly its - * tag). + * Otherwise, it shall be the hash of the most recent commit. *****************************************************************************/ void GitRepository::establish_description(void) { if (C::git_repository_head(&this->ref, this->repo) == 0) { + // According to the documentation, this retrieves the OID only if the + // reference is direct. However, I observed that it does so even if the + // reference is symbolic (i.e. we are on a branch). There is no harm in + // leaving it here because if it fails, it will just return a null + // pointer. + this->oid = C::git_reference_target(this->ref); + char const* branch_name; if (C::git_branch_name(&branch_name, this->ref) == 0) { @@ -240,18 +248,15 @@ void GitRepository::establish_description(void) return; }; - // If not on a branch, use the commit hash and the tag, if there is - // one. Unannotated tags cannot be looked up, so the only way to check - // is to iterate over all tags. - this->oid = C::git_reference_target(this->ref); + // We are not on a branch. The reference must be direct. Use the commit + // hash. this->description = C::git_oid_tostr_s(this->oid); this->description.erase(7); - C::git_tag_foreach(this->repo, this->update_description, this); return; } - // If we are here, we must be on a branch with no commits. Obtain the - // required information manually. + // We must be on a branch with no commits. Obtain the required information + // manually. std::ifstream head_file(this->gitdir / "HEAD"); if (!head_file.good()) { @@ -264,6 +269,19 @@ void GitRepository::establish_description(void) } } +/****************************************************************************** + * Obtain the tag of the working tree of the current Git repository (if there + * is one). + *****************************************************************************/ +void GitRepository::establish_tag(void) +{ + if (this->oid == nullptr) + { + return; + } + C::git_tag_foreach(this->repo, this->update_tag, this); +} + /****************************************************************************** * Obtain the state of the working tree of the current Git repository. This * shall be the name of the operation currently in progress (if any). @@ -307,8 +325,8 @@ void GitRepository::establish_dirty_staged_untracked(void) /****************************************************************************** * Check whether the given tag matches the reference of the given - * `GitRepository` instance. If it does, update the description of the latter - * with the tag name. + * `GitRepository` instance. If it does, update the corresponding member of the + * latter. * * @param name Tag name. * @param oid Tag object ID. @@ -316,19 +334,19 @@ void GitRepository::establish_dirty_staged_untracked(void) * * @return 1 if the tag matches the reference, 0 otherwise. *****************************************************************************/ -int GitRepository::update_description(char const* name, C::git_oid* oid, void* self_) +int GitRepository::update_tag(char const* name, C::git_oid* oid, void* self_) { GitRepository* self = static_cast(self_); if (C::git_oid_cmp(oid, self->oid) != 0) { return 0; } - std::string tag_name = name; - if (tag_name.rfind("refs/tags/", 0) == 0) + std::string tag = name; + if (tag.rfind("refs/tags/", 0) == 0) { - tag_name = tag_name.substr(10); + tag = tag.substr(10); } - self->description += " 󰓼 " + tag_name; + self->tag = tag; // Found a match. Stop iterating. return 1; } @@ -396,6 +414,10 @@ std::string GitRepository::get_information(void) { information_stream << D_GREEN << this->description << RESET; } + if (!this->tag.empty()) + { + information_stream << " 󰓼 " << this->tag; + } if (this->dirty || this->staged || this->untracked) { information_stream << ' '; From 440574f1f06b90926a3de551323824db64a08c02 Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Tue, 29 Oct 2024 22:47:23 +0530 Subject: [PATCH 23/34] Detect annotated and unannotated tags both --- custom-prompt/custom-prompt.cc | 61 ++++++++++++++++++++++++---------- 1 file changed, 43 insertions(+), 18 deletions(-) diff --git a/custom-prompt/custom-prompt.cc b/custom-prompt/custom-prompt.cc index db24d1a..a5f38f0 100644 --- a/custom-prompt/custom-prompt.cc +++ b/custom-prompt/custom-prompt.cc @@ -178,11 +178,11 @@ class GitRepository { private: C::git_repository* repo; + bool bare, detached; std::filesystem::path gitdir; C::git_reference* ref; C::git_oid const* oid; std::string description, tag; - bool bare, detached; std::string state; bool dirty, staged, untracked; @@ -205,7 +205,7 @@ class GitRepository * Read the current Git repository. *****************************************************************************/ GitRepository::GitRepository(void) : - repo(nullptr), ref(nullptr), oid(nullptr), bare(false), detached(false), dirty(false), staged(false), + repo(nullptr), bare(false), detached(false), ref(nullptr), oid(nullptr), dirty(false), staged(false), untracked(false) { if (C::git_libgit2_init() <= 0) @@ -216,11 +216,11 @@ GitRepository::GitRepository(void) : { return; } + this->bare = C::git_repository_is_bare(this->repo); + this->detached = C::git_repository_head_detached(this->repo); this->gitdir = C::git_repository_path(this->repo); this->establish_description(); this->establish_tag(); - this->bare = C::git_repository_is_bare(this->repo); - this->detached = C::git_repository_head_detached(this->repo); this->establish_state(); this->establish_dirty_staged_untracked(); } @@ -228,17 +228,17 @@ GitRepository::GitRepository(void) : /****************************************************************************** * Obtain a human-readable description of the working tree of the current Git * repository. This shall be the name of the current branch if it is available. - * Otherwise, it shall be the hash of the most recent commit. + * Otherwise, it shall be the object ID of the most recent commit. *****************************************************************************/ void GitRepository::establish_description(void) { if (C::git_repository_head(&this->ref, this->repo) == 0) { - // According to the documentation, this retrieves the OID only if the - // reference is direct. However, I observed that it does so even if the - // reference is symbolic (i.e. we are on a branch). There is no harm in - // leaving it here because if it fails, it will just return a null - // pointer. + // According to the documentation, this retrieves the reference object + // ID only if the reference is direct. However, I observed that it does + // so even if the reference is symbolic (i.e. if we are on a branch). + // There is no harm in leaving it here because if it fails, it will + // just return a null pointer. this->oid = C::git_reference_target(this->ref); char const* branch_name; @@ -249,7 +249,7 @@ void GitRepository::establish_description(void) }; // We are not on a branch. The reference must be direct. Use the commit - // hash. + // object ID. this->description = C::git_oid_tostr_s(this->oid); this->description.erase(7); return; @@ -275,10 +275,16 @@ void GitRepository::establish_description(void) *****************************************************************************/ void GitRepository::establish_tag(void) { - if (this->oid == nullptr) + LOG_DEBUG("%d %s", this->detached, C::git_oid_tostr_s(this->oid)); + // If a tag or a tagged commit is not checked out (which is the case if we + // are on a branch), don't search. (This makes the common case fast.) If + // the most recent commit is not available, there is nothing to search + // anyway. + if (!this->detached || this->oid == nullptr) { return; } + LOG_DEBUG("searching"); C::git_tag_foreach(this->repo, this->update_tag, this); } @@ -330,23 +336,42 @@ void GitRepository::establish_dirty_staged_untracked(void) * * @param name Tag name. * @param oid Tag object ID. - * @param self_ `GitRepository` instance whose description should be updated. + * @param self_ `GitRepository` instance whose member should be updated. * * @return 1 if the tag matches the reference, 0 otherwise. *****************************************************************************/ int GitRepository::update_tag(char const* name, C::git_oid* oid, void* self_) { GitRepository* self = static_cast(self_); + + // Compare the object ID of the tag with the object ID of the reference. if (C::git_oid_cmp(oid, self->oid) != 0) { - return 0; + C::git_tag* tag; + if (C::git_tag_lookup(&tag, self->repo, oid) != 0) + { + // This is an unannotated tag, meaning that its object ID is the + // same as the object ID of the corresponding commit. The latter + // does not match the object ID of the reference. + return 0; + } + + // This is an annotated tag, meaning that its object ID is different + // from the object ID of the corresponding commit. Find the latter and + // compare it with the object ID of the reference. + C::git_oid const* oid = C::git_tag_target_id(tag); + if (C::git_oid_cmp(oid, self->oid) != 0) + { + // The latter does not match the object ID of the reference. + return 0; + } } - std::string tag = name; - if (tag.rfind("refs/tags/", 0) == 0) + + self->tag = name; + if (self->tag.rfind("refs/tags/", 0) == 0) { - tag = tag.substr(10); + self->tag.erase(0, 10); } - self->tag = tag; // Found a match. Stop iterating. return 1; } From 7ee0bc5ffb39b4f92cdfabacac0470811ac1f587 Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Tue, 29 Oct 2024 23:15:15 +0530 Subject: [PATCH 24/34] Bit-fiddling to set dirty, staged and untracked statuses --- custom-prompt/Makefile | 4 ++-- custom-prompt/custom-prompt.cc | 27 +++++++-------------------- 2 files changed, 9 insertions(+), 22 deletions(-) diff --git a/custom-prompt/Makefile b/custom-prompt/Makefile index 725a818..3d958ba 100644 --- a/custom-prompt/Makefile +++ b/custom-prompt/Makefile @@ -1,7 +1,7 @@ CC = gcc CPPFLAGS = $(shell pkg-config --cflags libgit2) -CFLAGS = -fstrict-aliasing -std=c11 -Wall -Wextra -CXXFLAGS = -fstrict-aliasing -std=c++17 -Wall -Wextra +CFLAGS = -fstrict-aliasing -std=c11 -Wall -Wextra -Wno-unused-parameter +CXXFLAGS = -fstrict-aliasing -std=c++17 -Wall -Wextra -Wno-unused-parameter LDLIBS = -lstdc++ $(shell pkg-config --libs libgit2) MainSource = custom-prompt.cc diff --git a/custom-prompt/custom-prompt.cc b/custom-prompt/custom-prompt.cc index a5f38f0..773c62e 100644 --- a/custom-prompt/custom-prompt.cc +++ b/custom-prompt/custom-prompt.cc @@ -275,7 +275,6 @@ void GitRepository::establish_description(void) *****************************************************************************/ void GitRepository::establish_tag(void) { - LOG_DEBUG("%d %s", this->detached, C::git_oid_tostr_s(this->oid)); // If a tag or a tagged commit is not checked out (which is the case if we // are on a branch), don't search. (This makes the common case fast.) If // the most recent commit is not available, there is nothing to search @@ -284,7 +283,6 @@ void GitRepository::establish_tag(void) { return; } - LOG_DEBUG("searching"); C::git_tag_foreach(this->repo, this->update_tag, this); } @@ -319,7 +317,7 @@ void GitRepository::establish_state(void) } /****************************************************************************** - * Obtain the status of the index and working tree of the current Git + * Obtain the statuses of the index and working tree of the current Git * repository. *****************************************************************************/ void GitRepository::establish_dirty_staged_untracked(void) @@ -388,27 +386,16 @@ int GitRepository::update_tag(char const* name, C::git_oid* oid, void* self_) *****************************************************************************/ int GitRepository::update_dirty_staged_untracked(char const* _path, unsigned status_flags, void* self_) { - _path = _path; // Suppress unused parameter warning. GitRepository* self = static_cast(self_); - // The first two branches below are mutually exclusive. The third is not - // mutually exclusive with either of them. - if (status_flags + // The C++17 standard permits assigning integers to boolean variables. + self->dirty |= status_flags & (C::GIT_STATUS_WT_DELETED | C::GIT_STATUS_WT_MODIFIED | C::GIT_STATUS_WT_RENAMED - | C::GIT_STATUS_WT_TYPECHANGE)) - { - self->dirty = true; - } - else if (status_flags & C::GIT_STATUS_WT_NEW) - { - self->untracked = true; - } - if (status_flags + | C::GIT_STATUS_WT_TYPECHANGE); + self->staged |= status_flags & (C::GIT_STATUS_INDEX_DELETED | C::GIT_STATUS_INDEX_MODIFIED | C::GIT_STATUS_INDEX_NEW - | C::GIT_STATUS_INDEX_RENAMED | C::GIT_STATUS_INDEX_TYPECHANGE)) - { - self->staged = true; - } + | C::GIT_STATUS_INDEX_RENAMED | C::GIT_STATUS_INDEX_TYPECHANGE); + self->untracked |= status_flags & C::GIT_STATUS_WT_NEW; // Stop iterating if all possible statuses were found. return self->dirty && self->staged && self->untracked; From 11a0a93b7b22e36aca35cc3561cda0166af2d0ba Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Tue, 29 Oct 2024 23:16:32 +0530 Subject: [PATCH 25/34] Removed parameter names from method declarations --- custom-prompt/custom-prompt.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/custom-prompt/custom-prompt.cc b/custom-prompt/custom-prompt.cc index 773c62e..a5484ec 100644 --- a/custom-prompt/custom-prompt.cc +++ b/custom-prompt/custom-prompt.cc @@ -197,8 +197,8 @@ class GitRepository void establish_dirty_staged_untracked(void); // These are static methods because otherwise, their signatures do not // match the required signatures for use as callback functions. - static int update_tag(char const* name, C::git_oid* oid, void* self_); - static int update_dirty_staged_untracked(char const* path, unsigned status_flags, void* self_); + static int update_tag(char const*, C::git_oid*, void*); + static int update_dirty_staged_untracked(char const*, unsigned, void*); }; /****************************************************************************** From c1bd247aa0e57f4f57c33971536568ef66e78227 Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Wed, 30 Oct 2024 21:52:04 +0530 Subject: [PATCH 26/34] Updated documentation --- custom-prompt/custom-prompt.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/custom-prompt/custom-prompt.cc b/custom-prompt/custom-prompt.cc index a5484ec..10804b6 100644 --- a/custom-prompt/custom-prompt.cc +++ b/custom-prompt/custom-prompt.cc @@ -228,7 +228,7 @@ GitRepository::GitRepository(void) : /****************************************************************************** * Obtain a human-readable description of the working tree of the current Git * repository. This shall be the name of the current branch if it is available. - * Otherwise, it shall be the object ID of the most recent commit. + * Otherwise, it shall be the hash of the most recent commit. *****************************************************************************/ void GitRepository::establish_description(void) { @@ -249,7 +249,7 @@ void GitRepository::establish_description(void) }; // We are not on a branch. The reference must be direct. Use the commit - // object ID. + // hash. this->description = C::git_oid_tostr_s(this->oid); this->description.erase(7); return; From 82fd1681dc8e368f64dbd5f60af4b17937e4f05a Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Wed, 30 Oct 2024 22:07:10 +0530 Subject: [PATCH 27/34] Added Windows workflow to build libgit2 statically --- .github/workflows/package.yml | 127 +++++++++++++++++++--------------- 1 file changed, 71 insertions(+), 56 deletions(-) diff --git a/.github/workflows/package.yml b/.github/workflows/package.yml index e55ef2a..d0057f0 100644 --- a/.github/workflows/package.yml +++ b/.github/workflows/package.yml @@ -6,64 +6,79 @@ on: - 'custom-prompt/*' workflow_dispatch: +defaults: + run: + shell: bash + jobs: - build_macos_windows: - name: build on ${{ matrix.os.name }} - runs-on: ${{ matrix.os.name }} - strategy: - matrix: - os: [{name: 'macos-13', id: 'amd64-macos'}, {name: 'macos-14', id: 'aarch64-macos'}, {name: 'windows-2022', id: 'amd64-windows'}] + build_windows: + runs-on: windows-2022 steps: - uses: actions/checkout@v4 - - run: make -j release - working-directory: custom-prompt - - uses: actions/upload-artifact@v3 - with: - name: custom-prompt-${{ matrix.os.id }} - path: 'custom-prompt/bin' + - run: | + gh repo clone https://github.com/libgit2/libgit2.git + mkdir -p libgit2/build && cd libgit2/build + cmake .. -DBUILD_SHARED_LIBS=OFF + cmake --build . + ls -Al - build_linux: - name: build on ${{ matrix.arch }}/${{ matrix.os.name }}:${{ matrix.os.tag }} - runs-on: ubuntu-22.04 - container: ${{ matrix.arch }}/${{ matrix.os.name }}:${{ matrix.os.tag }} - strategy: - matrix: - arch: [amd64, i386] - os: [{name: 'alpine', tag: '3.20', libc: 'musl'}, {name: 'debian', tag: '12', libc: 'gnu'}] - steps: - - if: matrix.os.name == 'alpine' - run: apk add build-base libnotify-dev libx11-dev - - if: matrix.os.name == 'debian' - run: apt-get update && apt-get install -y build-essential libnotify-dev libx11-dev - - uses: actions/checkout@v1 - - run: make -j release - working-directory: custom-prompt - - uses: actions/upload-artifact@v1 - with: - name: custom-prompt-${{ matrix.arch }}-linux-${{ matrix.os.libc }} - path: 'custom-prompt/bin' + # build_macos_windows: + # name: build on ${{ matrix.os.name }} + # runs-on: ${{ matrix.os.name }} + # strategy: + # matrix: + # os: [{name: 'macos-13', id: 'amd64-macos'}, {name: 'macos-14', id: 'aarch64-macos'}, {name: 'windows-2022', id: 'amd64-windows'}] + # steps: + # - uses: actions/checkout@v4 + # - run: make -j release + # working-directory: custom-prompt + # - uses: actions/upload-artifact@v3 + # with: + # name: custom-prompt-${{ matrix.os.id }} + # path: 'custom-prompt/bin' - release: - if: github.ref_type == 'tag' - needs: [build_macos_windows, build_linux] - runs-on: ubuntu-22.04 - permissions: write-all - steps: - - uses: actions/checkout@v4 - - uses: actions/download-artifact@v3 - - run: | - chmod --recursive +x . - for package_directory in custom-prompt-* - do - ( - cd $package_directory - tar cfvz ${package_directory}.tgz * - ) - done - name: Create compressed archives of executable binaries - - run: | - gh release create ${{ github.ref_name }} -t ${{ github.ref_name }} --generate-notes - gh release upload ${{ github.ref_name }} */*.tgz - name: Publish release - env: - GH_TOKEN: ${{ github.token }} + # build_linux: + # name: build on ${{ matrix.arch }}/${{ matrix.os.name }}:${{ matrix.os.tag }} + # runs-on: ubuntu-22.04 + # container: ${{ matrix.arch }}/${{ matrix.os.name }}:${{ matrix.os.tag }} + # strategy: + # matrix: + # arch: [amd64, i386] + # os: [{name: 'alpine', tag: '3.20', libc: 'musl'}, {name: 'debian', tag: '12', libc: 'gnu'}] + # steps: + # - if: matrix.os.name == 'alpine' + # run: apk add build-base libnotify-dev libx11-dev + # - if: matrix.os.name == 'debian' + # run: apt-get update && apt-get install -y build-essential libnotify-dev libx11-dev + # - uses: actions/checkout@v1 + # - run: make -j release + # working-directory: custom-prompt + # - uses: actions/upload-artifact@v1 + # with: + # name: custom-prompt-${{ matrix.arch }}-linux-${{ matrix.os.libc }} + # path: 'custom-prompt/bin' + + # release: + # if: github.ref_type == 'tag' + # needs: [build_macos_windows, build_linux] + # runs-on: ubuntu-22.04 + # permissions: write-all + # steps: + # - uses: actions/checkout@v4 + # - uses: actions/download-artifact@v3 + # - run: | + # chmod --recursive +x . + # for package_directory in custom-prompt-* + # do + # ( + # cd $package_directory + # tar cfvz ${package_directory}.tgz * + # ) + # done + # name: Create compressed archives of executable binaries + # - run: | + # gh release create ${{ github.ref_name }} -t ${{ github.ref_name }} --generate-notes + # gh release upload ${{ github.ref_name }} */*.tgz + # name: Publish release + # env: + # GH_TOKEN: ${{ github.token }} From e6a4325507b5a08fae1a640fcd0fe27b9bcd8c87 Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Wed, 30 Oct 2024 22:09:07 +0530 Subject: [PATCH 28/34] Use Git instead of GitHub CLI, which requires a token --- .github/workflows/package.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/package.yml b/.github/workflows/package.yml index d0057f0..964e53b 100644 --- a/.github/workflows/package.yml +++ b/.github/workflows/package.yml @@ -16,7 +16,7 @@ jobs: steps: - uses: actions/checkout@v4 - run: | - gh repo clone https://github.com/libgit2/libgit2.git + git clone https://github.com/libgit2/libgit2.git mkdir -p libgit2/build && cd libgit2/build cmake .. -DBUILD_SHARED_LIBS=OFF cmake --build . From 783ba6d597f3399afb09e8d1baca79d41b98ba52 Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Wed, 30 Oct 2024 22:22:59 +0530 Subject: [PATCH 29/34] Install to target --- .github/workflows/package.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/package.yml b/.github/workflows/package.yml index 964e53b..c7da420 100644 --- a/.github/workflows/package.yml +++ b/.github/workflows/package.yml @@ -17,10 +17,11 @@ jobs: - uses: actions/checkout@v4 - run: | git clone https://github.com/libgit2/libgit2.git - mkdir -p libgit2/build && cd libgit2/build - cmake .. -DBUILD_SHARED_LIBS=OFF - cmake --build . - ls -Al + mkdir -p libgit2/build libgit2/target && cd libgit2/build + cmake .. -DCMAKE_INSTALL_PREFIX=$PWD/../target -DBUILD_CLI=OFF -DBUILD_SHARED_LIBS=OFF -DBUILD_TESTS=OFF + cmake --build . --target install + find $PWD/../target + make -j release # build_macos_windows: # name: build on ${{ matrix.os.name }} From e339c644e9ca37f307ff9043b0a949eec880e2ba Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Thu, 31 Oct 2024 00:41:08 +0530 Subject: [PATCH 30/34] Fixed `make` command --- .github/workflows/package.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/package.yml b/.github/workflows/package.yml index c7da420..7c9d5b6 100644 --- a/.github/workflows/package.yml +++ b/.github/workflows/package.yml @@ -18,10 +18,11 @@ jobs: - run: | git clone https://github.com/libgit2/libgit2.git mkdir -p libgit2/build libgit2/target && cd libgit2/build - cmake .. -DCMAKE_INSTALL_PREFIX=$PWD/../target -DBUILD_CLI=OFF -DBUILD_SHARED_LIBS=OFF -DBUILD_TESTS=OFF + cmake .. -DBUILD_CLI=OFF -DBUILD_SHARED_LIBS=OFF -DBUILD_TESTS=OFF cmake --build . --target install find $PWD/../target - make -j release + - run: make -j release + working-directory: custom-prompt # build_macos_windows: # name: build on ${{ matrix.os.name }} From 93e4ab05c8df15cdcdeec31832be5ee71c200382 Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Thu, 31 Oct 2024 00:46:30 +0530 Subject: [PATCH 31/34] Windows has `mkdir` --- .github/workflows/package.yml | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/.github/workflows/package.yml b/.github/workflows/package.yml index 7c9d5b6..e73e416 100644 --- a/.github/workflows/package.yml +++ b/.github/workflows/package.yml @@ -6,10 +6,6 @@ on: - 'custom-prompt/*' workflow_dispatch: -defaults: - run: - shell: bash - jobs: build_windows: runs-on: windows-2022 @@ -17,10 +13,10 @@ jobs: - uses: actions/checkout@v4 - run: | git clone https://github.com/libgit2/libgit2.git - mkdir -p libgit2/build libgit2/target && cd libgit2/build + mkdir libgit2/build + cd libgit2/build cmake .. -DBUILD_CLI=OFF -DBUILD_SHARED_LIBS=OFF -DBUILD_TESTS=OFF cmake --build . --target install - find $PWD/../target - run: make -j release working-directory: custom-prompt From 9788817542333303d686a281fb402dd0f5b23a15 Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Thu, 31 Oct 2024 00:47:37 +0530 Subject: [PATCH 32/34] Install pkg-onfig --- .github/workflows/package.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/package.yml b/.github/workflows/package.yml index e73e416..47e9d6b 100644 --- a/.github/workflows/package.yml +++ b/.github/workflows/package.yml @@ -17,6 +17,7 @@ jobs: cd libgit2/build cmake .. -DBUILD_CLI=OFF -DBUILD_SHARED_LIBS=OFF -DBUILD_TESTS=OFF cmake --build . --target install + choco install pkgconfiglite - run: make -j release working-directory: custom-prompt From 27cbf0a3fa70a68819ff7f15868f1c2e27f6b101 Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Thu, 31 Oct 2024 00:57:27 +0530 Subject: [PATCH 33/34] Removed package workflow --- .github/workflows/package.yml | 83 ----------------------------------- 1 file changed, 83 deletions(-) delete mode 100644 .github/workflows/package.yml diff --git a/.github/workflows/package.yml b/.github/workflows/package.yml deleted file mode 100644 index 47e9d6b..0000000 --- a/.github/workflows/package.yml +++ /dev/null @@ -1,83 +0,0 @@ -name: package -on: - push: - paths: - - '.github/workflows/package.yml' - - 'custom-prompt/*' - workflow_dispatch: - -jobs: - build_windows: - runs-on: windows-2022 - steps: - - uses: actions/checkout@v4 - - run: | - git clone https://github.com/libgit2/libgit2.git - mkdir libgit2/build - cd libgit2/build - cmake .. -DBUILD_CLI=OFF -DBUILD_SHARED_LIBS=OFF -DBUILD_TESTS=OFF - cmake --build . --target install - choco install pkgconfiglite - - run: make -j release - working-directory: custom-prompt - - # build_macos_windows: - # name: build on ${{ matrix.os.name }} - # runs-on: ${{ matrix.os.name }} - # strategy: - # matrix: - # os: [{name: 'macos-13', id: 'amd64-macos'}, {name: 'macos-14', id: 'aarch64-macos'}, {name: 'windows-2022', id: 'amd64-windows'}] - # steps: - # - uses: actions/checkout@v4 - # - run: make -j release - # working-directory: custom-prompt - # - uses: actions/upload-artifact@v3 - # with: - # name: custom-prompt-${{ matrix.os.id }} - # path: 'custom-prompt/bin' - - # build_linux: - # name: build on ${{ matrix.arch }}/${{ matrix.os.name }}:${{ matrix.os.tag }} - # runs-on: ubuntu-22.04 - # container: ${{ matrix.arch }}/${{ matrix.os.name }}:${{ matrix.os.tag }} - # strategy: - # matrix: - # arch: [amd64, i386] - # os: [{name: 'alpine', tag: '3.20', libc: 'musl'}, {name: 'debian', tag: '12', libc: 'gnu'}] - # steps: - # - if: matrix.os.name == 'alpine' - # run: apk add build-base libnotify-dev libx11-dev - # - if: matrix.os.name == 'debian' - # run: apt-get update && apt-get install -y build-essential libnotify-dev libx11-dev - # - uses: actions/checkout@v1 - # - run: make -j release - # working-directory: custom-prompt - # - uses: actions/upload-artifact@v1 - # with: - # name: custom-prompt-${{ matrix.arch }}-linux-${{ matrix.os.libc }} - # path: 'custom-prompt/bin' - - # release: - # if: github.ref_type == 'tag' - # needs: [build_macos_windows, build_linux] - # runs-on: ubuntu-22.04 - # permissions: write-all - # steps: - # - uses: actions/checkout@v4 - # - uses: actions/download-artifact@v3 - # - run: | - # chmod --recursive +x . - # for package_directory in custom-prompt-* - # do - # ( - # cd $package_directory - # tar cfvz ${package_directory}.tgz * - # ) - # done - # name: Create compressed archives of executable binaries - # - run: | - # gh release create ${{ github.ref_name }} -t ${{ github.ref_name }} --generate-notes - # gh release upload ${{ github.ref_name }} */*.tgz - # name: Publish release - # env: - # GH_TOKEN: ${{ github.token }} From 5719a2810e695c2a6ad678551b03c6da707da778 Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Thu, 31 Oct 2024 01:06:17 +0530 Subject: [PATCH 34/34] Removed code to load `__git_ps1` in Bash and Zsh --- .bashrc | 7 ------- .zshrc | 9 --------- 2 files changed, 16 deletions(-) diff --git a/.bashrc b/.bashrc index 26a33cc..7b26f80 100644 --- a/.bashrc +++ b/.bashrc @@ -114,13 +114,6 @@ then _source_one /usr/share/bash-completion/bash_completion /etc/bash_completion fi -# Showing the Git branch in the primary prompt depends upon a script which must -# be sourced separately on some Linux distributions. -if ! command -v __git_ps1 &>/dev/null -then - _source_one $HOME/Documents/projects/git/contrib/completion/git-prompt.sh /usr/share/git/completion/git-prompt.sh /usr/share/git-core/contrib/completion/git-prompt.sh -fi - PS1='[\u@\h \w]\$ ' PS2='──▶ ' PS3='#? ' diff --git a/.zshrc b/.zshrc index a9bc111..57e3f0b 100644 --- a/.zshrc +++ b/.zshrc @@ -75,15 +75,6 @@ rr() done } -if ! command -v __git_ps1 &>/dev/null -then - . ~/Documents/projects/git/contrib/completion/git-prompt.sh &>/dev/null \ - || . /usr/lib/git-core/git-sh-prompt &>/dev/null \ - || . /usr/share/git-core/contrib/completion/git-prompt.sh &>/dev/null \ - || . /usr/share/git/completion/git-prompt.sh &>/dev/null \ - || . /usr/share/git/git-prompt.sh &>/dev/null -fi - ############################################################################### # Shell options. ###############################################################################