From 5d69b98c5d62b05d1d6d6fd24aeac468af509365 Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Wed, 14 Nov 2018 16:12:25 +0300 Subject: Add support for repository typed URLs (git+https://..., etc) --- bpkg/manifest-utility.cxx | 27 +++++--- bpkg/rep-add.cli | 6 +- bpkg/rep-fetch.cxx | 4 +- bpkg/repository-types.cli | 11 ++++ tests/rep-add.testscript | 149 +++++++++++++++++++++++++++++---------------- tests/rep-fetch.testscript | 26 ++++---- 6 files changed, 144 insertions(+), 79 deletions(-) diff --git a/bpkg/manifest-utility.cxx b/bpkg/manifest-utility.cxx index c329108..79c131b 100644 --- a/bpkg/manifest-utility.cxx +++ b/bpkg/manifest-utility.cxx @@ -92,7 +92,9 @@ namespace bpkg parse_location (const string& s, optional ot) try { - repository_url u (s); + typed_repository_url tu (s); + + repository_url& u (tu.url); assert (u.path); // Make the relative path absolute using the current directory. @@ -102,13 +104,24 @@ namespace bpkg // Guess the repository type to construct the repository location: // - // 1. If type is specified as an option use that (but validate - // incompatible scheme/type e.g., git/pkg). + // 1. If the type is specified in the URL scheme, then use that (but + // validate that it matches the --type option, if present). + // + // 2. If the type is specified as an option, then use that. // - // 2. See guess_type() function description in libbpkg/manifest.hxx for - // the algorithm details. + // Validate the protocol/type compatibility (e.g. git:// vs pkg) for both + // cases. // - repository_type t (ot ? *ot : guess_type (u, true)); + // 3. See the guess_type() function description in + // for the algorithm details. + // + if (tu.type && ot && tu.type != ot) + fail << to_string (*ot) << " repository type mismatch for location '" + << s << "'"; + + repository_type t (tu.type ? *tu.type : + ot ? *ot : + guess_type (tu.url, true /* local */)); try { @@ -125,7 +138,7 @@ namespace bpkg // If the pkg repository type was guessed, then suggest the user to // specify the type explicitly. // - if (!ot && t == repository_type::pkg) + if (!tu.type && !ot && t == repository_type::pkg) dr << info << "consider using --type to specify repository type"; dr << endf; diff --git a/bpkg/rep-add.cli b/bpkg/rep-add.cli index 481b30a..9605ac7 100644 --- a/bpkg/rep-add.cli +++ b/bpkg/rep-add.cli @@ -40,9 +40,9 @@ namespace bpkg case of a local repository, its content (for example, the presence of the \cb{.git/} subdirectory). Without any identifying information the \cb{pkg} type is assumed unless explicitly specified with the \cb{--type} - option. Note, however, that the \cb{dir} repository type is never guessed - since it is not easily distinguishable from local \cb{pkg} and \cb{git} - repositories. + option or in the URL scheme. Note, however, that the \cb{dir} repository + type is never guessed since it is not easily distinguishable from local + \cb{pkg} and \cb{git} repositories. " } diff --git a/bpkg/rep-fetch.cxx b/bpkg/rep-fetch.cxx index 77ffc10..ef42b03 100644 --- a/bpkg/rep-fetch.cxx +++ b/bpkg/rep-fetch.cxx @@ -537,8 +537,8 @@ namespace bpkg } catch (const invalid_argument& e) { - fail << "invalid relative repository location '" << l - << "': " << e << + fail << "invalid relative repository location '" << l << "': " + << e << info << "base repository location is " << rl; } diff --git a/bpkg/repository-types.cli b/bpkg/repository-types.cli index 79c50f8..1471ecf 100644 --- a/bpkg/repository-types.cli +++ b/bpkg/repository-types.cli @@ -16,6 +16,17 @@ structure, and the format of their URLs. Currently three types of repositories are supported: archive-based \cb{pkg}, directory-based \cb{dir}, and version control-based \cb{git}. +The repository location may specify the repository type as part of the URL +scheme component in the \c{\i{type}\b{+}\i{protocol}} form. For example: + +\ +git+https://example.com/foo +dir+file:///tmp/repo +\ + +Note that the explicit specification is only needed when the correct type +cannot be guessed from the URL. See \l{bpkg-rep-add(1)} for details. + \h|PKG REPOSITORIES| diff --git a/tests/rep-add.testscript b/tests/rep-add.testscript index b57eb68..3280bc6 100644 --- a/tests/rep-add.testscript +++ b/tests/rep-add.testscript @@ -14,9 +14,9 @@ rep_list += -d cfg : none : $* 2>>EOE != 0 - error: repository location argument expected - info: run 'bpkg help rep-add' for more information - EOE + error: repository location argument expected + info: run 'bpkg help rep-add' for more information + EOE : empty : @@ -24,15 +24,15 @@ rep_list += -d cfg $clone_cfg; $* '' 2>>EOE != 0 - error: invalid repository location '': empty URL - EOE + error: invalid repository location '': empty URL + EOE } : unknown-type : $* 'repo' --type unknown 2>>EOE != 0 - error: invalid value 'unknown' for option '--type' - EOE + error: invalid value 'unknown' for option '--type' + EOE : no-version : @@ -40,9 +40,9 @@ rep_list += -d cfg $clone_cfg; $* 'stable' 2>>/~%EOE% != 0 - %error: invalid pkg repository location '.+/no-version/stable': missing repository version% - info: consider using --type to specify repository type - EOE + %error: invalid pkg repository location '.+/no-version/stable': missing repository version% + info: consider using --type to specify repository type + EOE } : git-invalid-fragment @@ -51,18 +51,28 @@ rep_list += -d cfg $clone_cfg; $* 'git://example.org/repo#' 2>>EOE != 0 - error: invalid git repository location 'git://example.org/repo#': missing refname or commit id for git repository - EOE + error: invalid git repository location 'git://example.org/repo#': missing refname or commit id for git repository + EOE } - : pkg-git-scheme + : git-scheme-pkg-type : { $clone_cfg; $* 'git://example.org/repo' --type pkg 2>>EOE != 0 - error: invalid pkg repository location 'git://example.org/repo': unsupported scheme for pkg repository - EOE + error: invalid pkg repository location 'git://example.org/repo': unsupported scheme for pkg repository + EOE + } + + : git-pkg-types + : + { + $clone_cfg; + + $* 'git+https://example.org/repo' --type pkg 2>>EOE != 0 + error: pkg repository type mismatch for location 'git+https://example.org/repo' + EOE } : invalid-path @@ -74,8 +84,8 @@ rep_list += -d cfg $clone_cfg; $* "$s" 2>>~%EOE% != 0 - %error: invalid repository path '.+/': invalid filesystem path% - EOE + %error: invalid repository path '.+/': invalid filesystem path% + EOE } : type-detection @@ -85,40 +95,53 @@ rep_list += -d cfg : git-scheme : - $clone_cfg; - $* 'git://example.org/repo#master' 2>>EOE - added git:example.org/repo#master - EOE + { + $clone_cfg; + + $* 'git://example.org/repo#master' 2>>EOE + added git:example.org/repo#master + EOE + } : http-git : - $clone_cfg; - $* 'http://example.org/repo.git#master' 2>>EOE - added git:example.org/repo#master - EOE + { + $clone_cfg; + + $* 'http://example.org/repo.git#master' 2>>EOE + added git:example.org/repo#master + EOE + } : http-pkg : - $clone_cfg; - $* 'http://example.org/1/repo' 2>>EOE - added pkg:example.org/repo - EOE + { + $clone_cfg; + + $* 'http://example.org/1/repo' 2>>EOE + added pkg:example.org/repo + EOE + } : file-git : - $clone_cfg && mkdir -p repo/.git; + { + $clone_cfg && mkdir -p repo/.git; - $* 'repo' 2>>/~%EOE% - %added git:.+/repo% - EOE + $* 'repo' 2>>/~%EOE% + %added git:.+/repo% + EOE + } : file-pkg : - $clone_cfg; + { + $clone_cfg; - $* '1/repo' 2>>/~%EOE% - %added .+/repo% - EOE + $* '1/repo' 2>>/~%EOE% + %added .+/repo% + EOE + } } } @@ -157,34 +180,52 @@ rep_list += -d cfg : pkg : - $clone_cfg; + { + $clone_cfg; - $* 'http://pkg.example.org/1/testing' 2>>EOE; - added pkg:example.org/testing - EOE + $* 'http://pkg.example.org/1/testing' 2>>EOE; + added pkg:example.org/testing + EOE - $* 'https://www.example.org/1/testing' 2>>EOE; - updated pkg:example.org/testing - EOE + $* 'https://www.example.org/1/testing' 2>>EOE; + updated pkg:example.org/testing + EOE - $rep_list >>EOO - pkg:example.org/testing https://www.example.org/1/testing - EOO + $rep_list >>EOO + pkg:example.org/testing https://www.example.org/1/testing + EOO + } : git : - $clone_cfg; + { + $clone_cfg; - $* 'git://example.org/testing.git#master' 2>>~%EOE%; - %added git:example.org/testing#master% - EOE + $* 'git://example.org/testing.git#master' 2>>~%EOE%; + %added git:example.org/testing#master% + EOE + + $* 'https://www.example.org/testing.git#master' 2>>EOE; + updated git:example.org/testing#master + EOE + + $rep_list >>EOO + git:example.org/testing#master https://www.example.org/testing.git#master + EOO + } +} + +: typed-url +: +{ + $clone_cfg; - $* 'https://www.example.org/testing.git#master' 2>>EOE; - updated git:example.org/testing#master + $* 'git+https://example.org/repo' 2>>EOE; + added git:example.org/repo EOE $rep_list >>EOO - git:example.org/testing#master https://www.example.org/testing.git#master + git:example.org/repo git+https://example.org/repo EOO } diff --git a/tests/rep-fetch.testscript b/tests/rep-fetch.testscript index 8320f70..4138209 100644 --- a/tests/rep-fetch.testscript +++ b/tests/rep-fetch.testscript @@ -486,9 +486,9 @@ if ($remote != true) 3 package\(s\) in 2 repository\(s\) EOE - $rep_list >>"EOO" - dir:($rep/libbar.git) ($rep/libbar.git) - prerequisite dir:($rep/style-basic.git) ($rep/style-basic.git) + $rep_list >>~%EOO% + %dir:.+libbar\.git dir\+file:///.+libbar\.git% + % prerequisite dir:.+style-basic\.git dir\+file:///.+style-basic\.git% EOO } @@ -506,9 +506,9 @@ if ($remote != true) 3 package\(s\) in 2 repository\(s\) EOE - $rep_list >>"EOO" - dir:($rep/libbar.git) ($rep/libbar.git) - prerequisite dir:($rep/style-basic.git) ($rep/style-basic.git) + $rep_list >>~%EOO% + %dir:.+libbar\.git dir\+file:///.+libbar\.git% + % prerequisite dir:.+style-basic\.git dir\+file:///.+style-basic\.git% EOO } @@ -527,9 +527,9 @@ if ($remote != true) 3 package\(s\) in 2 repository\(s\) EOE - $rep_list >>"EOO" - dir:($rep/libbar.git) ($rep/libbar.git) - prerequisite dir:($rep/style-basic.git) ($rep/style-basic.git) + $rep_list >>~%EOO% + %dir:.+libbar\.git dir\+file:///.+libbar\.git% + % prerequisite dir:.+style-basic\.git dir\+file:///.+style-basic\.git% EOO } @@ -544,9 +544,9 @@ if ($remote != true) 3 package\(s\) in 2 repository\(s\) EOE - $rep_list >>"EOO" - dir:($rep/libbar.git) ($rep/libbar.git) - prerequisite dir:($rep/style-basic.git) ($rep/style-basic.git) + $rep_list >>~%EOO% + %dir:.+libbar\.git dir\+file:///.+libbar\.git% + % prerequisite dir:.+style-basic\.git dir\+file:///.+style-basic\.git% EOO } } @@ -771,7 +771,7 @@ else $rep_list >>~%EOO% %git:.+libbar#master file:.+libbar\.git#master% - % prerequisite git:.+style-basic#stable file:.+style-basic#stable \(heads/master\)% + % prerequisite git:.+style-basic#stable git\+file:.+style-basic#stable \(heads/master\)% EOO } -- cgit v1.1