CASM  1.1.0
A Clusters Approach to Statistical Mechanics
casm_functions.cc
Go to the documentation of this file.
2 
3 #include <boost/filesystem.hpp>
4 #include <boost/filesystem/fstream.hpp>
5 
6 #include "casm/app/APICommand.hh"
9 #include "casm/app/bset.hh"
10 #include "casm/app/composition.hh"
11 #include "casm/app/enum.hh"
12 #include "casm/app/files.hh"
13 #include "casm/app/format.hh"
14 #include "casm/app/import.hh"
15 #include "casm/app/info.hh"
16 #include "casm/app/init.hh"
17 #include "casm/app/monte.hh"
18 #include "casm/app/query.hh"
19 #include "casm/app/ref.hh"
20 #include "casm/app/rm.hh"
21 #include "casm/app/run.hh"
22 #include "casm/app/select.hh"
23 #include "casm/app/settings.hh"
24 #include "casm/app/status.hh"
25 #include "casm/app/super.hh"
26 #include "casm/app/sym.hh"
27 #include "casm/app/update.hh"
28 #include "casm/app/view.hh"
29 #include "casm/casm_io/Log.hh"
30 #include "casm/clex/PrimClex.hh"
31 #include "casm/external/gzstream/gzstream.h"
32 #include "casm/misc/algorithm.hh"
33 #include "casm/version/version.hh"
34 
35 namespace CASM {
36 
37 void print_splash(std::ostream &out) {
38  out << " .::::::::. .:::::. .::::::. .:. "
39  ".:. \n"
40  << " .:::::::::::. .:::::::. .::::::::::. .:::. "
41  ".:::. \n"
42  << " .:::' ':::. .:::' ':::. .:::' ':::: .:::::. "
43  ".:::::. \n"
44  << " :::: :::: .:::' ':::. :::: '::' .:::::::. "
45  ".:::::::. \n"
46  << " :::: :::: :::: '::::. "
47  "::::'':::.:::'':::: \n"
48  << " :::: :::: :::: '::::::. :::: "
49  "':::::' :::: \n"
50  << " :::: ::::::::::::: ''::::::. :::: ':::' "
51  " :::: \n"
52  << " :::: ::::::::::::: ':::::: :::: ':' "
53  " :::: \n"
54  << " :::: .:::: :::: :::: ::::: :::: "
55  " :::: \n"
56  << " ':::. .::::' :::: :::: .::. .:::: :::: "
57  " :::: \n"
58  << " '::::::::::' :::: :::: :::::...:::::' :::: "
59  " :::: \n"
60  << " ':::::' '::' '::' ':::::::::::' '::' "
61  " '::' \n";
62 }
63 
72 CommandArgs::CommandArgs(int _argc, char *_argv[], PrimClex *_primclex,
73  fs::path _root)
74  : CLIParse(_argc, _argv), primclex(_primclex), root(_root) {
75  _init();
76 }
77 
85 CommandArgs::CommandArgs(std::string _args, PrimClex *_primclex, fs::path _root)
86  : CLIParse(_args), primclex(_primclex), root(_root) {
87  _init();
88 }
89 
91 
93  // set project 'root' if not already set
94  if (root.empty()) {
95  root = find_casmroot(fs::current_path());
96  }
97 
98  // set 'command'
99  command = (argc() > 1) ? std::string(argv()[1]) : "";
100 
101  if (command == "--version") {
102  command = "version";
103  }
104 
105  // check if 'help' command
106  std::vector<std::string> help_commands{
107  "help", "-h", "--help", "version", "--version", "status", "format"};
108  is_help = contains(help_commands, command);
109 
110  // check if LOG should be written
111  write_log = !(is_help || root.empty() || command == "init");
112 }
113 
116  static CommandMap command_map{
117  {"version", version_command},
118  {"status", status_command},
119  {"format", format_command},
120  {"init", init_command},
121  {"info", run_api_command<InfoCommand>},
122  {"settings", settings_command},
123  {SymCommand::name, run_api_command<SymCommand>},
124  {"composition", composition_command},
125  {"ref", ref_command},
126  {UpdateCommand::name, run_api_command<UpdateCommand>},
127  {EnumCommand::name, run_api_command<EnumCommand>},
128  {"super", super_command},
129  {SelectCommand::name, run_api_command<SelectCommand>},
130  {"bset", run_api_command<BsetCommand>},
131  {"run", run_command},
132  {RmCommand::name, run_api_command<RmCommand>},
133  {QueryCommand::name, run_api_command<QueryCommand>},
134  {"files", files_command},
135  {ImportCommand::name, run_api_command<ImportCommand>},
136  {"monte", monte_command},
137  {"view", view_command},
138  {"help", help_command}};
139 
140  return command_map;
141 }
142 
143 namespace api_impl {
144 
145 std::string date_time() {
146  auto t = std::time(nullptr);
147  char str[255];
148  strftime(str, sizeof(str), "%Y-%m-%d %H:%M:%S", std::localtime(&t));
149  return std::string(str);
150 };
151 
152 void write_LOG_begin(const CommandArgs &args) {
153  // If not a 'version', or 'help' command, write to LOG
154  fs::ofstream log(args.root / "LOG", std::ofstream::out | std::ofstream::app);
155  log << "# " << date_time() << std::endl;
156 
157  // record whoami@hostname
158 
159  std::string whoami, hostname;
160  {
161  FILE *fp;
162  char path[PATH_MAX];
163  fp = popen("whoami", "r");
164  while (fgets(path, PATH_MAX, fp) != NULL) {
165  whoami = std::string(path);
166  whoami.resize(whoami.size() - 1);
167  }
168  }
169  {
170  FILE *fp;
171  char path[PATH_MAX];
172  fp = popen("hostname", "r");
173  while (fgets(path, PATH_MAX, fp) != NULL) {
174  hostname = std::string(path);
175  hostname.resize(hostname.size() - 1);
176  }
177  }
178  log << "# " << whoami << "@" << hostname << "\n";
179 
180  // record CASM version number
181  log << "# " << version() << "\n";
182 
183  // record command arguments
184  for (int i = 0; i < args.argc(); i++) {
185  log << args.argv()[i] << " ";
186  }
187  log << "\n";
188  log.close();
189 }
190 
191 void write_LOG_end(const CommandArgs &args, int retcode) {
192  fs::ofstream log(args.root / "LOG", std::ofstream::out | std::ofstream::app);
193  log << "# return: " << retcode << " runtime(s): " << CASM::log().time_s()
194  << "\n\n";
195  log.close();
196 }
197 
198 } // namespace api_impl
199 
201 int casm_api(const CommandArgs &args) {
202  if (args.argc() == 1) {
203  help_command(args);
204  return ERR_INVALID_ARG;
205  }
206 
207  auto it = command_map().find(args.command);
208  if (it != command_map().end()) {
209  if (args.write_log) {
211  }
212 
214  int retcode = it->second(args);
215  if (args.write_log) {
216  api_impl::write_LOG_end(args, retcode);
217  }
218  return retcode;
219  } else {
220  help_command(args);
221  return ERR_INVALID_ARG;
222  }
223 }
224 
236  std::unique_ptr<PrimClex> &uniq_primclex) {
237  if (!args.primclex) {
238  uniq_primclex.reset(new PrimClex(args.root));
239  return *uniq_primclex;
240  }
241  return *args.primclex;
242 }
243 
254 std::ostream &make_ostream_if(bool output, std::ostream &sout,
255  std::unique_ptr<std::ostream> &fout,
256  fs::path out_path, bool gzip) {
257  if (output) {
258  if (out_path.string() == "STDOUT") {
259  return sout;
260  }
261 
262  out_path = fs::absolute(out_path);
263 
264  if (gzip) {
265  fout.reset(new gz::ogzstream(out_path.string().c_str()));
266  return *fout;
267  }
268 
269  fout.reset(new fs::ofstream(out_path));
270  return *fout;
271  } else {
272  return sout;
273  }
274 }
275 
277 int help_command(const CommandArgs &args) {
278  log().custom("casm usage");
279  log() << "\n";
280 
281  log() << "casm [--version] <command> [options] [args]" << std::endl
282  << std::endl;
283  log() << "available commands:" << std::endl;
284 
285  std::vector<std::string> subcom;
286  for (auto it = command_map().begin(); it != command_map().end(); ++it) {
287  std::string s = it->first;
288  // check for --version
289  if (s[0] != '-') {
290  subcom.push_back(std::string(" ") + s);
291  }
292  }
293 
294  std::sort(subcom.begin(), subcom.end());
295  for (auto it = subcom.begin(); it != subcom.end(); ++it) {
296  log() << *it << "\n";
297  }
298  log() << "\n";
299 
300  log() << "For help using a command: 'casm <command> --help'" << std::endl
301  << std::endl;
302  log() << "For step by step help use: 'casm status -n'" << std::endl
303  << std::endl;
304 
305  return 0;
306 };
307 
308 int version_command(const CommandArgs &args) {
309  log() << "casm version: " << version() << std::endl;
310  return 0;
311 }
312 
313 } // namespace CASM
std::set< std::string > & s
#define ERR_INVALID_ARG
Definition: errors.hh:7
int argc() const
Definition: CLIParse.hh:20
char ** argv() const
Definition: CLIParse.hh:22
static const std::string name
Definition: enum.hh:31
static const std::string name
Definition: import.hh:50
void custom(const std::string &what)
Definition: Log.hh:139
double time_s() const
Definition: Log.cc:41
void restart_clock()
Definition: Log.cc:35
PrimClex is the top-level data structure for a CASM project.
Definition: PrimClex.hh:55
static const std::string name
Definition: query.hh:61
static const std::string name
Definition: rm.hh:46
static const std::string name
Definition: select.hh:56
static const std::string name
Definition: sym.hh:18
static const std::string name
Definition: update.hh:41
CommandMap & command_map()
Return static CommandMap containing all CASM API commands.
int version_command(const CommandArgs &args)
int help_command(const CommandArgs &args)
Print CASM help info to log()
std::ostream & make_ostream_if(bool output, std::ostream &sout, std::unique_ptr< std::ostream > &fout, fs::path out_path, bool gzip)
Return a reference to proper std::ostream.
std::map< std::string, Command > CommandMap
int casm_api(const CommandArgs &args)
Executes CASM commands specified by args.
PrimClex & make_primclex_if_not(const CommandArgs &args, std::unique_ptr< PrimClex > &uniq_primclex)
If !_primclex, construct new PrimClex stored in uniq_primclex, then return reference to existing or c...
std::string date_time()
void write_LOG_begin(const CommandArgs &args)
void write_LOG_end(const CommandArgs &args, int retcode)
Main CASM namespace.
Definition: APICommand.hh:8
int format_command(const CommandArgs &args)
Definition: format.cc:46
int view_command(const CommandArgs &args)
Definition: view.cc:46
Log & log()
Definition: Log.hh:424
void print_splash(std::ostream &out)
int files_command(const CommandArgs &args)
Definition: files.cc:47
fs::path find_casmroot(const fs::path &cwd)
int super_command(const CommandArgs &args)
Definition: super.cc:129
int status_command(const CommandArgs &args)
Definition: status.cc:364
int run_command(const CommandArgs &args)
Definition: run.cc:40
bool contains(const Container &container, const T &value)
Equivalent to container.end() != std::find(container.begin(), container.end(), value)
Definition: algorithm.hh:83
int settings_command(const CommandArgs &args)
Definition: settings.cc:283
const std::string & version()
Definition: autoversion.cc:14
int init_command(const CommandArgs &args)
Definition: init.cc:139
int monte_command(const CommandArgs &args)
Definition: monte.cc:123
int ref_command(const CommandArgs &args)
Definition: ref.cc:177
int composition_command(const CommandArgs &args)
Definition: composition.cc:69
PrimClex * primclex
Definition: settings.cc:135
Data structure holding basic CASM command info.
CommandArgs(int _argc, char *_argv[], PrimClex *_primclex=nullptr, fs::path _root=fs::path())
CommandArgs constructor.
std::string command
~CommandArgs()
CommandArgs destructor.