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