Line data Source code
1 : /*! 2 : * \file esys/repo/exe/cmdstatus.cpp 3 : * \brief 4 : * 5 : * \cond 6 : * __legal_b__ 7 : * 8 : * Copyright (c) 2020-2021 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/exe/cmdstatus.h" 20 : #include "esys/repo/manifest/repository.h" 21 : #include "esys/repo/githelper.h" 22 : 23 : #include <termcolor/termcolor.hpp> 24 : 25 : #include <boost/filesystem.hpp> 26 : 27 : #include <sstream> 28 : #include <iomanip> 29 : 30 : namespace esys::repo::exe 31 : { 32 : 33 18 : CmdStatus::CmdStatus() 34 36 : : Cmd("Status") 35 : { 36 18 : } 37 : 38 21 : CmdStatus::~CmdStatus() = default; 39 : 40 0 : void CmdStatus::set_quiet(bool quiet) 41 : { 42 0 : m_quiet = quiet; 43 0 : } 44 : 45 3 : bool CmdStatus::get_quiet() const 46 : { 47 3 : return m_quiet; 48 : } 49 : 50 3 : Result CmdStatus::impl_run() 51 : { 52 3 : if (get_quiet()) warn("The option --quiet is not implemented yet"); 53 : 54 3 : Result result = process_sub_args_to_find_parent_path(); 55 3 : if (result.error()) 56 : { 57 0 : std::string err_str = "No ESysRepo folder found"; 58 0 : error(err_str); 59 0 : return ESYSREPO_RESULT(result, ResultCode::CMD_NO_ESYSREPO_FOLDER_FOUND, err_str); 60 0 : } 61 : 62 3 : result = open_esysrepo_folder(); 63 3 : if (result.error()) return ESYSREPO_RESULT(result); 64 : 65 3 : result = load_manifest(); 66 3 : if (result.error()) return ESYSREPO_RESULT(result); 67 : 68 3 : result = process_sub_args_as_git_repo_paths(); 69 3 : if (result.error()) return ESYSREPO_RESULT(result); 70 : 71 3 : std::map<std::string, int> map_input_repo_paths; 72 : 73 3 : if (get_input_git_repo_paths().size() != 0) 74 : { 75 0 : for (auto &path : get_input_git_repo_paths()) 76 : { 77 0 : auto repo = get_manifest()->find_repo_by_path(path); 78 0 : if (repo != nullptr) map_input_repo_paths[path] = 1; 79 0 : } 80 : } 81 : 82 3 : Result rresult; 83 : 84 12 : for (auto location : get_manifest()->get_locations()) 85 : { 86 36 : for (auto repo : location->get_repos()) 87 : { 88 30 : if (map_input_repo_paths.size() != 0) 89 : { 90 0 : if (map_input_repo_paths.find(repo->get_path()) == map_input_repo_paths.end()) continue; 91 : } 92 60 : result = open_repo(repo); 93 30 : if (result.error()) 94 : { 95 0 : rresult.add(ESYSREPO_RESULT(result)); 96 0 : continue; 97 : } 98 90 : print_repo(repo); 99 30 : } 100 6 : } 101 : 102 6 : return ESYSREPO_RESULT(rresult); 103 6 : } 104 : 105 30 : Result CmdStatus::open_repo(std::shared_ptr<manifest::Repository> repo) 106 : { 107 30 : auto git_helper = new_git_helper(); 108 30 : git_helper->set_auto_close(); 109 : 110 30 : boost::filesystem::path rel_repo_path; 111 30 : boost::filesystem::path repo_path = get_config_folder()->get_workspace_path(); 112 30 : repo_path /= repo->get_path(); 113 90 : repo_path = boost::filesystem::absolute(repo_path).lexically_normal().make_preferred(); 114 60 : rel_repo_path = boost::filesystem::relative(repo_path); 115 : 116 30 : m_rel_repo_path = rel_repo_path.string(); 117 30 : m_repo_path = repo_path.string(); 118 : 119 30 : Result result = git_helper->open(repo_path.string(), log::Level::DEBUG); 120 30 : if (result.error()) return ESYSREPO_RESULT(result); 121 : 122 30 : m_repo_status = std::make_shared<git::RepoStatus>(); 123 : 124 30 : result = git_helper->get_status(*m_repo_status, log::Level::DEBUG); 125 30 : if (result.error()) return ESYSREPO_RESULT(result); 126 : 127 30 : m_repo_status->sort_file_status(); 128 : 129 30 : m_branches.clear(); 130 : 131 30 : result = git_helper->get_branches(m_branches, git::BranchType::LOCAL, log::Level::DEBUG); 132 30 : if (result.error()) return ESYSREPO_RESULT(result); 133 : 134 30 : m_branches.sort(); 135 : 136 30 : return ESYSREPO_RESULT(git_helper->close(log::Level::DEBUG)); 137 60 : } 138 : 139 30 : void CmdStatus::print_repo(std::shared_ptr<manifest::Repository> repo) 140 : { 141 30 : std::ostringstream oss; 142 30 : std::string first_part; 143 30 : std::string cur_branch; 144 : 145 30 : oss << termcolor::colorize; 146 : 147 30 : if (m_branches.size() != 0) 148 : { 149 30 : if (m_branches.get()[0]->get_is_head()) cur_branch = m_branches.get()[0]->get_name(); 150 : } 151 : 152 30 : if (m_repo_status->get_file_status().size() == 0) 153 : { 154 81 : std::string rev = get_manifest()->get_repo_revision(repo); 155 : 156 27 : auto index = rev.find("refs/heads/"); 157 27 : if (index != rev.npos) rev = rev.substr(index + std::strlen("refs/heads/")); 158 : 159 27 : if (rev == cur_branch) return; 160 27 : } 161 : 162 3 : first_part = "Repository : " + repo->get_path(); 163 3 : oss << std::setw(get_start_print_branch()) << std::setfill(' ') << std::left << first_part; 164 : 165 3 : if (!cur_branch.empty()) oss << cur_branch; 166 : 167 7 : for (auto file_status : m_repo_status->get_file_status()) 168 : { 169 4 : oss << std::endl; 170 12 : print(oss, file_status); 171 4 : } 172 : 173 6 : info(oss.str()); 174 30 : } 175 : 176 4 : void CmdStatus::print(std::ostream &os, std::shared_ptr<git::FileStatus> file_status) 177 : { 178 12 : os << get_file_status_header(file_status); 179 4 : os << " "; 180 4 : if (get_show_file_permission()) 181 : { 182 4 : bool executable = false; 183 8 : if (file_status->get_index_to_work_dir() != nullptr) 184 4 : executable = (file_status->get_index_to_work_dir()->get_diff_delta().get_old_file().get_mode() 185 : == git::FileMode::BLOB_EXECUTABLE); 186 4 : if (executable) 187 0 : os << termcolor::red << "x "; 188 : else 189 4 : os << "- "; 190 : } 191 : else 192 0 : os << " "; 193 : 194 4 : os << file_status->get_old_name() << termcolor::reset; 195 4 : } 196 : 197 4 : std::string CmdStatus::get_file_status_header(std::shared_ptr<git::FileStatus> file_status) 198 : { 199 4 : std::string result = "--"; 200 4 : std::shared_ptr<git::Status> status; 201 : 202 8 : for (auto status : file_status->get_status()) 203 : { 204 4 : switch (status->get_type()) 205 : { 206 0 : case git::StatusType::CURRENT: result = "--"; break; 207 0 : case git::StatusType::INDEX: 208 0 : switch (status->get_sub_type()) 209 : { 210 0 : case git::StatusSubType::DELETED: result[0] = 'D'; break; 211 0 : case git::StatusSubType::MODIFIED: result[0] = 'M'; break; 212 0 : case git::StatusSubType::NEW: result[0] = 'A'; break; 213 0 : case git::StatusSubType::RENAMED: result[0] = 'R'; break; 214 0 : case git::StatusSubType::TYPECHANGE: result[0] = 'T'; break; 215 : default:; 216 : } 217 : break; 218 4 : case git::StatusType::WORKING_DIR: 219 4 : switch (status->get_sub_type()) 220 : { 221 0 : case git::StatusSubType::MODIFIED: result[1] = 'm'; break; 222 0 : case git::StatusSubType::DELETED: result[1] = 'd'; break; 223 : default:; 224 : } 225 : break; 226 0 : case git::StatusType::CONFLICTED: result[0] = 'U'; break; 227 4 : default:; 228 : } 229 4 : } 230 : 231 4 : return result; 232 4 : } 233 0 : void CmdStatus::set_start_print_branch(std::size_t start_print_branch) 234 : { 235 0 : m_start_print_branch = start_print_branch; 236 0 : } 237 : 238 3 : std::size_t CmdStatus::get_start_print_branch() const 239 : { 240 3 : return m_start_print_branch; 241 : } 242 : 243 0 : void CmdStatus::set_show_file_permission(bool show_file_permission) 244 : { 245 0 : m_show_file_permission = show_file_permission; 246 0 : } 247 : 248 4 : bool CmdStatus::get_show_file_permission() const 249 : { 250 4 : return m_show_file_permission; 251 : } 252 : 253 3 : Result CmdStatus::process_sub_args_to_find_parent_path() 254 : { 255 3 : if (!get_workspace_path().empty()) return ESYSREPO_RESULT(ResultCode::OK); 256 : 257 2 : if ((get_sub_args().size() == 0) || (!get_folder().empty()) || (!get_workspace_path().empty())) 258 2 : return ESYSREPO_RESULT(default_handling_folder_workspace()); 259 : 260 0 : std::string parent_path; 261 : 262 0 : for (auto &path : get_sub_args()) 263 : { 264 : // if (!boost::filesystem::exists(path)) continue; 265 0 : parent_path = Cmd::find_workspace_path(path); 266 0 : if (!parent_path.empty()) 267 : { 268 0 : set_workspace_path(parent_path); 269 0 : return ESYSREPO_RESULT(ResultCode::OK); 270 : } 271 : } 272 : 273 0 : parent_path = Cmd::find_workspace_path(); 274 0 : if (parent_path.empty()) return ESYSREPO_RESULT(ResultCode::CMD_WORKSPACE_PATH_IS_EMPTY); 275 : 276 0 : set_workspace_path(parent_path); 277 0 : return ESYSREPO_RESULT(ResultCode::OK); 278 3 : } 279 : 280 : } // namespace esys::repo::exe