aboutsummaryrefslogtreecommitdiff
path: root/src/libstore/build-result.hh
blob: 8840fa7e3404485b64f68c07e11c139faadc44d0 (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
#pragma once
///@file

#include "realisation.hh"
#include "derived-path.hh"
#include "comparator.hh"

#include <string>
#include <chrono>
#include <optional>

namespace nix {

struct BuildResult
{
    /**
     * @note This is directly used in the nix-store --serve protocol.
     * That means we need to worry about compatability across versions.
     * Therefore, don't remove status codes, and only add new status
     * codes at the end of the list.
     */
    enum Status {
        Built = 0,
        Substituted,
        AlreadyValid,
        PermanentFailure,
        InputRejected,
        OutputRejected,
        /// possibly transient
        TransientFailure,
        /// no longer used
        CachedFailure,
        TimedOut,
        MiscFailure,
        DependencyFailed,
        LogLimitExceeded,
        NotDeterministic,
        ResolvesToAlreadyValid,
        NoSubstituters,
    } status = MiscFailure;

    /**
     * Information about the error if the build failed.
     *
     * @todo This should be an entire ErrorInfo object, not just a
     * string, for richer information.
     */
    std::string errorMsg;

    std::string toString() const {
        auto strStatus = [&]() {
            switch (status) {
                case Built: return "Built";
                case Substituted: return "Substituted";
                case AlreadyValid: return "AlreadyValid";
                case PermanentFailure: return "PermanentFailure";
                case InputRejected: return "InputRejected";
                case OutputRejected: return "OutputRejected";
                case TransientFailure: return "TransientFailure";
                case CachedFailure: return "CachedFailure";
                case TimedOut: return "TimedOut";
                case MiscFailure: return "MiscFailure";
                case DependencyFailed: return "DependencyFailed";
                case LogLimitExceeded: return "LogLimitExceeded";
                case NotDeterministic: return "NotDeterministic";
                case ResolvesToAlreadyValid: return "ResolvesToAlreadyValid";
                case NoSubstituters: return "NoSubstituters";
                default: return "Unknown";
            };
        }();
        return strStatus + ((errorMsg == "") ? "" : " : " + errorMsg);
    }

    /**
     * How many times this build was performed.
     */
    unsigned int timesBuilt = 0;

    /**
     * If timesBuilt > 1, whether some builds did not produce the same
     * result. (Note that 'isNonDeterministic = false' does not mean
     * the build is deterministic, just that we don't have evidence of
     * non-determinism.)
     */
    bool isNonDeterministic = false;

    /**
     * For derivations, a mapping from the names of the wanted outputs
     * to actual paths.
     */
    SingleDrvOutputs builtOutputs;

    /**
     * The start/stop times of the build (or one of the rounds, if it
     * was repeated).
     */
    time_t startTime = 0, stopTime = 0;

    /**
     * User and system CPU time the build took.
     */
    std::optional<std::chrono::microseconds> cpuUser, cpuSystem;

    DECLARE_CMP(BuildResult);

    bool success()
    {
        return status == Built || status == Substituted || status == AlreadyValid || status == ResolvesToAlreadyValid;
    }

    void rethrow()
    {
        throw Error("%s", errorMsg);
    }
};

/**
 * A `BuildResult` together with its "primary key".
 */
struct KeyedBuildResult : BuildResult
{
    /**
     * The derivation we built or the store path we substituted.
     */
    DerivedPath path;
};

}