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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
|
// 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> // casecmp(), 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::casecmp;
using butl::reverse_iterate;
// Widely-used paths.
//
extern const dir_path bpkg_dir; // .bpkg/
extern const dir_path certs_dir; // .bpkg/certs/
// 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.
//
// By default the process command line is printed for verbosity >= 2
// (essential command lines).
//
// If fallback is specified, then this directory is searched for the
// executable as a last resort.
//
void
run (const char* args[], const dir_path& fallback = dir_path ());
inline void
run (cstrings& args, const dir_path& fallback = dir_path ())
{
run (args.data (), fallback);
}
// Directory extracted from argv[0] (i.e., this process' recall directory)
// or empty if there is none. Can be used as a search fallback.
//
extern dir_path exec_dir;
// 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;
const char*
name_b (const 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
|