aboutsummaryrefslogtreecommitdiff
path: root/build/context.txx
blob: 286d46023c2fa9797404f956ed3ea6357c3cb20c (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      : build/context.txx -*- C++ -*-
// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd
// license   : MIT; see accompanying LICENSE file

#include <system_error>

#include <build/diagnostics>

namespace build
{
  template <typename T>
  fs_status<rmfile_status>
  rmfile (const path& f, const T& t)
  {
    // We don't want to print the command if we couldn't remove the
    // file because it does not exist (just like we don't print the
    // update command if the file is up to date). This makes the
    // below code a bit ugly.
    //
    rmfile_status rs;

    try
    {
      rs = try_rmfile (f);
    }
    catch (const std::system_error& e)
    {
      if (verb)
        text << "rm " << f;
      else
        text << "rm " << t;

      fail << "unable to remove file " << f << ": " << e.what ();
    }

    if (rs == rmfile_status::success)
    {
      if (verb)
        text << "rm " << f;
      else
        text << "rm " << t;
    }

    return rs;
  }

  template <typename T>
  fs_status<rmdir_status>
  rmdir (const dir_path& d, const T& t)
  {
    bool w (d == work); // Don't try to remove working directory.
    rmdir_status rs;

    // We don't want to print the command if we couldn't remove the
    // directory because it does not exist (just like we don't print
    // mkdir if it already exists) or if it is not empty. This makes
    // the below code a bit ugly.
    //
    try
    {
      rs = !w ? try_rmdir (d) : rmdir_status::not_empty;
    }
    catch (const std::system_error& e)
    {
      if (verb)
        text << "rmdir " << d;
      else
        text << "rmdir " << t;

      fail << "unable to remove directory " << d << ": " << e.what ();
    }

    switch (rs)
    {
    case rmdir_status::success:
      {
        if (verb)
          text << "rmdir " << d;
        else
          text << "rmdir " << t;

        break;
      }
    case rmdir_status::not_empty:
      {
        if (verb)
          text << "directory " << d << " is "
               << (w ? "current working directory" : "not empty")
               << ", not removing";

        break;
      }
    case rmdir_status::not_exist:
      break;
    }

    return rs;
  }

  template <typename K>
  basic_path<char, K>
  relative (const basic_path<char, K>& p)
  {
    typedef basic_path<char, K> path;

    const dir_path& b (*relative_base);

    if (b.empty ())
      return p;

    if (p.sub (b))
      return p.leaf (b);

    // If base is a sub-path of {src,out}_root and this path is also a
    // sub-path of it, then use '..' to form a relative path.
    //
    // Don't think this is a good heuristic. For example, why shouldn't
    // we display paths from imported projects as relative if they are
    // more readable than absolute?
    //
    /*
    if ((work.sub (src_root) && p.sub (src_root)) ||
        (work.sub (out_root) && p.sub (out_root)))
      return p.relative (work);
    */

    if (p.root_directory () == b.root_directory ())
    {
      path r (p.relative (b));

      if (r.string ().size () < p.string ().size ())
        return r;
    }

    return p;
  }
}