aboutsummaryrefslogtreecommitdiff
path: root/bpkg/utility
blob: 7bb6111602b7b9f6e906f2eaba471d5991800f41 (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
126
127
128
129
130
131
132
133
134
135
136
137
// file      : bpkg/utility -*- C++ -*-
// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd
// license   : MIT; see accompanying LICENSE file

#ifndef BPKG_UTILITY
#define BPKG_UTILITY

#include <memory>   // make_shared()
#include <string>   // to_string()
#include <utility>  // move(), forward(), declval(), make_pair()
#include <cassert>  // assert()
#include <iterator> // make_move_iterator()

#include <butl/utility> // reverse_iterate()

#include <exception> // uncaught_exception()

#include <butl/filesystem>

#include <bpkg/types>

namespace bpkg
{
  using std::move;
  using std::forward;
  using std::declval;

  using std::make_pair;
  using std::make_shared;
  using std::make_move_iterator;
  using std::to_string;

  // <butl/utility>
  //
  using butl::reverse_iterate;

  // Y/N prompt. The def argument, if specified, should be either 'y'
  // or 'n'. It is used as the default answer, in case the user just
  // hits enter. Issue diagnostics and throw failed if no answer could
  // be extracted from STDOUT (e.g., because it was closed).
  //
  bool
  yn_prompt (const char* prompt, char def = '\0');

  // Filesystem.
  //
  bool
  exists (const path&);

  bool
  exists (const dir_path&);

  bool
  empty (const dir_path&);

  void
  mk (const dir_path&);

  void
  mk_p (const dir_path&);

  void
  rm (const path&);

  void
  rm_r (const dir_path&, bool dir = true);

  using auto_rm = butl::auto_rmfile;
  using auto_rm_r = butl::auto_rmdir;

  // Process.
  //
  // The process command line is printed for verbosity >= 2 (essential
  // command lines).
  //
  void
  run (const char* const args[]);

  inline void
  run (const cstrings& args) {run (args.data ());}

  // Run build2, mapping verbosity levels. If quiet is true, then run build2
  // quiet if our verbosity level is 1. Common vars (cvars) are set on the
  // configuration scope.
  //
  class common_options;

  void
  run_b (const common_options&,
         const dir_path& configuration,
         const string& buildspec,
         bool quiet = false,
         const strings& pvars = strings (),
         const strings& cvars = strings ());

  // Call a function if there is an exception.
  //

  // True means we are in the body of a destructor that is being
  // called as part of the exception stack unwindining. Used to
  // compensate for the deficiencies of uncaught_exception() until
  // C++17 uncaught_exceptions() becomes available.
  //
  // @@ MT: will have to be TLS.
  //
  extern bool exception_unwinding_dtor;

  template <typename F>
  struct exception_guard;

  template <typename F>
  inline exception_guard<F>
  make_exception_guard (F f)
  {
    return exception_guard<F> (std::move (f));
  }

  template <typename F>
  struct exception_guard
  {
    exception_guard (F f): f_ (std::move (f)) {}
    ~exception_guard ()
    {
      if (std::uncaught_exception ())
      {
        exception_unwinding_dtor = true;
        f_ ();
        exception_unwinding_dtor = false;
      }
    }

  private:
    F f_;
  };
}

#endif // BPKG_UTILITY