aboutsummaryrefslogtreecommitdiff
path: root/bpkg/utility.hxx
blob: 7a5194884e4dbd2295a5eaa4bd82208d0d3461b6 (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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
// file      : bpkg/utility.hxx -*- C++ -*-
// license   : MIT; see accompanying LICENSE file

#ifndef BPKG_UTILITY_HXX
#define BPKG_UTILITY_HXX

#include <map>
#include <memory>    // make_shared()
#include <string>    // to_string()
#include <cstring>   // strcmp(), strchr()
#include <utility>   // move(), forward(), declval(), make_pair()
#include <cassert>   // assert()
#include <iterator>  // make_move_iterator(), back_inserter()
#include <algorithm> // *

#include <libbutl/ft/lang.hxx>

#include <libbutl/utility.hxx>         // icasecmp(), reverse_iterate(), etc
#include <libbutl/process.hxx>
#include <libbutl/filesystem.hxx>
#include <libbutl/default-options.hxx>

#include <bpkg/types.hxx>
#include <bpkg/version.hxx>
#include <bpkg/common-options.hxx>

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::back_inserter;
  using std::to_string;

  using std::strcmp;
  using std::strchr;

  // <libbutl/utility.hxx>
  //
  using butl::icasecmp;
  using butl::reverse_iterate;

  using butl::alpha;
  using butl::alnum;
  using butl::digit;
  using butl::xdigit;

  using butl::trim;
  using butl::trim_left;
  using butl::trim_right;
  using butl::next_word;

  using butl::make_guard;
  using butl::make_exception_guard;

  using butl::getenv;
  using butl::setenv;
  using butl::unsetenv;

  using butl::eof;

  // <libbutl/process.hxx>
  //
  using butl::process_start_callback;
  using butl::process_print_callback;

  // <libbutl/filesystem.hxx>
  //
  using butl::auto_rmfile;
  using butl::auto_rmdir;

  // <libbutl/default-options.hxx>
  //
  using butl::load_default_options;
  using butl::merge_default_options;

  // Empty string and path.
  //
  extern const string empty_string;
  extern const path empty_path;
  extern const dir_path empty_dir_path;

  // Widely-used paths.
  //
  extern const dir_path bpkg_dir;           // .bpkg/
  extern const dir_path certs_dir;          // .bpkg/certs/
  extern const dir_path repos_dir;          // .bpkg/repos/

  extern const dir_path std_build_dir;      // build/
  extern const dir_path std_config_dir;     // build/config/
  extern const path     std_bootstrap_file; // build/bootstrap.build
  extern const path     std_root_file;      // build/root.build
  extern const string   std_build_ext;      // build

  extern const dir_path alt_build_dir;      // build2/
  extern const dir_path alt_config_dir;     // build2/config/
  extern const path     alt_bootstrap_file; // build2/bootstrap.build2
  extern const path     alt_root_file;      // build2/root.build2
  extern const string   alt_build_ext;      // build2

  extern const dir_path current_dir;        // ./

  // Host target triplet for which we were built.
  //
  extern const target_triplet host_triplet;

  // Temporary directory facility.
  //
  // An entry normally maps <cfg-dir> to <cfg-dir>/.bpkg/tmp/ but can also map
  // an empty directory to some system-wide directory (e.g., /tmp/bpkg-XXX/)
  // if there is no bpkg configuration. The temporary directory for the
  // current configuration is automatically created and cleaned up for most
  // commands in main(), so you don't need to call init_tmp() explicitly
  // except for certain special commands (like cfg-create).
  //
  extern std::map<dir_path, dir_path> tmp_dirs;

  extern bool keep_tmp; // --keep-tmp

  auto_rmfile
  tmp_file (const dir_path& cfg, const string& prefix);

  auto_rmdir
  tmp_dir (const dir_path& cfg, const string& prefix);

  void
  init_tmp (const dir_path& cfg);

  void
  clean_tmp (bool ignore_errors);

  // Path.
  //
  // Normalize a path. Also make the relative path absolute using the current
  // directory.
  //
  path&
  normalize (path&, const char* what);

  inline path
  normalize (const path& f, const char* what)
  {
    path r (f);
    return move (normalize (r, what));
  }

  dir_path&
  normalize (dir_path&, const char* what);

  inline dir_path
  normalize (const dir_path& d, const char* what)
  {
    dir_path r (d);
    return move (normalize (r, what));
  }

  dir_path
  current_directory ();

  // Diagnostics.
  //
  // If stderr is not a terminal, then the value is absent (so can be used as
  // bool). Otherwise, it is the value of the TERM environment variable (which
  // can be NULL).
  //
  extern optional<const char*> stderr_term;

  // True if the color can be used on the stderr terminal.
  //
  extern bool stderr_term_color;

  // Y/N prompt. See butl::yn_prompt() for details (this is a thin wrapper).
  //
  // Issue diagnostics and throw failed if no answer could be extracted from
  // stdin (e.g., because it was closed).
  //
  bool
  yn_prompt (const string& prompt, char def = '\0');

  // Filesystem.
  //
  bool
  exists (const path&, bool ignore_error = false);

  bool
  exists (const dir_path&, bool ignore_error = false);

  bool
  empty (const dir_path&);

  void
  mk (const dir_path&);

  void
  mk_p (const dir_path&);

  void
  rm (const path&, uint16_t verbosity = 3);

  enum class rm_error_mode {ignore, warn, fail};

  void
  rm_r (const dir_path&,
        bool dir_itself = true,
        uint16_t verbosity = 3,
        rm_error_mode = rm_error_mode::fail);

  // Note that if ignore_error is true, the diagnostics is still issued.
  //
  bool
  mv (const dir_path& from, const dir_path& to, bool ignore_errors = false);

  bool
  mv (const path& from, const path& to, bool ignore_errors = false);

  // Set (with diagnostics at verbosity level 3 or higher) the new and return
  // the previous working directory.
  //
  dir_path
  change_wd (const dir_path&);

  // File descriptor streams.
  //
  fdpipe
  open_pipe ();

  auto_fd
  open_null ();

  // 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.
  //

  // Verbosity level 1 mapping.
  //
  enum class verb_b
  {
    quiet,    // Run quiet.
    progress, // Run quiet but (potentially) with progress.
    normal    // Run normally (at verbosity 1).
  };

  template <typename V>
  void
  map_verb_b (const common_options&, verb_b, V& args, string& verb_arg);

  const char*
  name_b (const common_options&);

  process_path
  search_b (const common_options&);

  template <typename... A>
  void
  print_b (const common_options&, verb_b, A&&... args);

  template <typename O, typename E, typename... A>
  process
  start_b (const common_options&, O&& out, E&& err, verb_b, A&&... args);

  template <typename... A>
  void
  run_b (const common_options&, verb_b, A&&... args);

  // Read out the data from the specified file descriptor and dump it to
  // stderr. Throw io_error on the underlying OS errors.
  //
  void
  dump_stderr (auto_fd&&);
}

#include <bpkg/utility.txx>

#endif // BPKG_UTILITY_HXX