1 // =================================
  2 // Copyright (c) 2021 Seppo Laakko
  3 // Distributed under the MIT license
  4 // =================================
  5 
  6 #include <cmajor/build/ClientCommand.hpp>
  7 #include <cmajor/build/BuildLangLexer.hpp>
  8 #include <cmajor/build/BuildLangClientParser.hpp>
  9 #include <cmajor/build/BuildOption.hpp>
 10 #include <cmajor/build/BuildServerMessage.hpp>
 11 #include <cmajor/build/Log.hpp>
 12 #include <cmajor/build/BuildClient.hpp>
 13 #include <cmajor/build/BuildServer.hpp>
 14 #include <cmajor/build/ServerConfig.hpp>
 15 #include <cmajor/build/FiberExecutionContext.hpp>
 16 #include <cmajor/build/LocalExecutionContext.hpp>
 17 #include <cmajor/build/ClientExecutionContext.hpp>
 18 #include <cmajor/symbols/GlobalFlags.hpp>
 19 #include <sngcm/ast/Project.hpp>
 20 #include <soulng/util/Fiber.hpp>
 21 #include <soulng/util/Unicode.hpp>
 22 #include <soulng/util/Error.hpp>
 23 #include <soulng/util/Path.hpp>
 24 #include <soulng/util/Log.hpp>
 25 
 26 namespace cmajor { namespace build {
 27 
 28 using namespace soulng::unicode;
 29 using namespace cmajor::symbols;
 30 using namespace sngcm::ast;
 31 
 32 std::string GetFilePath(const std::string& path)
 33 {
 34     Assert(path.size() >= 2"invalid path");
 35     Assert(path[0] == '<' && path[path.size() - 1] == '>'"invalid path");
 36     std::string p = path.substr(1path.size() - 2);
 37     if (p == "system")
 38     {
 39         return GetFullPath(Path::Combine(Path::Combine(Path::Combine(CmajorRootDir()"system")"System.Install")"System.Install.cmp"));
 40     }
 41     return GetFullPath(p);
 42 }
 43 
 44 std::std::unique_ptr<ExecutionContext>CreateExecutionContext(conststd::string&serverName)
 45 {
 46     if (serverName.empty())
 47     {
 48         return std::unique_ptr<ExecutionContext>(new FiberExecutionContext());
 49     }
 50     else if (serverName == "local")
 51     {
 52         return std::unique_ptr<ExecutionContext>(new LocalExecutionContext());
 53     }
 54     else
 55     {
 56         return std::unique_ptr<ExecutionContext>(new ClientExecutionContext(serverName));
 57     }
 58 }
 59 
 60 ClientCommand::ClientCommand()
 61 {
 62 }
 63 
 64 ClientCommand::~ClientCommand()
 65 {
 66 }
 67 
 68 PushProjectClientCommand::PushProjectClientCommand(const std::string& projectFilePath_const std::string& serverName_) :
 69     projectFilePath(GetFilePath(projectFilePath_))serverName(serverName_)
 70 {
 71 }
 72 
 73 void PushProjectClientCommand::Execute()
 74 {
 75     std::set<std::string> pushedProjects;
 76     std::unique_ptr<ExecutionContext> context = CreateExecutionContext(serverName);
 77     context->GetClient()->PushProject(projectFilePathpushedProjects);
 78     Connection* connection = context->GetConnection();
 79     if (connection)
 80     {
 81         if (GetGlobalFlag(GlobalFlags::printDebugMessages))
 82         {
 83             LogMessage(-1"buildclient: closing connection");
 84         }
 85         if (connection->ServerAlive())
 86         {
 87             connection->SetServerAlive(false);
 88             CloseConnectionRequest closeConnectionRequest;
 89             closeConnectionRequest.SendTo(*connection);
 90         }
 91         connection->Close();
 92     }
 93     if (serverName.empty())
 94     {
 95         LogMessage(-1"project '" + projectFilePath + "' pushed to local build repository");
 96     }
 97     else
 98     {
 99         LogMessage(-1"project '" + projectFilePath + "' pushed to server '" + serverName + "'");
100     }
101 }
102 
103 RemoveProjectClientCommand::RemoveProjectClientCommand(const std::string& projectFilePath_const std::string& serverName_) :
104     projectFilePath(GetFilePath(projectFilePath_))serverName(serverName_)
105 {
106 }
107 
108 void RemoveProjectClientCommand::Execute()
109 {
110 }
111 
112 RemoveServerClientCommand::RemoveServerClientCommand(const std::string& serverName_) : serverName(serverName_)
113 {
114 }
115 
116 void RemoveServerClientCommand::Execute()
117 {
118     ServerConfig::Instance().Remove(serverName);
119     LogMessage(-1"server '" + serverName + "' removed");
120 }
121 
122 AddServerClientCommand::AddServerClientCommand(const std::string& serverName_const std::string& host_int port_const std::string& defaultToolChain_) :
123     serverName(serverName_)host(host_)port(port_)defaultToolChain(defaultToolChain_)
124 {
125 }
126 
127 void AddServerClientCommand::Execute()
128 {
129     bool force = false;
130     if (GetBuildOption(BuildOptions::force))
131     {
132         force = true;
133     }
134     ServerConfig::Instance().Add(serverNamehostportdefaultToolChainforcetruetrue);
135     LogMessage(-1"server '" + serverName + "' added");
136 }
137 
138 BuildProjectClientCommand::BuildProjectClientCommand(const std::string& projectFilePath_const std::string& serverName_) :
139     projectFilePath(GetFilePath(projectFilePath_))serverName(serverName_)
140 {
141 }
142 
143 void BuildProjectClientCommand::Execute()
144 {
145     std::unique_ptr<ExecutionContext> context = CreateExecutionContext(serverName);
146     std::string config = buildConfig;
147     std::string toolChain = buildToolChain;
148     bool printBuildOutput = GetBuildOption(BuildOptions::messages);
149     bool rebuild = GetBuildOption(BuildOptions::rebuild);
150     bool only = GetBuildOption(BuildOptions::only);
151     context->GetClient()->BuildProject(projectFilePathconfigtoolChainrebuildonlyprintBuildOutput);
152     Connection* connection = context->GetConnection();
153     if (connection)
154     {
155         if (GetGlobalFlag(GlobalFlags::printDebugMessages))
156         {
157             LogMessage(-1"buildclient: closing connection");
158         }
159         if (connection->ServerAlive())
160         {
161             connection->SetServerAlive(false);
162             CloseConnectionRequest closeConnectionRequest;
163             closeConnectionRequest.SendTo(*connection);
164         }
165         connection->Close();
166     }
167     if (serverName.empty())
168     {
169         LogMessage(-1"project '" + projectFilePath + "' built using local build repository");
170     }
171     else
172     {
173         LogMessage(-1"project '" + projectFilePath + "' built using server '" + serverName + "'");
174     }
175 }
176 
177 DebugProjectClientCommand::DebugProjectClientCommand(const std::string& projectFilePath_const std::string& serverName_) :
178     projectFilePath(GetFilePath(projectFilePath_))serverName(serverName_)
179 {
180 }
181 
182 void DebugProjectClientCommand::Execute()
183 {
184 }
185 
186 InstallProjectClientCommand::InstallProjectClientCommand(const std::string& projectFilePath_const std::string& directory_const std::string& serverName_) :
187     projectFilePath(GetFilePath(projectFilePath_))directory(GetFilePath(directory_))serverName(serverName_)
188 {
189 }
190 
191 void InstallProjectClientCommand::Execute()
192 {
193 }
194 
195 ShowConfigurationClientCommand::ShowConfigurationClientCommand()
196 {
197 }
198 
199 void ShowConfigurationClientCommand::Execute()
200 {
201     ServerConfig::Instance().Show();
202 }
203 
204 std::std::unique_ptr<ClientCommand>ParseClientCommand(conststd::string&command)
205 {
206     BuildLangLexer lexer(ToUtf32(command)""0);
207     BuildOptionSetter optionSetter;
208     return BuildLangClientParser::Parse(lexer&optionSetter);
209 }
210 
211 } } // namespace cmajor::build;