From c2404728b623588aa89920ae435b48af0fef011e Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Thu, 22 Jun 2023 15:49:05 +0300 Subject: Add branch sub-option for git project vcs in bdep-new Also fix tests which failed if for the initial branch git-init defaults to the name other than 'master'. --- bdep/git.cxx | 23 ++++++++++++++++++----- bdep/git.hxx | 40 +++++++++++++++++++++++++++++++++++++++- bdep/git.txx | 6 ++++-- bdep/new.cli | 8 +++++++- bdep/new.cxx | 46 ++++++++++++++++++++++++++++++++++++++++++++-- 5 files changed, 112 insertions(+), 11 deletions(-) (limited to 'bdep') diff --git a/bdep/git.cxx b/bdep/git.cxx index cc697b3..f9bdc04 100644 --- a/bdep/git.cxx +++ b/bdep/git.cxx @@ -24,10 +24,8 @@ namespace bdep static optional bun_git_ver; #endif - // Check that git is at least of the specified minimum supported version. - // - void - git_check_version (const semantic_version& min_ver, bool system) + bool + git_try_check_version (const semantic_version& min_ver, bool system) { // Query and cache git version on the first call. // @@ -50,9 +48,24 @@ namespace bdep // Note that we don't expect the min_ver to contain the build component, // that doesn't matter functionality-wise for git. // - if (*gv < min_ver) + return *gv >= min_ver; + } + + // As above but issue diagnostics and fail if git is older than the + // specified minimum supported version. + // + void + git_check_version (const semantic_version& min_ver, bool system) + { + if (!git_try_check_version (min_ver, system)) + { + optional& gv (system ? sys_git_ver : bun_git_ver); + + assert (gv); // Must have been cached by git_try_check_version(). + fail << "unsupported git version " << *gv << info << "minimum supported version is " << min_ver << endf; + } } // Return git process path and the --exec-path option, if it is required for diff --git a/bdep/git.hxx b/bdep/git.hxx index b7703ea..30baf69 100644 --- a/bdep/git.hxx +++ b/bdep/git.hxx @@ -67,18 +67,50 @@ namespace bdep // Run git process. // + // Pass NULL as the repository argument if the git command is not + // repository-specific (e.g., init). + // template void run_git (const semantic_version&, bool system, bool progress, - const dir_path& repo, + const dir_path* repo, A&&... args); template inline void run_git (const semantic_version& min_ver, bool system, + const dir_path* repo, + A&&... args) + { + run_git (min_ver, + system, + true /* progress */, + repo, + forward (args)...); + } + + template + inline void + run_git (const semantic_version& min_ver, + bool system, + bool progress, + const dir_path& repo, + A&&... args) + { + run_git (min_ver, + system, + progress, + &repo, + forward (args)...); + } + + template + inline void + run_git (const semantic_version& min_ver, + bool system, const dir_path& repo, A&&... args) { @@ -173,6 +205,12 @@ namespace bdep template void git_push (const common_options&, const dir_path& repo, A&&... args); + + // Return true if git is at least of the specified minimum supported + // version. + // + bool + git_try_check_version (const semantic_version&, bool system); } #include diff --git a/bdep/git.txx b/bdep/git.txx index ef81bd8..2af8e1f 100644 --- a/bdep/git.txx +++ b/bdep/git.txx @@ -8,7 +8,7 @@ namespace bdep run_git (const semantic_version& min_ver, bool system, bool progress, - const dir_path& repo, + const dir_path* repo, A&&... args) { // Unfortunately git doesn't have any kind of a no-progress option but @@ -30,10 +30,12 @@ namespace bdep // process pr (start_git (min_ver, system, - repo, 0 /* stdin */, err /* stdout */, err /* stderr */, + (repo != nullptr + ? cstrings ({"-C", repo->string ().c_str ()}) + : cstrings ()), forward (args)...)); bool io (false); diff --git a/bdep/new.cli b/bdep/new.cli index 8f3b094..c6dc8ee 100644 --- a/bdep/new.cli +++ b/bdep/new.cli @@ -501,7 +501,12 @@ namespace bdep \li|\cb{git} Initialize a \cb{git(1)} repository inside the project and generate - \cb{.gitignore} files.|| + \cb{.gitignore} files. Recognized version control system sub-options:| + + \li|\n\ \ \ \c{\b{branch=}\i{name}} + + Use the specified name for the initial branch in the newly created + repository.|| \dl| @@ -632,6 +637,7 @@ namespace bdep // class cmd_new_git_options { + string branch; }; class cmd_new_none_options diff --git a/bdep/new.cxx b/bdep/new.cxx index 2c954fc..a2d2ad4 100644 --- a/bdep/new.cxx +++ b/bdep/new.cxx @@ -24,6 +24,13 @@ using namespace butl; namespace bdep { + // While we don't have any specific requirements for git version here, let's + // use the lowest common denominator for other bdep commands. Note that + // *_git() functions require the minimum supported git version as an + // argument. + // + static const semantic_version git_ver {2, 1, 0}; + // License id to full name map. // // Used for the license full name search for the auto-detected and @@ -1235,8 +1242,43 @@ cmd_new (cmd_new_options&& o, cli::group_scanner& args) { switch (vc) { - case vcs::git: run ("git", "init", "-q", out); break; - case vcs::none: break; + case vcs::git: + { + const cmd_new_git_options& opt (vc.git_opt); + + // If the branch name is specified, then pass it to git-init using the + // --initial-branch option if the git version is at least 2.28.0 (the + // one which has introduced this option). Otherwise, run git-init + // normally and then change HEAD to refer to the requested name. Note + // that the branch will only be created on the first commit. + // + if (opt.branch_specified ()) + { + if (git_try_check_version (semantic_version {2, 28, 0}, + true /* system */)) + { + run_git (git_ver, true /* system */, nullptr /* repo */, + "init", "-q", "--initial-branch", opt.branch (), out); + } + else + { + run_git (git_ver, true /* system */, nullptr /* repo */, + "init", "-q", out); + + run_git (git_ver, true /* system */, out, + "symbolic-ref", + "-q", + "HEAD", + "refs/heads/" + opt.branch ()); + } + } + else + run_git (git_ver, true /* system */, nullptr /* repo */, + "init", "-q", out); + + break; + } + case vcs::none: break; } } -- cgit v1.1