aboutsummaryrefslogtreecommitdiff
path: root/tests/wildcard/driver.cxx
blob: b3aae6250af82b39d332897edc64a6c78cb3b1a3 (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
// file      : tests/wildcard/driver.cxx -*- C++ -*-
// copyright : Copyright (c) 2014-2017 Code Synthesis Ltd
// license   : MIT; see accompanying LICENSE file

#include <string>
#include <vector>
#include <cassert>
#include <iostream>
#include <algorithm> // sort()
#include <exception>

#include <butl/path>
#include <butl/utility>    // operator<<(ostream, exception)
#include <butl/filesystem>

using namespace std;
using namespace butl;

// Disable arguments globbing that may be enabled by default for MinGW runtime.
//
// Note that if _CRT_glob symbol is not defined explicitly, then runtime will
// be bound to the one defined in the implicitly linked libmingw32.a library.
// Yet another (but more troublesome) way is to link CRT_noglob.o (from MinGW
// libraries directory) that provides exactly the same symbol definition.
//
#ifdef __MINGW32__
int _CRT_glob = 0;
#endif

// Usage: argv[0] (-m <pattern> <name> | -s [-n] <pattern> [<dir>])
//
// Execute actions specified by -m or -s options. Exit with code 0 if succeed,
// 1 if fail, 2 on the underlying OS error (print error description to STDERR).
//
// -m
//    Match a name against the pattern.
//
// -s
//    Search for paths matching the pattern in the directory specified (absent
//    directory means the current one). Print the matching canonicalized paths
//    to STDOUT in the ascending order. Succeed if at least one matching path
//    is found. Note that this option must go first in the command line,
//
// -n
//    Do not sort paths found.
//
int
main (int argc, const char* argv[])
try
{
  assert (argc >= 2);

  string op (argv[1]);
  bool match (op == "-m");
  assert (match || op == "-s");

  if (match)
  {
    assert (argc == 4);

    string pattern (argv[2]);
    string name (argv[3]);
    return path_match (pattern, name) ? 0 : 1;
  }
  else
  {
    assert (argc >= 3);

    bool sort (true);
    int i (2);
    for (; i != argc; ++i)
    {
      string o (argv[i]);
      if (o == "-n")
        sort = false;
      else
        break; // End of options.
    }

    assert (i != argc); // Still need pattern.
    path pattern (argv[i++]);

    dir_path start;
    if (i != argc)
      start = dir_path (argv[i++]);

    assert (i == argc); // All args parsed,

    vector<path> paths;
    auto add = [&paths] (path&& p) -> bool
    {
      paths.emplace_back (move (p.canonicalize ()));
      return true;
    };

    path_search (pattern, add, start);

    if (sort)
      std::sort (paths.begin (), paths.end ());

    for (const auto& p: paths)
      cout << p.representation () << endl;

    return paths.empty () ? 1 : 0;
  }
}
catch (const invalid_path& e)
{
  cerr << e << ": " << e.path << endl;
  return 2;
}
catch (const exception& e)
{
  cerr << e << endl;
  return 2;
}