summaryrefslogtreecommitdiffstats
path: root/Source/cmUVProcessChain.h
blob: 139588b93005685d517f88b30511f66a72eb8935 (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
/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file Copyright.txt or https://cmake.org/licensing for details.  */
#pragma once

#include "cmConfigure.h" // IWYU pragma: keep

#include <array>
#include <cstddef> // IWYU pragma: keep
#include <cstdint>
#include <memory>
#include <string>
#include <utility>
#include <vector>

#include <cm3p/uv.h>

class cmUVProcessChain;

class cmUVProcessChainBuilder
{
public:
  enum Stream
  {
    Stream_INPUT = 0,
    Stream_OUTPUT = 1,
    Stream_ERROR = 2,
  };

  cmUVProcessChainBuilder();

  cmUVProcessChainBuilder& AddCommand(
    const std::vector<std::string>& arguments);
  cmUVProcessChainBuilder& SetBuiltinLoop();
  cmUVProcessChainBuilder& SetExternalLoop(uv_loop_t& loop);
  cmUVProcessChainBuilder& SetNoStream(Stream stdio);
  cmUVProcessChainBuilder& SetBuiltinStream(Stream stdio);
  cmUVProcessChainBuilder& SetMergedBuiltinStreams();
  cmUVProcessChainBuilder& SetExternalStream(Stream stdio, int fd);
  cmUVProcessChainBuilder& SetWorkingDirectory(std::string dir);

  uv_loop_t* GetLoop() const;

  cmUVProcessChain Start() const;

private:
  enum StdioType
  {
    None,
    Builtin,
    External,
  };

  friend class cmUVProcessChain;

  struct StdioConfiguration
  {
    StdioType Type;
    int FileDescriptor;
  };

  struct ProcessConfiguration
  {
    std::vector<std::string> Arguments;
  };

  std::array<StdioConfiguration, 3> Stdio;
  std::vector<ProcessConfiguration> Processes;
  std::string WorkingDirectory;
  bool MergedBuiltinStreams = false;
  uv_loop_t* Loop = nullptr;
};

class cmUVProcessChain
{
public:
  enum class ExceptionCode
  {
    None,
    Fault,
    Illegal,
    Interrupt,
    Numerical,
    Spawn,
    Other,
  };

  struct Status
  {
    int SpawnResult;
    bool Finished;
    int64_t ExitStatus;
    int TermSignal;

    std::pair<ExceptionCode, std::string> GetException() const;
  };

  cmUVProcessChain(const cmUVProcessChain& other) = delete;
  cmUVProcessChain(cmUVProcessChain&& other) noexcept;

  ~cmUVProcessChain();

  cmUVProcessChain& operator=(const cmUVProcessChain& other) = delete;
  cmUVProcessChain& operator=(cmUVProcessChain&& other) noexcept;

  uv_loop_t& GetLoop();

  // FIXME: Add stdin support
  int OutputStream();
  int ErrorStream();

  bool Valid() const;
  bool Wait(uint64_t milliseconds = 0);
  std::vector<const Status*> GetStatus() const;
  const Status& GetStatus(std::size_t index) const;
  bool Finished() const;

private:
  friend class cmUVProcessChainBuilder;

  cmUVProcessChain();

  struct InternalData;
  std::unique_ptr<InternalData> Data;
};