feisty meow concerns codebase  2.140
vsts_version_fixer.cpp
Go to the documentation of this file.
1 /*****************************************************************************\
2 * *
3 * Name : vsts_version_fixer *
4 * Author : Chris Koeritz *
5 * *
6 *******************************************************************************
7 * Copyright (c) 2008-$now By Author. This program is free software; you can *
8 * redistribute it and/or modify it under the terms of the GNU General Public *
9 * License as published by the Free Software Foundation; either version 2 of *
10 * the License or (at your option) any later version. This is online at: *
11 * http://www.fsf.org/copyleft/gpl.html *
12 * Please send any updates to: fred@gruntose.com *
13 \*****************************************************************************/
14 
19 #include <basis/astring.h>
20 #include <basis/environment.h>
21 #include <basis/functions.h>
22 #include <filesystem/byte_filer.h>
23 #include <filesystem/directory.h>
24 #include <filesystem/filename.h>
28 #include <timely/time_stamp.h>
29 #include <versions/version_ini.h>
30 
31 #undef LOG
32 #define LOG(s) CLASS_EMERGENCY_LOG(program_wide_logger::get(), s)
33 #undef BASE_LOG
34 #define BASE_LOG(s) program_wide_logger::get().log(s, ALWAYS_PRINT)
35 
36 using namespace application;
37 //using namespace basis;
38 using namespace filesystem;
39 using namespace loggers;
40 using namespace processes;
41 using namespace structures;
42 using namespace timely;
43 using namespace versions;
44 
45 //#define DEBUG_VSTS_VERSION_FIXER
46  // uncomment for noisy version.
47 
49 
50 class vsts_version_fixer : public application::application_shell
51 {
52 public:
53  vsts_version_fixer() : application_shell() {}
54  virtual ~vsts_version_fixer() {}
55 
56  virtual int execute();
57 
58  DEFINE_CLASS_NAME("vsts_version_fixer");
59 
60  void remove_confusing_files();
62 
63 //move these
64  typedef bool spider_method(const directory &current);
66 
71 //hmmm: support postfix and in order also.
72 //hmmm: support reporting where the spidering stopped.
73  bool spider_directory(directory start, spider_method to_invoke);
75 
77 //move those
78 
79  bool perform_version_stamping(const filename &start_name);
81 
82  void whack_in_subdirs(const directory &start,
83  const string_array &file_whacks, const string_array &dir_whacks);
85 
89 };
90 
91 HOOPLE_MAIN(vsts_version_fixer, )
92 
93 
95 //hmmm: move to a useful place; maybe even in directory class?
96 bool vsts_version_fixer::spider_directory(directory start,
97  spider_method to_invoke)
98 {
99  FUNCDEF("spider_directory");
100 
101  using namespace basis;
102 
103 //LOG(astring("spider_directory: ") + start.path());
104  // call our method on this directory first. this ensures that we have
105  // dealt with it before we spider off elsewhere.
106  bool ret = to_invoke(start);
107  if (!ret) return false; // bail.
108 
109  // now let's look at the subdirectories. we'll recurse on all of them in
110  // the order listed.
111  const string_array &dirs = start.directories();
112 //LOG(astring("dirs found to spider: ") + dirs.text_form());
113  for (int dir_indy = 0; dir_indy < dirs.length(); dir_indy++) {
114  const astring &current_dir = dirs[dir_indy];
115 //LOG(astring("currdir into ") + current_dir);
116  if (current_dir.equal_to(".svn")) continue; // skip this.
117  if (current_dir.equal_to("CVS")) continue; // skip this also.
118  directory new_dir(start.path() + "/" + current_dir, start.pattern().observe());
119  bool ret = spider_directory(new_dir, to_invoke);
120  if (!ret) return false; // bail from subdir issue.
121  }
122  // if we made it to here, everything was groovy.
123  return true;
124 }
125 
127 
128 #define static_class_name() "vsts_version_fixer"
129 
130 // global variables used to communicate with whacking_spider.
133 
134 bool whacking_spider(const directory &current)
135 {
136  FUNCDEF("whacking_spider");
137  using namespace basis;
138 //LOG(astring("whacking_spider: ") + current.path());
139  // iterate across the files in the directory and check for evil ones.
140  const string_array &files = current.files();
141  for (int file_indy = 0; file_indy < files.length(); file_indy++) {
142  const astring &current_file = files[file_indy];
143 //LOG(astring("currfile ") + current_file);
144  // now iterate across our pattern list to see if this thing is
145  // one of the offending files.
146  for (int pat_indy = 0; pat_indy < global_file_whacks.length(); pat_indy++) {
147 //LOG(astring("currpat ") + global_file_whacks[pat_indy]);
148  if (current_file.iends(global_file_whacks[pat_indy])) {
149  filename goner(current.path() + "/" + current_file);
150  BASE_LOG(astring("whack file: ") + goner.raw());
151  goner.unlink();
152  break; // stop looking at the pattern list for matches.
153  }
154  }
155  }
156 
157  // okay, now that we've cleaned out those files, let's look at the
158  // subdirectories.
159  const string_array &dirs = current.directories();
160  for (int dir_indy = 0; dir_indy < dirs.length(); dir_indy++) {
161  const astring &current_dir = dirs[dir_indy];
162 //LOG(astring("currdir ") + current_dir);
163  for (int pat_indy = 0; pat_indy < global_dir_whacks.length(); pat_indy++) {
164  if (current_dir.iequals(global_dir_whacks[pat_indy])) {
165  filename goner(current.path() + "/" + current_dir);
166  BASE_LOG(astring("whack dir: ") + goner.raw());
167 //hmmm: plug in recursive delete here instead.
168 basis::un_int kid;
169 launch_process::run("rm", astring("-rf ") + goner.raw(), launch_process::AWAIT_APP_EXIT, kid);
170  break; // skip remainder of patterns for this dir.
171  }
172  }
173  }
174  return true;
175 }
176 
177 #undef static_class_name
178 
180 
181 void vsts_version_fixer::whack_in_subdirs(const directory &start,
182  const string_array &file_whacks, const string_array &dir_whacks)
183 {
184  FUNCDEF("whack_in_subdirs");
185  using namespace basis;
186 
187  // save the lists so the spider method can see them.
188  // note that this approach with a global variable would be bad if there
189  // were concurrent invocations of the spidering, but we're not doing
190  // that here.
191  global_file_whacks = file_whacks;
192  global_dir_whacks = dir_whacks;
193 
194  bool worked = spider_directory(start, whacking_spider);
195  if (!worked) {
196  LOG(astring("spidering of ") + start.path() + " failed for some reason.");
197  }
198 }
199 
201 
202 #define static_class_name() "vsts_version_fixer"
203 
205 
206 bool stamping_spider(const directory &current)
207 {
208  FUNCDEF("stamping_spider");
209  using namespace basis;
210 //LOG(astring("stamping_spider: ") + current.path());
211 
212  const string_array &files = current.files();
213  for (int file_indy = 0; file_indy < files.length(); file_indy++) {
214  const astring &current_file = files[file_indy];
215 //LOG(astring("currfile ") + current_file);
216  // we won't process the "core_version.ini" file, which is a special
217  // case that is somewhat well known as not being a file used (by us)
218  // for dlls.
219  if (current_file.ends("version.ini")
220  && !current_file.iequals("core_version.ini") ) {
221 //LOG(astring("found ver file: ") + current.path() + "/" + current_file);
222 //
223  astring versions_directory = environment::get("FEISTY_MEOW_GENERATED_STORE");
224  // we keep our version files one level below the top of the generated store.
225  versions_directory += "/versions";
226 
227  version_ini::one_stop_version_stamp(current.path() + "/" + current_file,
228  versions_directory, global_build_ini, true);
229  }
230  }
231  return true;
232 }
233 
234 #undef static_class_name
235 
237 
238 bool vsts_version_fixer::perform_version_stamping(const filename &start_name)
239 {
240  FUNCDEF("perform_version_stamping");
241  directory start(start_name);
242  return spider_directory(start, stamping_spider);
243 }
244 
246 
247 void vsts_version_fixer::remove_confusing_files()
248 {
249  using namespace basis;
250  // clean out a few directories that show up in the source tree from c#
251  // projects compilation. c# projects always rebuild every time anyways,
252  // so this doesn't lose us any compilation time. the only thing c#
253  // projects don't ever seem to rebuild is their version resource, unless
254  // they're forced to totally recompile like we cause below.
255  string_array source_file_whacks; // none right now.
256  string_array source_dir_whacks;
257  source_dir_whacks += "obj";
258  source_dir_whacks += "Debug";
259  source_dir_whacks += "Release";
260  source_dir_whacks += "bin";
261  source_dir_whacks += "temp_build";
262  directory repo_source(environment::get("FEISTY_MEOW_APEX") + "/source");
263  whack_in_subdirs(repo_source, source_file_whacks, source_dir_whacks);
264  directory libra_src(environment::get("FEISTY_MEOW_APEX") + "/libraries");
265  whack_in_subdirs(libra_src, source_file_whacks, source_dir_whacks);
266  directory produ_src(environment::get("FEISTY_MEOW_APEX") + "/products");
267  whack_in_subdirs(produ_src, source_file_whacks, source_dir_whacks);
268 
269 /* this never helped.
270  // clean out a variety of bad files in the objects hierarchy.
271  // currently this is just the generated RES files which we have seen cause
272  // vsts to think apps and dlls are up to date when they are actually not.
273  directory repo_objects(environment::get("FEISTY_MEOW_APEX"));
274  string_array objects_file_whacks;
275  objects_file_whacks += ".res";
276  string_array objects_dir_whacks; // none right now.
277  whack_in_subdirs(repo_objects, objects_file_whacks, objects_dir_whacks);
278 */
279 }
280 
281 int vsts_version_fixer::execute()
282 {
283  FUNCDEF("execute");
284  using namespace basis;
285  log(time_stamp::notarize(true) + "vsts_version_fixer started.", ALWAYS_PRINT);
286 
287  remove_confusing_files();
288 
289  astring repo_dir = environment::get("FEISTY_MEOW_APEX");
290 
291  // figure out which build parameter file to use.
292  global_build_ini = "";
293  astring parmfile = environment::get("BUILD_PARAMETER_FILE");
294  if (parmfile.t()) {
295  global_build_ini = parmfile;
296 LOG(astring("found parm variable ") + parmfile);
297  } else {
298  // they didn't specify the file. argh.
299  global_build_ini = repo_dir + "/production/feisty_meow_config.ini";
300  if (!filename(global_build_ini).exists()) {
301 LOG(astring("guess not found: ") + global_build_ini);
302  LOG("cannot locate the build configuration file.");
303  return 3;
304  }
305  }
306 
307  // now stamp versions on everything we can find.
308  filename repo_source = repo_dir + "/../../libraries";
309  if (!repo_source.exists()) {
310  repo_source = repo_dir + "/source";
311  if (!repo_source.exists()) {
312  LOG("cannot locate the main library source location.");
313  return 3;
314  }
315  }
316 LOG(astring("chose source dir as ") + repo_source);
317  perform_version_stamping(repo_source);
318 
319  filename repo_apps = repo_dir + "/../../products";
320  if (repo_apps.exists()) {
321  perform_version_stamping(repo_apps);
322  }
323  log(time_stamp::notarize(true) + "vsts_version_fixer finished.", ALWAYS_PRINT);
324  return 0;
325 }
326 
327 #ifdef __BUILD_STATIC_APPLICATION__
328  // static dependencies found by buildor_gen_deps.sh:
332  #include <basis/astring.cpp>
333  #include <basis/common_outcomes.cpp>
334  #include <basis/environment.cpp>
335  #include <basis/guards.cpp>
336  #include <basis/mutex.cpp>
337  #include <basis/utf_conversion.cpp>
344  #include <filesystem/byte_filer.cpp>
345  #include <filesystem/directory.cpp>
346  #include <filesystem/filename.cpp>
347  #include <loggers/combo_logger.cpp>
348  #include <loggers/console_logger.cpp>
349  #include <loggers/critical_events.cpp>
350  #include <loggers/file_logger.cpp>
353  #include <structures/bit_vector.cpp>
354  #include <structures/checksums.cpp>
358  #include <structures/string_table.cpp>
360  #include <textual/byte_formatter.cpp>
361  #include <textual/parser_bits.cpp>
363  #include <timely/earth_time.cpp>
364  #include <timely/time_control.cpp>
365  #include <timely/time_stamp.cpp>
366  #include <versions/version_ini.cpp>
367 #endif // __BUILD_STATIC_APPLICATION__
368 
The application_shell is a base object for console programs.
int length() const
Returns the current reported length of the allocated C array.
Definition: array.h:115
Provides a dynamically resizable ASCII character string.
Definition: astring.h:35
bool t() const
t() is a shortcut for the string being "true", as in non-empty.
Definition: astring.h:97
bool ends(const astring &maybe_suffix) const
returns true if this string ends with "maybe_suffix".
Definition: astring.h:187
bool iequals(const astring &that) const
returns true if this is case-insensitively equal to "that".
Definition: astring.cpp:565
bool equal_to(const char *that) const
returns true if "that" is equal to this.
Definition: astring.cpp:159
bool iends(const astring &maybe_suffix) const
Definition: astring.h:192
Implements a scanner that finds all filenames in the directory specified.
Definition: directory.h:27
const structures::string_array & directories() const
these are the directory names from the folder.
Definition: directory.cpp:145
const structures::string_array & files() const
returns the list of files that we found in this directory.
Definition: directory.cpp:143
const basis::astring & path() const
returns the directory that we manage.
Definition: directory.cpp:89
Provides operations commonly needed on file names.
Definition: filename.h:64
bool exists() const
returns true if the file exists.
Definition: filename.cpp:426
const basis::astring & raw() const
returns the astring that we're holding onto for the path.
Definition: filename.cpp:97
bool unlink() const
actually removes the file, if possible.
Definition: filename.cpp:101
An array of strings with some additional helpful methods.
Definition: string_array.h:32
#define DEFINE_CLASS_NAME(objname)
Defines the name of a class by providing a couple standard methods.
Definition: enhance_cpp.h:45
#define FUNCDEF(func_in)
FUNCDEF sets the name of a function (and plugs it into the callstack).
Definition: enhance_cpp.h:57
Provides macros that implement the 'main' program of an application.
#define HOOPLE_MAIN(obj_name, obj_args)
options that should work for most unix and linux apps.
Definition: hoople_main.h:61
Implements an application lock to ensure only one is running at once.
The guards collection helps in testing preconditions and reporting errors.
Definition: array.h:30
unsigned int un_int
Abbreviated name for unsigned integers.
Definition: definitions.h:62
list files
Definition: eml_to_txt.py:157
A platform independent way to obtain the timestamp of a file.
Definition: byte_filer.cpp:37
A logger that sends to the console screen using the standard output device.
A dynamic container class that holds any kind of object via pointers.
Definition: amorph.h:55
#include <time.h>
Definition: earth_time.cpp:37
basis::astring global_build_ini
#define LOG(s)
string_array global_dir_whacks
string_array global_file_whacks
#define BASE_LOG(s)
bool stamping_spider(const directory &current)
bool whacking_spider(const directory &current)
Aids in achievement of platform independence.