aboutsummaryrefslogtreecommitdiff
path: root/build2/filesystem.hxx
blob: ed99685fbe887ef3c940fdda667d041cb6d32276 (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
// file      : build2/filesystem.hxx -*- C++ -*-
// copyright : Copyright (c) 2014-2019 Code Synthesis Ltd
// license   : MIT; see accompanying LICENSE file

#ifndef BUILD2_FILESYSTEM_HXX
#define BUILD2_FILESYSTEM_HXX

#include <libbutl/filesystem.mxx>

#include <build2/types.hxx>
#include <build2/utility.hxx>

// Higher-level filesystem utilities built on top of <libbutl/filesystem.mxx>.
//
namespace build2
{
  using butl::auto_rmfile;
  using butl::auto_rmdir;

  // The dual interface wrapper for the {mk,rm}{file,dir}() functions
  // below that allows you to use it as a true/false return or a more
  // detailed enum from <libbutl/filesystem.mxx>
  //
  template <typename T>
  struct fs_status
  {
    T v;
    fs_status (T v): v (v) {};
    operator T () const {return v;}
    explicit operator bool () const {return v == T::success;}
  };

  // Set the file access and modification times to the current time printing
  // the standard diagnostics starting from the specified verbosity level. If
  // the file does not exist and create is true, create it and fail otherwise.
  // Return true if the file was created and false otherwise.
  //
  bool
  touch (const path&, bool create, uint16_t verbosity = 1);

  // Return the modification time for an existing regular file and
  // timestamp_nonexistent otherwise. Print the diagnostics and fail on system
  // error.
  //
  timestamp
  mtime (const char*);

  inline timestamp
  mtime (const path& p)
  {
    return mtime (p.string ().c_str ());
  }

  // Create the directory and print the standard diagnostics starting from
  // the specified verbosity level.
  //
  // Note that this implementation is not suitable if it is expected that the
  // directory will exist in the majority of cases and performance is
  // important. See the fsdir{} rule for details.
  //
  using mkdir_status = butl::mkdir_status;

  fs_status<mkdir_status>
  mkdir (const dir_path&, uint16_t verbosity = 1);

  fs_status<mkdir_status>
  mkdir_p (const dir_path&, uint16_t verbosity = 1);

  // Remove the file and print the standard diagnostics starting from the
  // specified verbosity level. The second argument is only used in
  // diagnostics, to print the target name. Passing the path for target will
  // result in the relative path being printed.
  //
  using rmfile_status = butl::rmfile_status;

  template <typename T>
  fs_status<rmfile_status>
  rmfile (const path&, const T& target, uint16_t verbosity = 1);

  inline fs_status<rmfile_status>
  rmfile (const path& f, int verbosity = 1) // Literal overload (int).
  {
    return rmfile (f, f, static_cast<uint16_t> (verbosity));
  }

  inline fs_status<rmfile_status>
  rmfile (const path& f, uint16_t verbosity) // Overload (verb_never).
  {
    return rmfile (f, f, verbosity);
  }

  fs_status<rmfile_status>
  rmsymlink (const path&, bool dir, uint16_t verbosity);

  // Similar to rmfile() but for directories (note: not -r).
  //
  using rmdir_status = butl::rmdir_status;

  template <typename T>
  fs_status<rmdir_status>
  rmdir (const dir_path&, const T& target, uint16_t verbosity = 1);

  inline fs_status<rmdir_status>
  rmdir (const dir_path& d, int verbosity = 1) // Literal overload (int).
  {
    return rmdir (d, d, static_cast<uint16_t> (verbosity));
  }

  inline fs_status<rmdir_status>
  rmdir (const dir_path& d, uint16_t verbosity) // Overload (verb_never).
  {
    return rmdir (d, d, verbosity);
  }

  // Remove the directory recursively and print the standard diagnostics
  // starting from the specified verbosity level. Note that this function
  // returns not_empty if we try to remove a working directory. If the dir
  // argument is false, then the directory itself is not removed.
  //
  // @@ Collides (via ADL) with butl::rmdir_r(), which sucks.
  //
  fs_status<rmdir_status>
  rmdir_r (const dir_path&, bool dir = true, uint16_t verbosity = 1);

  // Check for a file, directory or filesystem entry existence. Print the
  // diagnostics and fail on system error, unless ignore_error is true.
  //
  bool
  exists (const path&, bool follow_symlinks = true, bool ignore_error = false);

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

  bool
  entry_exists (const path&,
                bool follow_symlinks = false,
                bool ignore_error = false);

  // Check for a directory emptiness. Print the diagnostics and fail on system
  // error.
  //
  bool
  empty (const dir_path&);

  // Directories containing .buildignore (or .build2ignore in the alternative
  // naming scheme) file are automatically ignored by recursive name patterns.
  // For now the file is just a marker and its contents don't matter.

  // Create a directory containing an empty .buildignore file.
  //
  fs_status<mkdir_status>
  mkdir_buildignore (const dir_path&, const path&, uint16_t verbosity = 1);

  // Return true if the directory is empty or only contains the .buildignore
  // file. Fail if the directory doesn't exist.
  //
  bool
  empty_buildignore (const dir_path&, const path&);

  // Remove a directory if it is empty or only contains the .buildignore file.
  //
  fs_status<rmdir_status>
  rmdir_buildignore (const dir_path&, const path&, uint16_t verbosity = 1);
}

#include <build2/filesystem.txx>

#endif // BUILD2_FILESYSTEM_HXX