Line data Source code
1 : /*! 2 : * \file esys/repo/libgit2/notes_libgit2.cpp. 3 : * \brief 4 : * 5 : * \cond 6 : * __legal_b__ 7 : * 8 : * Copyright (c) 2023 Michel Gillet 9 : * Distributed under the MIT License. 10 : * (See accompanying file LICENSE.txt or 11 : * copy at https://opensource.org/licenses/MIT) 12 : * 13 : * __legal_e__ 14 : * \endcond 15 : * 16 : */ 17 : 18 : #include "esys/repo/esysrepo_prec.h" 19 : #include "esys/repo/libgit2/notes.h" 20 : #include "esys/repo/libgit2/gitimpl.h" 21 : #include "esys/repo/libgit2/git.h" 22 : 23 : namespace esys::repo::libgit2 24 : { 25 : 26 203 : Notes::Notes(Git *git) 27 203 : : m_git(git) 28 : { 29 203 : } 30 : 31 6 : Git *Notes::get_git() 32 : { 33 6 : return m_git; 34 : } 35 : 36 22 : GitImpl *Notes::get_git_impl() 37 : { 38 22 : return m_git->get_impl(); 39 : } 40 : 41 6 : Result Notes::load_all() 42 : { 43 6 : if (is_loaded()) return ESYSREPO_RESULT(ResultCode::OK); 44 : 45 6 : Result result; 46 : 47 13 : for (auto const &ref : get_git()->get_notes_references()) 48 : { 49 7 : result = load(ref); 50 7 : if (result.error()) return ESYSREPO_RESULT(result); 51 : } 52 : 53 6 : set_loaded(true); 54 : 55 6 : return ESYSREPO_RESULT(ResultCode::OK); 56 6 : } 57 : 58 7 : Result Notes::load(const std::string &ref) 59 : { 60 7 : Guard<git_iterator> it; 61 7 : std::string the_ref = GitImpl::normalize_notes_ref(ref); 62 : 63 7 : auto result_int = git_note_iterator_new(it.get_p(), get_git_impl()->get_repo(), the_ref.c_str()); 64 7 : if (result_int != 0) 65 : { 66 : // It would seem that this error means there are no notes to iterate over 67 1 : if (result_int == GIT_ENOTFOUND) return ESYSREPO_RESULT(ResultCode::OK); 68 0 : return ESYSREPO_RESULT(ResultCode::GIT_RAW_INT_ERROR, result_int); 69 : } 70 : 71 6 : git_oid note_id; 72 6 : git_oid annotated_id; 73 6 : auto ref_map_notes_it = m_ref_map_notes.find(ref); 74 : 75 6 : if (ref_map_notes_it != m_ref_map_notes.end()) return ESYSREPO_RESULT(ResultCode::GENERIC_ERROR); 76 : 77 6 : auto ref_map_notes = std::make_shared<RefMapNotesItem>(); 78 6 : ref_map_notes->m_ref = ref; 79 : 80 6 : m_ref_map_notes[ref] = ref_map_notes; 81 : 82 11 : do 83 : { 84 11 : result_int = git_note_next(¬e_id, &annotated_id, it.get()); 85 21 : if (result_int == 0) add_note(ref_map_notes, note_id, annotated_id); 86 11 : } while (result_int == 0); 87 : 88 6 : if (result_int == GIT_ITEROVER) return ESYSREPO_RESULT(ResultCode::OK); 89 0 : return ESYSREPO_RESULT(ResultCode::GIT_RAW_INT_ERROR, result_int); 90 7 : } 91 : 92 0 : Notes::OIDCommitMapNoteItem::OIDCommitMapNoteItem() = default; 93 : 94 5 : Notes::OIDCommitMapNoteItem::OIDCommitMapNoteItem(Notes *notes, const git_oid ¬e_oid, const git_oid &comment_oid, 95 5 : RefMapNotesItem *ref_map) 96 5 : : m_notes(notes) 97 5 : , m_note_oid(note_oid) 98 5 : , m_comment_oid(comment_oid) 99 5 : , m_ref_map(ref_map) 100 : { 101 5 : } 102 : 103 5 : std::shared_ptr<git::Note> Notes::OIDCommitMapNoteItem::get_note() 104 : { 105 5 : if (m_note != nullptr) return m_note; 106 : 107 5 : Guard<git_note> note_obj; 108 : 109 5 : if (m_ref.empty()) m_ref = GitImpl::normalize_notes_ref(m_ref_map->m_ref); 110 : 111 5 : auto result_int = 112 5 : git_note_read(note_obj.get_p(), m_notes->get_git_impl()->get_repo(), m_ref.c_str(), &m_comment_oid); 113 10 : if (result_int != 0) return nullptr; 114 : 115 5 : m_note = std::make_shared<git::Note>(); 116 5 : auto message = git_note_message(note_obj.get()); 117 10 : if (message != nullptr) m_note->set_message(message); 118 : 119 5 : m_note->set_reference(m_ref_map->m_ref); 120 : 121 5 : auto author = git_note_author(note_obj.get()); 122 5 : Result result = m_notes->get_git_impl()->get_signature(author, m_note->get_author()); 123 5 : if (result.error()) return nullptr; 124 : 125 5 : auto committer = git_note_committer(note_obj.get()); 126 5 : result = m_notes->get_git_impl()->get_signature(author, m_note->get_committer()); 127 5 : if (result.error()) return nullptr; 128 : 129 5 : return m_note; 130 10 : } 131 : 132 10 : bool Comparegit_oid::operator()(const git_oid &lhs, const git_oid &rhs) const 133 : { 134 210 : for (int idx = 0; idx < GIT_OID_RAWSZ; ++idx) 135 : { 136 200 : if (lhs.id[idx] < rhs.id[idx]) return true; 137 : } 138 : return false; 139 : } 140 : 141 5 : void Notes::add_note(std::shared_ptr<RefMapNotesItem> map, const git_oid ¬e_oid, const git_oid &commit_oid) 142 : { 143 5 : OIDCommitMapNoteItem item(this, note_oid, commit_oid, map.get()); 144 : 145 5 : std::shared_ptr<OIDCommitMapNoteVec> oid_map_notes_vec; 146 : 147 5 : auto oid_map_notes_it = m_oid_map_notes.find(commit_oid); 148 5 : if (oid_map_notes_it == m_oid_map_notes.end()) 149 : { 150 8 : oid_map_notes_vec = std::make_shared<OIDCommitMapNoteVec>(); 151 4 : m_oid_map_notes[commit_oid] = oid_map_notes_vec; 152 : } 153 : else 154 1 : oid_map_notes_vec = oid_map_notes_it->second; 155 5 : oid_map_notes_vec->push_back(item); 156 : 157 5 : std::shared_ptr<OIDCommitMapNoteVec> iod_commit_map_note_vec; 158 5 : auto iod_commit_map_note_it = map->m_iod_commit_map_note.find(commit_oid); 159 5 : if (iod_commit_map_note_it == map->m_iod_commit_map_note.end()) 160 : { 161 10 : iod_commit_map_note_vec = std::make_shared<OIDCommitMapNoteVec>(); 162 5 : map->m_iod_commit_map_note[commit_oid] = iod_commit_map_note_vec; 163 : } 164 : else 165 0 : iod_commit_map_note_vec = iod_commit_map_note_it->second; 166 : 167 5 : iod_commit_map_note_vec->push_back(item); 168 10 : } 169 : 170 6 : Result Notes::get_note(const git_oid ¬e_oid, std::vector<std::shared_ptr<git::Note>> ¬es) const 171 : { 172 6 : notes.clear(); 173 : 174 6 : auto it = m_oid_map_notes.find(note_oid); 175 6 : if (it == m_oid_map_notes.end()) return ESYSREPO_RESULT(ResultCode::OK); 176 : 177 4 : auto vec = it->second; 178 : 179 4 : if (vec == nullptr) return ESYSREPO_RESULT(ResultCode::OK); 180 : 181 9 : for (auto &item : *vec.get()) 182 : { 183 5 : auto note = item.get_note(); 184 5 : if (note == nullptr) return ESYSREPO_RESULT(ResultCode::INTERNAL_ERROR); 185 5 : notes.push_back(note); 186 5 : } 187 : 188 4 : return ESYSREPO_RESULT(ResultCode::OK); 189 6 : } 190 : 191 6 : bool Notes::is_loaded() const 192 : { 193 6 : return m_loaded; 194 : } 195 : 196 14 : void Notes::set_loaded(bool loaded) 197 : { 198 14 : m_loaded = loaded; 199 14 : } 200 : 201 8 : void Notes::clear() 202 : { 203 8 : m_ref_map_notes.clear(); 204 8 : m_oid_map_notes.clear(); 205 8 : set_loaded(false); 206 8 : } 207 : 208 : } // namespace esys::repo::libgit2