From 93a673946ca1587126b3c108476234d93a7c5c7c Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Mon, 2 Jul 2018 11:24:47 +0200 Subject: Try to obtain real email from environment, VCS in bdep-new --- bdep/new.cli | 9 ++++ bdep/new.cxx | 12 ++++- bdep/project-email.cxx | 116 +++++++++++++++++++++++++++++++++++++++++++++++++ bdep/project-email.hxx | 23 ++++++++++ 4 files changed, 158 insertions(+), 2 deletions(-) create mode 100644 bdep/project-email.cxx create mode 100644 bdep/project-email.hxx diff --git a/bdep/new.cli b/bdep/new.cli index e700985..df77717 100644 --- a/bdep/new.cli +++ b/bdep/new.cli @@ -245,4 +245,13 @@ namespace bdep working directory." } }; + + "\h|ENVIRONMENT| + + The \cb{BDEP_EMAIL} environment variable can be used to specify the package + email address. If not set, the \cb{new} command will first try to obtain + the email from the version control system (if used) and then from the + \cb{EMAIL} environment variable. If all these methods fail, a dummy + \cb{@example.org} email is used. + " } diff --git a/bdep/new.cxx b/bdep/new.cxx index ab8b255..9869fe7 100644 --- a/bdep/new.cxx +++ b/bdep/new.cxx @@ -5,6 +5,7 @@ #include #include +#include #include #include @@ -172,7 +173,8 @@ namespace bdep fail << "directory " << out << " already exists"; // Initialize the version control system. Do it before writing anything - // ourselves in case it fails. + // ourselves in case it fails. Also, the email discovery may do the VCS + // detection. // if (!pkg) { @@ -257,6 +259,12 @@ namespace bdep // manifest // + string email; + { + optional r (project_email (prj)); + email = r ? move (*r) : "you@example.org"; + } + os.open (f = out / "manifest"); os << ": 1" << endl << "name: " << n << endl @@ -264,7 +272,7 @@ namespace bdep << "summary: " << s << " " << t << endl << "license: TODO" << endl << "url: https://example.org/" << n << endl - << "email: you@example.org" << endl + << "email: " << email << endl << "depends: * build2 >= 0.8.0-" << endl << "depends: * bpkg >= 0.8.0-" << endl << "#depends: libhello ^1.0.0" << endl; diff --git a/bdep/project-email.cxx b/bdep/project-email.cxx new file mode 100644 index 0000000..20279a0 --- /dev/null +++ b/bdep/project-email.cxx @@ -0,0 +1,116 @@ +// file : bdep/project-email.cxx -*- C++ -*- +// copyright : Copyright (c) 2014-2018 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#include + +#include + +#include + +using namespace butl; + +namespace bdep +{ + optional + project_email (const dir_path& prj) + { + optional r; + + // The search order is as follows: + // + // BDEP_EMAIL + // + // EMAIL + // + if ((r = getenv ("BDEP_EMAIL"))) + return r; + + // See if this is a VCS repository we recognize. + // + + // .git can be either a directory or a file in case of a submodule. + // + if (entry_exists (prj / ".git", + true /* follow_symlinks */, + true /* ignore_errors */)) + { + // In git the author email can be specified with the GIT_AUTHOR_EMAIL + // environment variable after which things fall back to the committer + // (GIT_COMMITTER_EMAIL and then the user.email git-config value). The + // resolved value can be queried with the GIT_AUTHOR_IDENT logical + // variable. + // + process pr; + bool io (false); + try + { + fdpipe pipe (fdopen_pipe ()); + + // If git cannot determine the author name/email, it fails verbosely + // so we suppress all diagnostics. + // + pr = start (0 /* stdin */, + pipe /* stdout */, + fdnull () /* stderr */, + "git", + "-C", prj, + "var", + "GIT_AUTHOR_IDENT"); + + pipe.out.close (); + ifdstream is (move (pipe.in), ifdstream::badbit); + + // The output should be a single line in this form: + // + // NAME TIME ZONE + // + // For example: + // + // John Doe 1530517726 +0200 + // + // The <> delimiters are there even if the email is empty so we use + // them as anchors. + // + string l; + if (!eof (getline (is, l))) + { + size_t p1, p2; + + if ((p2 = l.rfind ('>' )) == string::npos || + (p1 = l.rfind ('<', p2)) == string::npos) + fail << "no email in git-var output"; + + if (++p1 != p2) + r = string (l, p1, p2 - p1); + } + + is.close (); // Detect errors. + } + catch (const io_error&) + { + io = true; // Presumably git failed so check that first. + } + + if (!pr.wait ()) + { + const process_exit& e (*pr.exit); + + if (!e.normal ()) + fail << "process git " << e; + + r = nullopt; + } + else if (io) + fail << "unable to read git-var output"; + + if (r) + return r; + } + + if ((r = getenv ("EMAIL"))) + return r; + + return r; + } +} diff --git a/bdep/project-email.hxx b/bdep/project-email.hxx new file mode 100644 index 0000000..c630682 --- /dev/null +++ b/bdep/project-email.hxx @@ -0,0 +1,23 @@ +// file : bdep/project-email.hxx -*- C++ -*- +// copyright : Copyright (c) 2014-2018 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#ifndef BDEP_PROJECT_EMAIL_HXX +#define BDEP_PROJECT_EMAIL_HXX + +#include +#include + +namespace bdep +{ + // Given a project directly, try to discover the author's email address + // using the environment and, if project looks like a repository, its VCS. + // + // Note: if using this function in a command, don't forget to update its + // ENVIRONMENT section to mention BDEP_EMAIL. + // + optional + project_email (const dir_path&); +} + +#endif // BDEP_PROJECT_EMAIL_HXX -- cgit v1.1