Line data Source code
1 : /*! 2 : * \file esys/repo/exe/nested.h 3 : * \brief Nested workspace helpers (ADR-0043) 4 : * 5 : * \cond 6 : * __legal_b__ 7 : * 8 : * Copyright (c) 2026 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 : #pragma once 19 : 20 : #include "esys/repo/esysrepo_defs.h" 21 : #include "esys/repo/exe/cmd.h" 22 : #include "esys/repo/manifest.h" 23 : #include "esys/repo/manifest/repository.h" 24 : #include "esys/repo/result.h" 25 : 26 : #include <functional> 27 : #include <memory> 28 : #include <set> 29 : #include <string> 30 : #include <vector> 31 : 32 : //<swig_out/> 33 : 34 : namespace esys::repo::exe 35 : { 36 : 37 : //! How to treat a nested child that is not yet a workspace 38 : enum class NestedMissingMode 39 : { 40 : Fail, //!< Mutating commands (sync): hard fail 41 : WarnSkip, //!< Read-only (status/list/info): warn and continue 42 : }; 43 : 44 : //! Recursion / cycle state for nested walks 45 132 : struct NestedContext 46 : { 47 : int depth = 0; 48 : int max_depth = 8; 49 : std::set<std::string> visited_abs; 50 : }; 51 : 52 : //! Collect repositories with ``<workspace nested="true"/>`` 53 : ESYSREPO_API std::vector<std::shared_ptr<manifest::Repository>> 54 : collect_nested_repositories(const Manifest &manifest); 55 : 56 : //! Absolute child path = parent_workspace / repo_path 57 : ESYSREPO_API std::string nested_child_abs_path(const std::string &parent_workspace, const std::string &repo_path); 58 : 59 : //! True if ``child_path/.esysrepo`` exists 60 : ESYSREPO_API bool nested_workspace_initialized(const std::string &child_path); 61 : 62 : //! Detect a local native manifest at child root; empty if none 63 : ESYSREPO_API std::string find_nested_local_manifest(const std::string &child_path); 64 : 65 : //! Sync one parent-manifest path (clone/update the nested Git project) 66 : ESYSREPO_API Result sync_nested_parent_path(Cmd &parent, const std::string &repo_path); 67 : 68 : //! Ensure child has ``.esysrepo`` via init-from-local (no nested re-entry) 69 : ESYSREPO_API Result ensure_child_workspace(Cmd &parent, const std::string &child_abs_path); 70 : 71 : /*! After parent init: sync each nested path, ensure child workspace, recurse. 72 : * Uses ``NestedContext`` for depth / cycle detection. 73 : */ 74 : ESYSREPO_API Result bootstrap_nested_workspaces(Cmd &parent, NestedContext &ctx); 75 : 76 : /*! After parent command: for each nested child with ``.esysrepo``, invoke ``fn``. 77 : * Missing child workspace: Fail or WarnSkip per ``mode``. 78 : */ 79 : ESYSREPO_API Result for_each_nested( 80 : Cmd &parent, NestedMissingMode mode, NestedContext &ctx, 81 : const std::function<Result(const std::string &child_abs, std::shared_ptr<manifest::Repository> repo)> &fn); 82 : 83 : //! Copy logger / git / job_count from parent onto a child command 84 : ESYSREPO_API void prepare_nested_cmd(Cmd &parent, Cmd &child, const std::string &child_abs_path); 85 : 86 : } // namespace esys::repo::exe