aboutsummaryrefslogtreecommitdiff
path: root/libbutl/default-options.mxx
blob: e9f92d39aac7852ef72139c1c537747f3c037f60 (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
// file      : libbutl/default-options.mxx -*- C++ -*-
// license   : MIT; see accompanying LICENSE file

#ifndef __cpp_modules_ts
#pragma once
#endif

#ifndef __cpp_lib_modules_ts
#include <vector>

#include <utility>      // move(), forward(), make_pair()
#include <algorithm>    // reverse()
#include <system_error>
#endif

// Other includes.

#ifdef __cpp_modules_ts
export module butl.default_options;
#ifdef __cpp_lib_modules_ts
import std.core;
#endif
import butl.path;
import butl.optional;
import butl.small_vector;

import butl.git;
import butl.filesystem;
#else
#include <libbutl/path.mxx>
#include <libbutl/optional.mxx>
#include <libbutl/small-vector.mxx>

#include <libbutl/git.mxx>
#include <libbutl/filesystem.mxx>
#endif

#include <libbutl/export.hxx>

LIBBUTL_MODEXPORT namespace butl
{
  // Default options files helper implementation.
  //
  struct default_options_files
  {
    small_vector<path, 2> files;
    optional<dir_path>    start;
  };

  template <typename O>
  struct default_options_entry
  {
    path file;
    O    options;
    bool remote;
  };

  template <typename O>
  using default_options = small_vector<default_options_entry<O>, 4>;

  // Search for and load (using scanner S and parsing in the U::fail mode for
  // both options and arguments) the specified list of options files in the
  // specified directories returning a vector of option class instances (O).
  // Pass each default options file path to the specified function prior to
  // load (can be used for tracing, etc). The function signature is:
  //
  // void (const path&, bool remote, bool overwrite)
  //
  // Note that the function may be called for the same file twice if it was
  // later discovered that it is in fact remote. In the second call the
  // overwrite flag will be true.
  //
  // Throw `pair<path, system_error>` on the underlying OS error with the
  // first half referring the filesystem entry the error relates to and pass
  // through exceptions thrown by the options scanner/parser.
  //
  // Search order:
  //
  // - sys_dir
  // - home_dir
  // - extra_dir (can also be handled during the start/outer traversal)
  // - start_dir and outer until home_dir or root (both excluding)
  //
  // Except for sys_dir and extra_dir, the options files are looked for in the
  // .build2/ and .build2/local/ subdirectories of each directory. For
  // sys_dir and extra_dir they are looked for in the directory itself (e.g.,
  // /etc/build2/).
  //
  // Note that the search is stopped at the directory containing a file with
  // --no-default-options.
  //
  // Also note that all the directories should be absolute and normalized.
  //
  // The presence of the .git filesystem entry causes the options files in
  // this directory and any of its subdirectories to be considered remote
  // (note that in the current implementation this is the case even for files
  // from the .build2/local/ subdirectory since the mere location is not a
  // sufficient ground to definitively conclude that the file is not remote;
  // to be sure we would need to query the VCS or some such).
  //
  // Note that the extra directory options files are never considered remote.
  //
  template <typename O, typename S, typename U, typename F>
  default_options<O>
  load_default_options (const optional<dir_path>& sys_dir,
                        const optional<dir_path>& home_dir,
                        const optional<dir_path>& extra_dir,
                        const default_options_files&,
                        F&&);

  // Merge the default options and the command line options.
  //
  // Note that this is the default implementation and in some cases you may
  // want to provide an options class-specific version that verifies/sanitizes
  // the default options (e.g., you may not want to allow certain options to
  // be specified in the default options files) or warns/prompts about
  // potentially dangerous options if they came from the remote options files.
  //
  template <typename O>
  O
  merge_default_options (const default_options<O>&, const O& cmd_ops);

  // As above but pass each default option to the specified function prior to
  // merging. The function signature is:
  //
  // void (const default_options_entry<O>&, const O& cmd_ops)
  //
  // This version can be used to verify the default options. For example, you
  // may want to disallow certain options from being specified in the default
  // options files.
  //
  template <typename O, typename F>
  O
  merge_default_options (const default_options<O>&, const O&, F&&);

  // Find a common start (parent) directory stopping at home or root
  // (excluding).
  //
  LIBBUTL_SYMEXPORT optional<dir_path>
  default_options_start (const optional<dir_path>& home_dir,
                         const std::vector<dir_path>&);
}

#include <libbutl/default-options.ixx>
#include <libbutl/default-options.txx>