From 05e0f5ca9e9a916746bd6b26baff317663674574 Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Mon, 30 Apr 2018 12:46:10 +0300 Subject: Add support for default and excluding git ref filters --- libbpkg/manifest.cxx | 45 +++++++++++++++++++++++++++++++-------------- libbpkg/manifest.hxx | 37 ++++++++++++++++++++++++------------- 2 files changed, 55 insertions(+), 27 deletions(-) (limited to 'libbpkg') diff --git a/libbpkg/manifest.cxx b/libbpkg/manifest.cxx index ab3acf1..78e3f2e 100644 --- a/libbpkg/manifest.cxx +++ b/libbpkg/manifest.cxx @@ -2320,36 +2320,43 @@ namespace bpkg // git_ref_filter // git_ref_filter:: - git_ref_filter (const string& frag) + git_ref_filter (const string& rf) { - size_t p (frag.find ('@')); + exclusion = rf[0] == '-'; + + // Strip the leading +/-. + // + const string& s (exclusion || rf[0] == '+' ? string (rf, 1) : rf); + + size_t p (s.find ('@')); + if (p != string::npos) { if (p != 0) - name = string (frag, 0, p); + name = string (s, 0, p); - if (p + 1 != frag.size ()) - commit = string (frag, p + 1); + if (p + 1 != s.size ()) + commit = string (s, p + 1); } - else if (!frag.empty ()) + else if (!s.empty ()) { // A 40-characters fragment that consists of only hexadecimal digits is // assumed to be a commit id. // - if (frag.size () == 40 && - find_if_not (frag.begin (), frag.end (), + if (s.size () == 40 && + find_if_not (s.begin (), s.end (), // Resolve the required overload. // - static_cast (xdigit)) == frag.end ()) - commit = frag; + static_cast (xdigit)) == s.end ()) + commit = s; else - name = frag; + name = s; } if (!name && !commit) throw invalid_argument ( - "missing reference name or commit id for git repository"); + "missing refname or commit id for git repository"); if (commit && commit->size () != 40) throw invalid_argument ( @@ -2357,10 +2364,20 @@ namespace bpkg } git_ref_filters - parse_git_ref_filters (const string& s) + parse_git_ref_filters (const optional& fs) { + if (!fs) + return git_ref_filters ({git_ref_filter ()}); + + const string& s (*fs); + git_ref_filters r; - for (size_t p (0); p != string::npos; ) + bool def (s[0] == '#'); + + if (def) + r.push_back (git_ref_filter ()); + + for (size_t p (def ? 1 : 0); p != string::npos; ) { size_t e (s.find (',', p)); r.emplace_back (string (s, p, e != string::npos ? e - p : e)); diff --git a/libbpkg/manifest.hxx b/libbpkg/manifest.hxx index 3716670..68c4bc7 100644 --- a/libbpkg/manifest.hxx +++ b/libbpkg/manifest.hxx @@ -835,40 +835,51 @@ namespace bpkg return os << l.string (); } - // Git refname and/or commit. At least one of them must be present. If both - // are present then the commit is expected to belong to the history of the - // specified ref (e.g., tag or branch). Note that the name member can also - // be an abbreviated commit id (full, 40-character commit ids should always - // be stored in the commit member since then may refer to an unadvertised - // commit). + // Git refname/pattern and/or commit. If none of them is present then the + // default reference set is assumed. If both are present then the commit is + // expected to belong to the history of the specified refs (e.g., tag or + // branch). Note that the name member can also be an abbreviated commit id + // (full, 40-character commit ids should always be stored in the commit + // member since they may refer to an unadvertised commit). // class LIBBPKG_EXPORT git_ref_filter { public: butl::optional name; butl::optional commit; + bool exclusion = false; public: - // Parse the [][@] repository URL fragment representation. - // Throw std::invalid_argument if the filter representation format is - // invalid. + git_ref_filter () = default; // Default reference set. + + // Parse the [+|-][][@] reference filter representation. + // Throw std::invalid_argument if the string is empty or the filter + // representation format is invalid. // explicit git_ref_filter (const std::string&); git_ref_filter (butl::optional n, - butl::optional c) + butl::optional c, + bool e) : name (std::move (n)), - commit (std::move (c)) {} + commit (std::move (c)), + exclusion (e) {} + + bool + default_refs () const {return !name && !commit;} }; using git_ref_filters = std::vector; - // Parse a comma-separated list of git reference filters. Throw + // Parse a comma-separated list of git reference filters. If the argument + // starts with the '#' character then prepend the resulting list with the + // default reference set filter (see above). If the argument is absent then + // return the list containing a single default reference set filter. Throw // std::invalid_argument if the filter list format is invalid. // LIBBPKG_EXPORT git_ref_filters - parse_git_ref_filters (const std::string&); + parse_git_ref_filters (const butl::optional&); enum class repository_role { -- cgit v1.1