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
#pragma once
///@file

#include <chrono>
#include <thread>

#include "lix/libutil/logging.hh"
#include "lix/libutil/sync.hh"

namespace nix {

struct ProgressBar : public Logger
{
    struct ActInfo
    {
        using TimePoint = std::chrono::time_point<std::chrono::steady_clock>;

        std::string s, lastLine, phase;
        ActivityType type = actUnknown;
        uint64_t done = 0;
        uint64_t expected = 0;
        uint64_t running = 0;
        uint64_t failed = 0;
        std::map<ActivityType, uint64_t> expectedByType;
        bool visible = true;
        ActivityId parent;
        std::optional<std::string> name;
        TimePoint startTime;
    };

    struct ActivitiesByType
    {
        std::map<ActivityId, std::list<ActInfo>::iterator> its;
        uint64_t done = 0;
        uint64_t expected = 0;
        uint64_t failed = 0;
    };

    struct State
    {
        std::list<ActInfo> activities;
        std::map<ActivityId, std::list<ActInfo>::iterator> its;

        std::map<ActivityType, ActivitiesByType> activitiesByType;

        int lastLines = 0;

        uint64_t filesLinked = 0, bytesLinked = 0;

        uint64_t corruptedPaths = 0, untrustedPaths = 0;

        uint32_t paused = 1;
        bool haveUpdate = false;
    };

    Sync<State> state_;

    std::thread updateThread;

    std::condition_variable quitCV, updateCV;

    bool printBuildLogs = false;
    bool printMultiline = false;
    bool isTTY;

    ProgressBar(bool isTTY);

    ~ProgressBar();

    void pause() override;

    void resetProgress() override;

    void resume() override;

    bool isVerbose() override;

    BufferState log(Verbosity lvl, std::string_view s) override;

    BufferState logEI(const ErrorInfo & ei) override;

    BufferState log(State & state, Verbosity lvl, std::string_view s);

    BufferState startActivityImpl(
        ActivityId act,
        Verbosity lvl,
        ActivityType type,
        const std::string & s,
        const Fields & fields,
        ActivityId parent
    ) override;

    bool hasAncestor(State & state, ActivityType type, ActivityId act);

    BufferState stopActivityImpl(ActivityId act) override;

    BufferState
    resultImpl(ActivityId act, ResultType type, const std::vector<Field> & fields) override;

    void update(State & state);

    std::string getStatus(State & state);

    void writeToStdout(std::string_view s) override;

    std::optional<char> ask(std::string_view msg) override;

    void setPrintBuildLogs(bool printBuildLogs) override;

    void setPrintMultiline(bool printMultiline) override;

private:
    void eraseProgressDisplay(State & state);

    std::chrono::milliseconds restoreProgressDisplay(State & state);
};

Logger * makeProgressBar();

}