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>
24#include <filesystem/filename.h>
28#include <timely/time_stamp.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
36using namespace application;
37//using namespace basis;
38using namespace filesystem;
39using namespace loggers;
40using namespace processes;
41using namespace structures;
42using namespace timely;
43using namespace versions;
44
45//#define DEBUG_VSTS_VERSION_FIXER
46 // uncomment for noisy version.
47
49
50class vsts_version_fixer : public application::application_shell
51{
52public:
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
91HOOPLE_MAIN(vsts_version_fixer, )
92
93
94
95//hmmm: move to a useful place; maybe even in directory class?
96bool 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
134bool 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.
168basis::un_int 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
181void 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
206bool 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
238bool 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
247void 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
281int 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;
296LOG(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()) {
301LOG(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 }
316LOG(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:
329 #include <algorithms/sorts.cpp>
334 #include <basis/astring.cpp>
336 #include <basis/environment.cpp>
337 #include <basis/guards.cpp>
338 #include <basis/mutex.cpp>
339 #include <basis/utf_conversion.cpp>
347 #include <filesystem/directory.cpp>
348 #include <filesystem/filename.cpp>
349 #include <loggers/combo_logger.cpp>
352 #include <loggers/file_logger.cpp>
356 #include <structures/checksums.cpp>
363 #include <textual/parser_bits.cpp>
365 #include <timely/earth_time.cpp>
366 #include <timely/time_control.cpp>
367 #include <timely/time_stamp.cpp>
368 #include <versions/version_ini.cpp>
369#endif // __BUILD_STATIC_APPLICATION__
370
The application_shell is a base object for console programs.
virtual int execute()=0
< retrieves the command line from the /proc hierarchy on linux.
application_shell()
constructs an application_shell to serve as the root of the program.
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:568
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.
const structures::string_array & files() const
returns the list of files that we found in this directory.
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
@ AWAIT_APP_EXIT
stays in the function until the launched application has exited.
static basis::un_int run(const basis::astring &app_name, const basis::astring &command_line, int flag, basis::un_int &child_id)
starts an application using the "app_name" as the executable to run.
An array of strings with some additional helpful methods.
static basis::astring notarize(bool add_space=true)
a useful method for getting a textual version of the time "right now".
static bool one_stop_version_stamp(const basis::astring &path, const basis::astring &header_store, const basis::astring &source_version, bool do_logging)
performs version stamping using the ini file in "path".
#define DEFINE_CLASS_NAME(objname)
Defines the name of a class by providing a couple standard methods.
Definition enhance_cpp.h:42
#define FUNCDEF(func_in)
FUNCDEF sets the name of a function (and plugs it into the callstack).
Definition enhance_cpp.h:54
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
A platform independent way to obtain the timestamp of a file.
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>
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.