aboutsummaryrefslogtreecommitdiff
path: root/bpkg/utility.txx
blob: a21325c18056c4e35b4dcb447a97f4c31d39decd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
// file      : bpkg/utility.txx -*- C++ -*-
// license   : MIT; see accompanying LICENSE file

#include <bpkg/diagnostics.hxx>

namespace bpkg
{
  // *_b()
  //
  template <typename V>
  void
  map_verb_b (const common_options& co, verb_b v, V& ops, string& verb_arg)
  {
    // Map verbosity level. If we are running quiet or at level 1,
    // then run build2 quiet. Otherwise, run it at the same level
    // as us.
    //
    bool progress    (co.progress ());
    bool no_progress (co.no_progress ());

    if (verb == 0)
    {
      ops.push_back ("-q");
      no_progress = false;  // Already suppressed with -q.
    }
    else if (verb == 1)
    {
      if (v != verb_b::normal)
      {
        ops.push_back ("-q");

        if (!no_progress)
        {
          if (v == verb_b::progress && stderr_term)
          {
            ops.push_back ("--progress");
              progress = false; // The option is already added.
          }
        }
        else
          no_progress = false; // Already suppressed with -q.
      }
    }
    else if (verb == 2)
      ops.push_back ("-v");
    else
    {
      verb_arg = to_string (verb);
      ops.push_back ("--verbose");
      ops.push_back (verb_arg.c_str ());
    }

    if (progress)
      ops.push_back ("--progress");

    if (no_progress)
      ops.push_back ("--no-progress");
  }

  template <typename O, typename E, typename... A>
  process
  start_b (const common_options& co,
           O&& out,
           E&& err,
           verb_b v,
           A&&... args)
  {
    process_path pp (search_b (co));

    try
    {
      small_vector<const char*, 1> ops;

      // NOTE: see custom versions in system_package_manager* if adding
      //       anything new here (search for search_b()).

      string verb_arg;
      map_verb_b (co, v, ops, verb_arg);

      // Forward our --[no]diag-color options.
      //
      if (co.diag_color ())
        ops.push_back ("--diag-color");

      if (co.no_diag_color ())
        ops.push_back ("--no-diag-color");

      return process_start_callback (
        [] (const char* const args[], size_t n)
        {
          if (verb >= 2)
            print_process (args, n);
        },
        0 /* stdin */,
        forward<O> (out),
        forward<E> (err),
        pp,
        ops,
        co.build_option (),
        forward<A> (args)...);
    }
    catch (const process_error& e)
    {
      fail << "unable to execute " << pp.recall_string () << ": " << e << endf;
    }
  }

  template <typename... A>
  void
  run_b (const common_options& co, verb_b v, A&&... args)
  {
    process pr (
      start_b (co, 1 /* stdout */, 2 /* stderr */, v, forward<A> (args)...));

    if (!pr.wait ())
    {
      const process_exit& e (*pr.exit);

      if (e.normal ())
        throw failed (); // Assume the child issued diagnostics.

      fail << "process " << name_b (co) << " " << e;
    }
  }
}