1 //
2 // aegis - project change supervisor
3 // Copyright (C) 1995-2009, 2011, 2012 Peter Miller
4 // Copyright (C) 2007, 2008 Walter Franzini
5 //
6 // This program is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 3 of the License, or (at
9 // your option) any later version.
10 //
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with this program. If not, see <http://www.gnu.org/licenses/>.
18 //
19 
20 #ifndef LIBAEGIS_CHANGE_H
21 #define LIBAEGIS_CHANGE_H
22 
23 #include <libaegis/cstate.fmtgen.h>
24 #include <libaegis/fstate.fmtgen.h>
25 #include <libaegis/pconf.fmtgen.h>
26 #include <libaegis/view_path.h>
27 #include <libaegis/zero.h>
28 
29 class nstring_list; // forward
30 
31 //
32 // Name of the project configuration file,
33 // relative to the baseline/devdir root.
34 //
35 #define THE_CONFIG_FILE_OLD "config"
36 #define THE_CONFIG_FILE_NEW "aegis.conf"
37 
38 #include <libaegis/user.h>
39 
40 //
41 // Define a magic number to represent the trunk transaction
42 // of the project.  It has an exceptional file name.
43 //
44 #define TRUNK_CHANGE_NUMBER ((long)((~(unsigned long)0) >> 1))
45 
46 #define TIME_NOT_SET (time_t)0
47 #define UUID_NOT_SET (string_ty*)0
48 
49 struct string_list_ty; // forward
50 struct sub_context_ty; // forward
51 struct symtab_ty; // forward
52 class project; // forward
53 
54 class change
55 {
56 public:
57     /**
58       * The pointer typedef is provided so that clients of this
59       * interface may use change::pointer everywhere they need to point
60       * at a change instance, and only this typedef needs to be edited
61       * to use a variety of smart pointer instead.
62       */
63     typedef change *pointer;
64 
65     long                reference_count;
66     project          *pp;
67     long                number;
68     cstate_ty           *cstate_data;
69     string_ty           *cstate_filename;
70     int                 cstate_is_a_new_file;
71     fstate_ty           *fstate_data;
72     symtab_ty           *fstate_stp;
73     symtab_ty           *fstate_uuid_stp;
74     string_ty           *fstate_filename;
75     fstate_ty           *pfstate_data;
76     symtab_ty           *pfstate_stp;
77     symtab_ty           *pfstate_uuid_stp;
78     string_ty           *pfstate_filename;
79     int                 fstate_is_a_new_file;
80     string_ty           *top_path_unresolved;
81     string_ty           *top_path_resolved;
82     string_ty           *development_directory_unresolved;
83     string_ty           *development_directory_resolved;
84     string_ty           *integration_directory_unresolved;
85     string_ty           *integration_directory_resolved;
86     string_ty           *logfile;
87     pconf_ty            *pconf_data;
88     long                lock_magic;
89     int                 bogus;
90     string_ty           *architecture_name;
91     string_list_ty      *file_list[view_path_MAX];
92     bool                project_specific_setenv_performed;
93 
94     // NOTE: methods are sorted alphabetically.  To have methods
95     // grouped, make sure they change their suffix rather than their
96     // prefix.  E.g. thingumy_get and thingumy_set rather than
97     // get_thingumy and set_thingumy.
98 
99     // ----------  A  ------------------------------------------------------
100 
101     /**
102       * The attributes_get method is used to obtain the value of an
103       * attribute of this change set.
104       *
105       * @param name
106       *     The name of the attribute.
107       *     Attribute names are not case sensitive.
108       * @returns
109       *     the string value of the attribute, or the empty string
110       *     if not found.
111       */
112     nstring attributes_get(const nstring &name);
113 
114     /**
115       * The attributes_get_boolean method is used to obtain the
116       * value of an attribute of this change set, as a true/false
117       * attribute.
118       *
119       * @param name
120       *     The name of the attribute.
121       *     Attribute names are not case sensitive.
122       * @returns
123       *     the boolean value of the attribute, or false if the
124       *     attribute is not found or is not interpretable as a
125       *     boolean.
126       */
127     bool attributes_get_boolean(const nstring &name);
128 
129     // ----------  B  ------------------------------------------------------
130 
131     /**
132       * The brief_description_get method is used to obtain the brief
133       * description of this change set.
134       */
135     nstring brief_description_get(void);
136 
137     // ----------  C  ------------------------------------------------------
138 
139     /**
140       * The copyright_years_get_string is used to get a string
141       * containing the list fo copyrigth years, a union of the project's
142       * copyright years and this change set's copyright years.
143       */
144     nstring copyright_years_get_string(void);
145 
146     /**
147       * The completion_timestamp method is used to obtain the time that
148       * the change set completed integration, or "now" if it is not yet
149       * complete.  use the #is_completed method to distinguish the two cases.
150       */
151     time_t completion_timestamp(void);
152 
153     /**
154       * The creator_name method is used to obtain the Unix name of the
155       * user that created this change.
156       *
157       * @returns
158       *     The string value of the Unix name or NULL if not defined.
159       *     DO NOT str_free it when you are done with it, it is cached.
160       */
161     string_ty *creator_name(void);
162 
163     /**
164       * The cstate_filename_get method is used to obtain the name of
165       * the file containing cstate meta-data of this change.
166       *
167       * @returns
168       *     a string.  DO NOT str_free it when you are done with it,
169       *     it is cached.
170       */
171     string_ty *cstate_filename_get(void);
172 
173     /**
174       * The cstate_get method may be used to obtain the cstate meta-data
175       * of this change.
176       */
177     cstate_ty *cstate_get(void);
178 
179     /**
180       * THe cstate_write method may be used to write the cstate
181       * meta-data of this change
182       */
183     void cstate_write(void);
184 
185     // ----------  D  ------------------------------------------------------
186 
187     /**
188      * The delta_number_get method is used to get the delta number of a
189      * change, or zero if the change is not yet completed.
190      */
191     long delta_number_get(void);
192 
193     /**
194       * The description_get method is used to obtain the long
195       * description of this change set.
196       */
197     nstring description_get(void);
198 
199     /**
200       * The developer_name method is used to obtain the Unix name of
201       * the developer of this change.
202       *
203       * @returns
204       *     The string value of the Unix name or NULL if not defined.
205       *     DO NOT str_free it when you are done with it, it is
206       *     cached.
207       */
208     string_ty *developer_name(void);
209 
210     /**
211       * The developer_user_get method is used to obtain a user_ty
212       * instance representing the (most recent) developer of this change
213       * set.
214       */
215     user_ty::pointer developer_user_get(void);
216 
217     // ----------  E  ------------------------------------------------------
218 
219     // ----------  F  ------------------------------------------------------
220 
221     /**
222       * The file_exists method is used to determine whether or not a
223       * file exists in the change set.  (view_path == view_path_first)
224       *
225       * @param filename
226       *     The base-relative name of the file to search for.
227       */
228     bool file_exists(const nstring &filename);
229 
230     /**
231       * The file_find method is used to locate a change file similar to
232       * the file named.
233       *
234       * @param filename
235       *     The name of the file to be found.
236       * @param vp
237       *     The style of view path to be used.
238       */
239     fstate_src_ty *file_find(const nstring &filename, view_path_ty vp);
240 
241     /**
242       * The file_find method is used to locate a change file similar to
243       * the one indicated.  If possible it uses the UUID otherwise (for
244       * backwards compatibility) it uses the file name.
245       *
246       * @param src
247       *     The meta-data of the file to be found.
248       * @param vp
249       *     The style of view path to be used.
250       */
251     fstate_src_ty *file_find(fstate_src_ty *src, view_path_ty vp);
252 
253     /**
254       * The file_find method is used to locate a change file similar to
255       * the one indicated.  If possible it uses the UUID otherwise (for
256       * backwards compatibility) it uses the file name.
257       *
258       * @param src
259       *     The meta-data of the file to be found.
260       * @param vp
261       *     The style of view path to be used.
262       */
263     fstate_src_ty *file_find(cstate_src_ty *src, view_path_ty vp);
264 
265     /**
266       * The file_find method is used to locate a change file similar to
267       * the file named, in the change set itself
268       * (view_path == view_path_first).
269       *
270       * @param filename
271       *     The name of the file to be found.
272       */
273     fstate_src_ty *file_find(const nstring &filename);
274 
275     /**
276       * The file_find_fuzzy method is used to locate a change file with
277       * a name similar to the one given.
278       *
279       * @param filename
280       *     The name of the file to be found.
281       * @param vp
282       *     The style of view path to be used.
283       */
284     fstate_src_ty *file_find_fuzzy(const nstring &filename, view_path_ty vp);
285 
286     /**
287       * The file_find_uuid method is used to find a source file given
288       * the UUID.
289       *
290       * @param uuid
291       *     The UUID to search for.
292       * @param view_path
293       *     The style and depth of search for the file.
294       * @returns
295       *     a pointer to the file information, or NULL if no file has the
296       *     specified UUID.
297       */
298     fstate_src_ty *file_find_uuid(string_ty *uuid, view_path_ty view_path);
299 
300     /**
301       * The file_find_uuid method is used to find a source file given
302       * the UUID.
303       *
304       * @param uuid
305       *     The UUID to search for.
306       * @param view_path
307       *     The style and depth of search for the file.
308       * @returns
309       *     a pointer to the file information, or NULL if no file has the
310       *     specified UUID.
311       */
312     fstate_src_ty *file_find_uuid(const nstring &uuid, view_path_ty view_path);
313 
314     /**
315       * The file_new method is used to add a new file to a change set's
316       * file manifest.  No checking is poerformed, it is up to the caller
317       * to ensure that the name is unique.
318       *
319       * @param file_name
320       *     The name of the file to be created.
321       * @returns
322       *     A newly allocated file, with the name set, and everything
323       *     else blank.
324       */
325     fstate_src_ty *file_new(string_ty *file_name);
326 
327     /**
328       * The file_new method is used to add a new file to a change
329       * set's file manifest.  No checking is poerformed, it is up to
330       * the caller to ensure that the file name and UUID are unique.
331       * Typically this is used when adding a project file to a change
332       * set for modification or removal.
333       *
334       * @param meta
335       *     The meta-data of the file to be created.
336       * @returns
337       *     A newly allocated file, with the name set, and everything
338       *     else blank.
339       */
340     fstate_src_ty *file_new(fstate_src_ty *meta);
341 
342     /**
343       * The file_path method is used to obtain the absolute path to
344       * the given change file.
345       *
346       * @param file_name
347       *     The name of the file in question.
348       * @returns
349       *     a string containing the absolute path, or NULL if the file is
350       *     not a change source file.
351       */
352     string_ty *file_path(string_ty *file_name);
353 
354     /**
355       * The file_path method is used to obtain the absolute path to
356       * the given change file.
357       *
358       * @param file_name
359       *     The name of the file in question.
360       * @returns
361       *     a string containing the absolute path, or the empty string
362       *     if the file is not a change source file.
363       */
364     nstring file_path(const nstring &file_name);
365 
366     /**
367       * The file_path method is used to obtain the absolute path to
368       * the given change file.
369       *
370       * @param src
371       *     The meta-data of the file in question.
372       * @returns
373       *     a string containing the absolute path, or NULL if the file is
374       *     not a change source file.
375       */
376     string_ty *file_path(fstate_src_ty *src);
377 
378     /**
379       * The file_path_by_uuid method is used to obtain the absolute
380       * path to the given change file.
381       *
382       * @param uuid
383       *     The UUID of the file in question.
384       * @returns
385       *     a string containing the absolute path, or NULL if the file is
386       *     not a change source file.
387       */
388     string_ty *file_path_by_uuid(string_ty *uuid);
389 
390     /**
391       * The file_path_by_uuid method is used to obtain the absolute
392       * path to the given change file.
393       *
394       * @param uuid
395       *     The UUID of the file in question.
396       * @returns
397       *     a string containing the absolute path, or NULL if the file is
398       *     not a change source file.
399       */
400     nstring file_path_by_uuid(const nstring &uuid);
401 
402     /**
403       * The file_promote method is used to check whether or not recent
404       * integrations have change the actions the change files must
405       * perform.
406       *
407       * If two changes are creating the same file, the first one integrated
408       * means that the second one must update its action to "modify".
409       *
410       * If two changes are removing the same file, the first one integrated
411       * means that the second one needs to drop the file from its list.
412       *
413       * If one change is removing a file, and a second change is modifying
414       * the same file, after the first change is integrated, the second
415       * change must update its action to "create".
416       *
417       * @returns
418       *     true if anything changed, false if nothing changed.
419       */
420     bool file_promote(void);
421 
422     /**
423       * The file_resolve_name method is used to resolve an arbitrary
424       * UNIX pathname (relative or absolute) into a base relative path
425       * within a change set's search path.
426       *
427       * @param up
428       *     The user invoking the program.
429       * @param file_name
430       *     The file name to be resolved.
431       * @returns
432       *     The resolved base relative file name.  Use str_free when you are
433       *     done with it.
434       */
435     string_ty *file_resolve_name(user_ty::pointer up, string_ty *file_name);
436 
437     /**
438       * The file_resolve_name method is used to resolve an arbitrary
439       * UNIX pathname (relative or absolute) into a base relative path
440       * within a change set's search path.
441       *
442       * @param up
443       *     The user invoking the program.
444       * @param file_name
445       *     The file name to be resolved.
446       * @returns
447       *     The resolved base relative file name.  Use str_free when you are
448       *     done with it.
449       */
450     nstring file_resolve_name(user_ty::pointer up, const nstring &file_name);
451 
452     /**
453       * The file_resolve_names method is used to resolve arbitrary UNIX
454       * pathnames (relative or absolute) into base relative paths within
455       * a change set's search path.
456       *
457       * @param up
458       *     The user invoking the program.
459       * @param file_names
460       *     The file names to be resolved.
461       *     This parameter ISN'T const because this will be done in situ.
462       */
463     void file_resolve_names(user_ty::pointer up, string_list_ty &file_names);
464 
465     /**
466       * The file_unchanged method is used to determine whether a source
467       * file is unchanged compared to the file in the baseline.
468       *
469       * @param src_data
470       *     The file in question.
471       * @param up
472       *     The user to perform file actions as.
473       * @returns
474       *     bool; true if the file is unchanged, false if the file has
475       *     changed, and false if the comparison isn't meaningful.
476       */
477     bool file_unchanged(fstate_src_ty *src_data, user_ty::pointer up);
478 
479     /**
480       * The file_is_config method is used to determine whether or not
481       * the named file is a configuration file.
482       *
483       * @param name
484       *     The name of the file of interest
485       * @returns
486       *     true if it is a config file, false if not.
487       */
488     bool file_is_config(string_ty *name);
489 
490     /**
491       * The download_files_acessable method may be used to to determine
492       * whether or not the calling user has permission to access the
493       * change set's download files.  This usually means read and search
494       * premission on the development directory and/or the integration
495       * director, unless the change set is in the completed state.
496       */
497     bool download_files_accessable(void);
498 
499 private:
500     /**
501       * The fimprove method is used to cope with previous versions
502       * of the file meta data, and rewrite them to conform to later
503       * expectations.
504       *
505       * @param fstate_data
506       *     The file meta data to be massaged.
507       */
508     void fimprove(fstate_ty *fstate_data);
509 
510 public:
511     /**
512       * The fstate_get method is used to obtain a current value for the
513       * change file state symbol table.
514       *
515       * @note
516       *     This would be static to aegis/change_file.c if only
517       *     aegis/aer/value/fstate.c did not need it.  No other place
518       *     should access this directly.
519       */
520     fstate_ty *fstate_get(void);
521 
522     // ----------  G  ------------------------------------------------------
523 
524     /**
525       * The gid_get method is used to obtain the Unix group id of the
526       * change owner.
527       */
528     int gid_get() const;
529 
530     // ----------  H  ------------------------------------------------------
531 
532     // ----------  I  ------------------------------------------------------
533 
534     /**
535       * The integration_directory_get method may be used to obtain the
536       * change's integration directory path.  It is an error if the
537       * change is not in the 'being integrated' state.
538       *
539       * @param resolve
540       *     whether or not to resolve symlinks in the path.
541       */
542     nstring integration_directory_get(bool resolve);
543 
544     /**
545       * The integrator_name method is used to obtain the Unix group
546       * name of the integrator.
547       *
548       * @returns
549       *     The string value of the Unix name or NULL if not defined.
550       *     DO NOT str_free it when you are done with it, it is
551       *     cached.
552       */
553     string_ty *integrator_name(void);
554 
555     /**
556       * The is_a_branch method is used to determine whether or not this
557       * change set is an active branch.  If you want to know if it was
558       * ever an active branch (e.g. now completed) use the #was_a_branch
559       * method.
560       */
561     bool is_a_branch(void);
562 
563     /**
564       * The is_awaiting_development method returns true if the given
565       * change is in the awaiting development state, and false if it is
566       * not.
567       */
568     bool is_awaiting_development(void);
569 
570     /**
571       * The is_being_developed method returns true if the given change
572       * is in the being developed state, and false if it is not.
573       */
574     bool is_being_developed(void);
575 
576     /**
577       * The is_being_integrated method is used to determine whether or
578       * not this is in the being integrated state.
579       *
580       * @returns
581       *     bool; true if this is in the being integrated state, and
582       *     false if it is not.
583       */
584     bool is_being_integrated(void);
585 
586     /**
587       * The change_is_completed function returns true (non-zero) if this
588       * change is in the completed state, and false (zero) if it is not.
589       */
590     bool is_completed(void);
591 
592     // ----------  J  ------------------------------------------------------
593 
594     // ----------  K  ------------------------------------------------------
595 
596     // ----------  L  ------------------------------------------------------
597 
598     // ----------  M  ------------------------------------------------------
599 
600     // ----------  N  ------------------------------------------------------
601 
602     // ----------  O  ------------------------------------------------------
603 
604     // ----------  P  ------------------------------------------------------
605 
606     /**
607       * The pconf_attributes_get method is used to obtain the
608       * value of an attribute of the project, from the project
609       * configuration file.  It could be in this change, or it could
610       * be in a baseline or an ancestor baseline.
611       *
612       * @param name
613       *     The name of the attribute.
614       *     Attribute names are not case sensitive.
615       * @returns
616       *     the string value of the attribute, or the empty string
617       *     if not found.
618       */
619     nstring pconf_attributes_find(const nstring &name);
620 
621     /**
622       * The pconf_attributes_get_boolean method is used to obtain the
623       * value of an attribute of the project, from the project
624       * configuration file.  It could be in this change, or it could
625       * be in a baseline or an ancestor baseline.
626       *
627       * @param name
628       *     The name of the attribute.
629       *     Attribute names are not case sensitive.
630       * @param dflt
631       *     The default value to return if no attribute available.
632       * @returns
633       *     the string value of the attribute, or the empty string
634       *     if not found.
635       */
636     bool pconf_attributes_get_boolean(const nstring &name, bool dflt = false);
637 
638     /**
639       * The pconf_copyright_owner_get method is used to obtain the
640       * name of the copyright holder of a project.
641       */
642     nstring pconf_copyright_owner_get(void);
643 
644     /**
645       * The pfstate_get method is used to obtain the project file state
646       * information for a change set.  This is all of the project files,
647       * not just one.
648       */
649     fstate_ty *pfstate_get(void);
650 
651     /**
652       * The project_specific_setenv_performed_set method is used to
653       * remember if the environment variable(s), specified as
654       * project_specific attributes, has been already exported.
655       *
656       * @returns
657       *     Void.
658       */
659     void project_specific_setenv_performed_set(void);
660 
661     /**
662       * The project_specific_setenv_performed_get method is used to
663       * know if the environment variable(s), specified as
664       * project_specific attributes, has been already exported.
665       *
666       * @returns
667       *     True if the variables has been already exported, false
668       *     otherwise.
669       */
670     bool project_specific_setenv_performed_get() const;
671 
672     // ----------  Q  ------------------------------------------------------
673 
674     // ----------  R  ------------------------------------------------------
675 
676     /**
677       * The reviewer_name method is used to determine the Unix name of
678       * the (last) reviewer.
679       *
680       * @returns
681       *     The string representation of the Unix name or NULL if not
682       *     defined. DO NOT str_free it when you are done with it, it
683       *     is cached.
684       */
685     string_ty *reviewer_name(void);
686 
687     /**
688       * The run_project_file_command_needed method may be used to
689       * determine whether or not the project_file_command needstosed in
690       * recent integration history.
691       *
692       * @returns
693       *     true if need to run it (see next method), false if not.
694       */
695     bool run_project_file_command_needed(void);
696 
697     /**
698       * The run_project_file_command method is used to run the command
699       * configured in the aegis.conf file's project_file_command field.
700       *
701       * @param up
702       *     The user to run the command as.
703       *
704       * @note
705       *     this method MUST be called outside the change set lock
706       */
707     void run_project_file_command(const user_ty::pointer &up);
708 
709     /**
710       * The run_project_file_command_done method is used to remember
711       * that the project_file comman has been (is about to be) called
712       * recently.
713       *
714       * @note
715       *     this method MUST be called INSIDE the change set lock
716       */
717     void run_project_file_command_done(void);
718 
719     /**
720       * The run_new_file_command method is used to run the
721       * new_file_command field of the aegis.conf file.
722       *
723       * @param slp
724       *     The list of new file names
725       * @param up
726       *     Th euser to run the command as.
727       */
728     void run_new_file_command(string_list_ty *slp, const user_ty::pointer &up);
729 
730     /**
731       * The run_new_file_undo_command method is used to run the command
732       * in the new_file_undo_command field of the aegis.conf file.
733       *
734       * @param slp
735       *     The list of filenames affected.
736       * @param up
737       *     the user to run the program as
738       */
739     void run_new_file_undo_command(string_list_ty *slp,
740         const user_ty::pointer &up);
741 
742     /**
743       * The run_new_test_command method is used to run the command in
744       * the new_test_command field of the aegis.conf file.
745       *
746       * @param slp
747       *     The list of filenames affected.
748       * @param up
749       *     the user to run the program as
750       */
751     void run_new_test_command(string_list_ty *slp,
752         const user_ty::pointer &up);
753 
754     /**
755       * The run_new_test_undo_command method is used to run the command
756       * in the new_test_undo_command field of the aegis.conf file.
757       *
758       * @param slp
759       *     The list of filenames affected.
760       * @param up
761       *     the user to run the program as
762       */
763     void run_new_test_undo_command(string_list_ty *slp,
764         const user_ty::pointer &up);
765 
766     /**
767       * The run_copy_file_command method is used to run the command in
768       * the copy_file_command field of the aegis.conf file.
769       *
770       * @param slp
771       *     The list of filenames affected.
772       * @param up
773       *     the user to run the program as
774       */
775     void run_copy_file_command(string_list_ty *slp, const user_ty::pointer &up);
776 
777     /**
778       * The run_copy_file_undo_command method is used to run the command
779       * in the copy_file_undo_command field of the aegis.conf file.
780       *
781       * @param slp
782       *     The list of filenames affected.
783       * @param up
784       *     the user to run the program as
785       */
786     void run_copy_file_undo_command(string_list_ty *slp,
787         const user_ty::pointer &up);
788 
789     /**
790       * The run_remove_file_command method is used to run the command in
791       * the remove_file_command field of the aegis.conf file.
792       *
793       * @param slp
794       *     The list of filenames affected.
795       * @param up
796       *     the user to run the program as
797       */
798     void run_remove_file_command(string_list_ty *slp,
799         const user_ty::pointer &up);
800 
801     /**
802       * The run_remove_file_undo_command method is used to run the
803       * command in the remove_file_undo_command field of the aegis.conf
804       * file.
805       *
806       * @param slp
807       *     The list of filenames affected.
808       * @param up
809       *     the user to run the program as
810       */
811     void run_remove_file_undo_command(string_list_ty *slp,
812         const user_ty::pointer &up);
813 
814     /**
815       * The run_make_transparent_command method is used to run the
816       * command in the make_transparent_command field of the aegis.conf
817       * file.
818       *
819       * @param slp
820       *     The list of filenames affected.
821       * @param up
822       *     the user to run the program as
823       */
824     void run_make_transparent_command(string_list_ty *slp,
825         const user_ty::pointer &up);
826 
827     /**
828       * The run_make_transparent_undo_comman method is used to run
829       * the command in the make_transparent_undo_command field of the
830       * aegis.conf file.
831       *
832       * @param slp
833       *     The list of filenames affected.
834       * @param up
835       *     the user to run the program as
836       */
837     void run_make_transparent_undo_command(string_list_ty *slp,
838         const user_ty::pointer &up);
839 
840     /**
841       * The run_forced_develop_begin_notify_command method is used to
842       * run the command in the forced_develop_begin_notify_command field
843       * of the aegis.conf file.
844       *
845       * @param up
846       *     the user to run the program as
847       */
848     void run_forced_develop_begin_notify_command(const user_ty::pointer &up);
849 
850     /**
851       * The run_develop_end_notify_command method is used to run
852       * the command in the develop_end_notify_command field of the
853       * aegis.conf file.
854       */
855     void run_develop_end_notify_command(void);
856 
857     /**
858       * The run_develop_end_undo_notify_command method is used to run
859       * the command in the develop_end_undo_notify_command field of the
860       * aegis.conf file.
861       */
862     void run_develop_end_undo_notify_command(void);
863 
864     /**
865       * The run_review_begin_notify_command method is used to run
866       * the command in the review_begin_notify_command field of the
867       * aegis.conf file.
868       */
869     void run_review_begin_notify_command(void);
870 
871     /**
872       * The run_review_begin_undo_notify_command method is used to run
873       * the command in the review_begin_undo_notify_command field of the
874       * aegis.conf file.
875       */
876     void run_review_begin_undo_notify_command(void);
877 
878     /**
879       * The run_review_pass_notify_command method is used to run
880       * the command in the review_pass_notify_command field of the
881       * aegis.conf file.
882       */
883     void run_review_pass_notify_command(void);
884 
885     /**
886       * The run_review_pass_undo_notify_command method is used to run
887       * the command in the review_pass_undo_notify_command field of the
888       * aegis.conf file.
889       */
890     void run_review_pass_undo_notify_command(void);
891 
892     /**
893       * The run_review_fail_notify_command method is used to run
894       * the command in the review_fail_notify_command field of the
895       * aegis.conf file.
896       */
897     void run_review_fail_notify_command(void);
898 
899     /**
900       * The run_integrate_pass_notify_command method is used to run
901       * the command in the integrate_pass_notify_command field of the
902       * aegis.conf file.
903       */
904     void run_integrate_pass_notify_command(void);
905 
906     /**
907       * The run_integrate_fail_notify_command method is used to run
908       * the command in the integrate_fail_notify_command field of the
909       * aegis.conf file.
910       */
911     void run_integrate_fail_notify_command(void);
912 
913     /**
914       * The run_develop_begin_early_command method is used to run the
915       * develop_begin_early_command from the project configuration file.
916       * This is used by the aedb command, just after the development
917       * directory has been created.
918       *
919       * @param up
920       *     The user to run the command as.
921       */
922     void run_develop_begin_early_command(user_ty::pointer up);
923 
924     /**
925       * The run_develop_begin_command method is used to run the
926       * develop_begin_command from the projetc configuration file.  This
927       * is used by the aedb command, just all other actions performed by
928       * aedb.
929       *
930       * @param up
931       *     The user to run the command as.
932       */
933     void run_develop_begin_command(user_ty::pointer up);
934 
935     // ----------  S  ------------------------------------------------------
936 
937     /**
938       * The search_path_get method may be used to obtain the search path
939       * (list of progressively more out-of-date ancestor branches)
940       * within which to search for files.
941       *
942       * @param result
943       *     Where to append the additional directories.
944       * @param resolve
945       *     Whether or not to expand synbolic links within paths.
946       */
947     void search_path_get(string_list_ty *result, bool resolve);
948 
949     /**
950       * The search_path_get method may be used to obtain the search path
951       * (list of progressively more out-of-date ancestor branches)
952       * within which to search for files.
953       *
954       * @param result
955       *     Where to append the additional directories.
956       * @param resolve
957       *     Whether or not to expand synbolic links within paths.
958       */
959     void search_path_get(nstring_list &result, bool resolve);
960 
961     // ----------  T  ------------------------------------------------------
962 
963     time_t time_limit_get(void);
964 
965     /**
966       * The umask method is used to obtain the umask for this change.
967       *
968       * @returns
969       *     An int representing the umask value.
970       */
971     int umask_get() const;
972 
973     // ----------  U  ------------------------------------------------------
974 
975     /**
976      * The uuid_get method is used to obtain the UUID of this change set.
977      *
978      * @returns
979      *     The uuid of the change set, or the empty string of this
980      *     change set doesn't have a UUID.
981      */
982     nstring uuid_get(void);
983 
984     /**
985      * The uuid_get_list method is used to obtain all of the UUIDs
986      * associated with this change set.  This includes the change set's
987      * UUID, if it has one, and all of the aoriginal-uuid attributes.
988      *
989      * @param uuids
990      *     Where to put all of the UUIDs associated with this change set.
991      */
992     void uuid_get_list(nstring_list &uuids);
993 
994     // ----------  V  ------------------------------------------------------
995 
996     /**
997       * The version_debian_get method is used to get the version
998       * of this change set, in Debian format.  In particular, it
999       * makes being-developed change sets look like they are "release
1000       * candidates" for the next project delta, otherwise business as
1001       * usual.
1002       */
1003     nstring version_debian_get(void);
1004 
1005     /**
1006       * The version_rpm_get method is used to get the version of
1007       * this change set, in RPM format.  In particular, it makes
1008       * being-developed change sets look like they are "branched from"
1009       * for the current project delta, otherwise business as usual.
1010       */
1011     nstring version_rpm_get(void);
1012 
1013     /**
1014       * The version_get method is used to get the version of this change
1015       * set.  This will consist of the branch name (1.2) combined with
1016       * ether a delta number (.D123) or, for incomplete changes, a
1017       * change number (.C123).
1018       */
1019     nstring version_get(void);
1020 
1021     // ----------  W  ------------------------------------------------------
1022 
1023     /**
1024       * The was_a_branch method is used to determine whether or not this
1025       * change set is, or was ever, an active branch.  If you want to
1026       * know if it is a currently active branch (beging_developed) use
1027       * the #is_a_branch method.
1028       */
1029     bool was_a_branch(void);
1030 
1031     // ----------  X  ------------------------------------------------------
1032 
1033     // ----------  Y  ------------------------------------------------------
1034 
1035     // ----------  Z  ------------------------------------------------------
1036 
1037     // ---------------------------------------------------------------------
1038     // PLEASE keep the above method declarations in alphabetical order.
1039 
1040     //
1041     // If you add instance variables to this class, don't forget to update
1042     // change_alloc()     in libaegis/change/alloc.cc
1043     // change_free()      in libaegis/change/free.cc
1044     // change_lock_sync() in libaegis/change/lock_sync.cc
1045     //
1046 };
1047 
1048 change::pointer change_alloc(project *, long);
1049 void change_free(change::pointer );
1050 change::pointer change_copy(change::pointer );
1051 void change_bind_existing(change::pointer );
1052 int change_bind_existing_errok(change::pointer );
1053 void change_bind_new(change::pointer );
1054 change::pointer change_bogus(project *);
1055 
1056 cstate_history_ty *change_history_new(change::pointer , user_ty::pointer );
1057 
1058 void change_top_path_set(change::pointer , string_ty *);
1059 void change_top_path_set(change::pointer , const nstring &);
1060 void change_development_directory_set(change::pointer , string_ty *);
1061 void change_integration_directory_set(change::pointer , string_ty *);
1062 string_ty *change_top_path_get(change::pointer , int);
1063 string_ty *change_development_directory_get(change::pointer , int);
1064 string_ty *change_integration_directory_get(change::pointer , int);
1065 string_ty *change_logfile_basename(void);
1066 string_ty *change_logfile_get(change::pointer );
1067 void change_cstate_lock_prepare(change::pointer );
1068 void change_error(change::pointer , sub_context_ty *, const char *);
1069 void change_fatal(change::pointer , sub_context_ty *, const char *) NORETURN;
1070 void change_verbose(change::pointer , sub_context_ty *, const char *);
1071 
1072 /**
1073  * The change_warning function is used to issue a warning message
1074  * specific to a change.  The message will be substituted accouring
1075  * to aesub(5) and any additional substitutions provided in the
1076  * substitution context.
1077  */
1078 void change_warning(change::pointer , sub_context_ty *, const char *);
1079 
1080 /**
1081  * The change_warning_obsolete_field function is used to warn about the
1082  * use of obsolete fields (in user suppied files, Aegis will take care
1083  * of quietly cleaning up the meta-data files all by itself).
1084  */
1085 void change_warning_obsolete_field(change::pointer cp, string_ty *errpos,
1086     const char *old_field, const char *new_field);
1087 
1088 pconf_ty *change_pconf_get(change::pointer , int);
1089 
1090 // use cp->run_new_file_command instead
1091 void change_run_new_file_command(change::pointer cp, string_list_ty *slp,
1092     user_ty::pointer up) DEPRECATED;
1093 
1094 // use cp->run_new_file_undo_command instead
1095 void change_run_new_file_undo_command(change::pointer cp, string_list_ty *slp,
1096     user_ty::pointer up) DEPRECATED;
1097 
1098 // use cp->run_new_test_command instead
1099 void change_run_new_test_command(change::pointer cp, string_list_ty *slp,
1100     user_ty::pointer up) DEPRECATED;
1101 
1102 // use cp->run_new_test_undo_command instead
1103 void change_run_new_test_undo_command(change::pointer cp, string_list_ty *slp,
1104     user_ty::pointer up) DEPRECATED;
1105 
1106 // use cp->run_copy_file_command instead
1107 void change_run_copy_file_command(change::pointer cp, string_list_ty *slp,
1108     user_ty::pointer up) DEPRECATED;
1109 
1110 // use cp->run_copy_file_undo_command instead
1111 void change_run_copy_file_undo_command(change::pointer cp, string_list_ty *slp,
1112     user_ty::pointer up) DEPRECATED;
1113 
1114 // use cp->run_remove_file_command instead
1115 void change_run_remove_file_command(change::pointer cp, string_list_ty *slp,
1116     user_ty::pointer up) DEPRECATED;
1117 
1118 // use cp->run_remove_file_undo_command instead
1119 void change_run_remove_file_undo_command(change::pointer cp,
1120     string_list_ty *slp, user_ty::pointer up) DEPRECATED;
1121 
1122 // use cp->run_make_transparent_command instead
1123 void change_run_make_transparent_command(change::pointer cp,
1124     string_list_ty *slp, user_ty::pointer up) DEPRECATED;
1125 
1126 // use cp->run_make_transparent_undo_command instead
1127 void change_run_make_transparent_undo_command(change::pointer cp,
1128     string_list_ty *slp, user_ty::pointer up) DEPRECATED;
1129 
1130 // use vp->run_project_file_command_needed() instead
1131 int change_run_project_file_command_needed(change::pointer cp) DEPRECATED;
1132 
1133 // use cp->run_project_file_command(up) instead
1134 void change_run_project_file_command(change::pointer cp, user_ty::pointer up)
1135     DEPRECATED;
1136 
1137 // use cp->run_forced_develop_begin_notify_command instead
1138 void change_run_forced_develop_begin_notify_command(change::pointer cp,
1139     user_ty::pointer up) DEPRECATED;
1140 
1141 // use cp->run_develop_end_notify_command instead
1142 void change_run_develop_end_notify_command(change::pointer cp) DEPRECATED;
1143 
1144 // use cp->run_develop_end_undo_notify_command instead
1145 void change_run_develop_end_undo_notify_command(change::pointer cp) DEPRECATED;
1146 
1147 // use cp->run_review_begin_notify_command instead
1148 void change_run_review_begin_notify_command(change::pointer cp) DEPRECATED;
1149 
1150 // use cp->run_review_begin_undo_notify_command
1151 void change_run_review_begin_undo_notify_command(change::pointer cp) DEPRECATED;
1152 
1153 // use cp->run_review_pass_notify_command instead
1154 void change_run_review_pass_notify_command(change::pointer cp) DEPRECATED;
1155 
1156 // use cp->run_review_pass_undo_notify_command instead
1157 void change_run_review_pass_undo_notify_command(change::pointer cp) DEPRECATED;
1158 
1159 // use cp->run_review_fail_notify_command instead
1160 void change_run_review_fail_notify_command(change::pointer cp) DEPRECATED;
1161 
1162 // use cp->run_integrate_pass_notify_command instead
1163 void change_run_integrate_pass_notify_command(change::pointer cp) DEPRECATED;
1164 
1165 // use cp->run_integrate_fail_notify_command instead
1166 void change_run_integrate_fail_notify_command(change::pointer cp) DEPRECATED;
1167 
1168 void change_run_history_get_command(change::pointer cp, fstate_src_ty *src,
1169     string_ty *output_file, user_ty::pointer up);
1170 void change_run_history_create_command(change::pointer cp, fstate_src_ty *);
1171 void change_run_history_put_command(change::pointer cp, fstate_src_ty *);
1172 
1173 /**
1174  * The change_run_history_query_command function is used to obtain the
1175  * head revision number of the history of the given source file.
1176  *
1177  * @param cp
1178  *     The change to operate within.
1179  * @param src
1180  *     The source file meta-data of the file of interest.
1181  * @returns
1182  *     Pointer to string containing the version.  Use str_free() when
1183  *     you are done with it.
1184  */
1185 string_ty *change_run_history_query_command(change::pointer cp,
1186     fstate_src_ty *src);
1187 
1188 void change_run_history_label_command(change::pointer cp, fstate_src_ty *,
1189     string_ty *label);
1190 
1191 /**
1192  * The change_run_history_transaction_begin_command function is
1193  * used to run the history_transaction_begin_command in the project
1194  * configuration file.  This is used by the aeipass(1) command before
1195  * any history put or create commands.
1196  *
1197  * @param cp
1198  *     The change to operate within.
1199  */
1200 void change_run_history_transaction_begin_command(change::pointer cp);
1201 
1202 /**
1203  * The change_run_history_transaction_end_command function is
1204  * used to run the history_transaction_end_command in the project
1205  * configuration file.  This is used by the aeipass(1) command after
1206  * any history put or create commands.
1207  *
1208  * @param cp
1209  *     The change to operate within.
1210  */
1211 void change_run_history_transaction_end_command(change::pointer cp);
1212 
1213 /**
1214  * The change_run_history_transaction_abort_command function is
1215  * used to run the history_transaction_abort_command in the project
1216  * configuration file.  This is used by the aeipass(1) command if
1217  * a history transaction needs to be aborted.
1218  *
1219  * @param cp
1220  *     The change to operate within.
1221  */
1222 void change_run_history_transaction_abort_command(change::pointer cp);
1223 
1224 void change_history_trashed_fingerprints(change::pointer , string_list_ty *);
1225 void change_run_diff_command(change::pointer cp, user_ty::pointer up,
1226     string_ty *original, string_ty *input, string_ty *output);
1227 void change_run_diff3_command(change::pointer cp, user_ty::pointer up,
1228     string_ty *original, string_ty *most_recent, string_ty *input,
1229     string_ty *output);
1230 void change_run_merge_command(change::pointer cp, user_ty::pointer up,
1231     string_ty *original, string_ty *most_recent, string_ty *input,
1232     string_ty *output);
1233 void change_run_patch_diff_command(change::pointer cp, user_ty::pointer up,
1234     string_ty *original, string_ty *input, string_ty *output,
1235     string_ty *index_name);
1236 void change_run_annotate_diff_command(change::pointer cp, user_ty::pointer up,
1237     string_ty *original, string_ty *input, string_ty *output,
1238     string_ty *index_name, const char *diff_option);
1239 int change_has_merge_command(change::pointer );
1240 void change_run_integrate_begin_command(change::pointer );
1241 void change_run_integrate_begin_undo_command(change::pointer );
1242 
1243 void change_run_develop_begin_command(change::pointer cp, user_ty::pointer up)
1244     DEPRECATED;
1245 
1246 void change_run_develop_begin_undo_command(change::pointer cp,
1247     user_ty::pointer up);
1248 int change_run_test_command(change::pointer cp, user_ty::pointer up,
1249     string_ty *, string_ty *, int, int,
1250     const nstring_list &variable_assignments);
1251 int change_run_development_test_command(change::pointer cp, user_ty::pointer up,
1252     string_ty *, string_ty *, int, int,
1253     const nstring_list &variable_assignments);
1254 void change_run_build_command(change::pointer );
1255 void change_run_build_time_adjust_notify_command(change::pointer );
1256 void change_run_development_build_command(change::pointer , user_ty::pointer ,
1257     string_list_ty *);
1258 
1259 /**
1260  * The change_run_develop_end_policy_command function is used to
1261  * run the develop_end_policy_command specified in the project
1262  * configuration file.
1263  *
1264  * @param cp
1265  *     The change in question.
1266  * @param up
1267  *     The developer of the change.
1268  * @note
1269  *     This function does not return if the command exits with a
1270  *     non-zero exit status.
1271  */
1272 void change_run_develop_end_policy_command(change::pointer cp,
1273     user_ty::pointer up);
1274 
1275 string_ty *change_file_whiteout(change::pointer , string_ty *);
1276 void change_file_whiteout_write(change::pointer cp, string_ty *path,
1277     user_ty::pointer up);
1278 void change_become(change::pointer );
1279 void change_become_undo(change::pointer cp);
1280 void change_developer_become(change::pointer );
1281 void change_developer_become_undo(change::pointer cp);
1282 
1283 void change_development_directory_clear(change::pointer );
1284 void change_integration_directory_clear(change::pointer );
1285 void change_architecture_clear(change::pointer );
1286 void change_architecture_add(change::pointer , string_ty *);
1287 void change_architecture_query(change::pointer );
1288 string_ty *change_architecture_name(change::pointer , int);
1289 string_ty *change_run_architecture_discriminator_command(change::pointer cp);
1290 cstate_architecture_times_ty *change_architecture_times_find(change::pointer ,
1291                                                              string_ty *);
1292 void change_build_time_set(change::pointer );
1293 
1294 /**
1295  * The change_test_time_set function is used to set the test time for a
1296  * change.  The architecture of the currently executing session is used.
1297  *
1298  * @param cp
1299  *     The change in question.
1300  * @param when
1301  *     The time the test was performed.
1302  */
1303 void change_test_time_set(change::pointer cp, time_t when);
1304 
1305 /**
1306  * The change_test_time_set function is used to set the test time for a
1307  * change, for the given architecture variant.
1308  *
1309  * @param cp
1310  *     The change in question.
1311  * @param variant
1312  *     The name of the architecture of interest.
1313  * @param when
1314  *     The time the test was performed.
1315  */
1316 void change_test_time_set(change::pointer cp, string_ty *variant, time_t when);
1317 
1318 /**
1319  * The change_test_baseline_time_set function is used to set the
1320  * baseline test time for a change.  The architecture of the currently
1321  * executing session is used.
1322  *
1323  * @param cp
1324  *     The change in question.
1325  * @param when
1326  *     The time the test was performed.
1327  */
1328 void change_test_baseline_time_set(change::pointer cp, time_t when);
1329 
1330 /**
1331  * The change_test_baseline_time_set function is used to set the test
1332  * time for a change, for the given architecture variant.
1333  *
1334  * @param cp
1335  *     The change in question.
1336  * @param variant
1337  *     The name of the architecture of interest.
1338  * @param when
1339  *     The time the test was performed.
1340  */
1341 void change_test_baseline_time_set(change::pointer cp, string_ty *variant,
1342     time_t when);
1343 
1344 /**
1345  * The change_regression_test_time_set function is used to set (or
1346  * clear) the regression test time stamp of the chanegh set.
1347  *
1348  * @param cp
1349  *     The change set in question.
1350  * @param when
1351  *     The time the test was performed, or zero to clear the time.
1352  * @param arch_name
1353  *     The name of the architecture, or the NULL pointer to mean "the
1354  *     current one".
1355  */
1356 void change_regression_test_time_set(change::pointer cp, time_t when,
1357     string_ty *arch_name = 0);
1358 
1359 void change_test_times_clear(change::pointer );
1360 void change_build_times_clear(change::pointer );
1361 void change_architecture_from_pconf(change::pointer );
1362 
1363 const char *change_outstanding_builds(change::pointer , time_t);
1364 const char *change_outstanding_tests(change::pointer , time_t);
1365 const char *change_outstanding_tests_baseline(change::pointer , time_t);
1366 const char *change_outstanding_tests_regression(change::pointer , time_t);
1367 
1368 int change_pathconf_name_max(change::pointer );
1369 string_ty *change_filename_check(change::pointer , string_ty *);
1370 
1371 void change_create_symlinks_to_baseline(change::pointer , user_ty::pointer ,
1372     const work_area_style_ty &);
1373 
1374 /**
1375  * The change_maintain_symlinks_to_baseline is used to repair the
1376  * symbolic links (etc) as dictated by the development_directory_style
1377  * field of the project configuration file.
1378  *
1379  * The "symlink" in the name is an historical accident, it also
1380  * maintains the hard links and copies as well.
1381  *
1382  * @param cp
1383  *     The change to operatte on
1384  * @param up
1385  *     The user to operate as
1386  * @param undoing
1387  *     True if this call is in response to and undo operation (aecpu,
1388  *     aemtu) because they need special attention for file time stamps.
1389  *     Defaults to false if not specified.
1390  *
1391  * @note
1392  *      This function is NOT to be called by aeb, because it needs
1393  *      different logic.
1394  * @note
1395  *     This function may only be called when the change is in the
1396  *     "being developed" state.
1397  */
1398 void change_maintain_symlinks_to_baseline(change::pointer cp,
1399     user_ty::pointer up, bool undoing = false);
1400 
1401 void change_remove_symlinks_to_baseline(change::pointer , user_ty::pointer ,
1402     const work_area_style_ty &);
1403 
1404 void change_rescind_test_exemption(change::pointer );
1405 
1406 /**
1407  * The change_fstate_filename_get function is used to obtain the
1408  * absolute path of the file which holds the change's file state.
1409  *
1410  * @param cp
1411  *     The change being operated on.
1412  * @returns
1413  *     a string.  DO NOT str_free it when you are done with it,
1414  *     it is cached.
1415  */
1416 string_ty *change_fstate_filename_get(change::pointer cp);
1417 
1418 /**
1419  * The change_pfstate_filename_get function is used to obtain the
1420  * absolute path of the file which holds the delta's cache of the
1421  * project file state.
1422  *
1423  * @param cp
1424  *     The change being operated on.
1425  * @returns
1426  *     a string.  DO NOT str_free it when you are done with it,
1427  *     it is cached.
1428  */
1429 string_ty *change_pfstate_filename_get(change::pointer cp);
1430 
1431 void change_rescind_test_exemption_undo(change::pointer );
1432 void change_force_regression_test_exemption(change::pointer );
1433 void change_force_regression_test_exemption_undo(change::pointer );
1434 
1435 void change_check_architectures(change::pointer );
1436 string_ty *change_new_test_filename_get(change::pointer , long, int);
1437 string_ty *change_development_directory_template(change::pointer ,
1438                                                  user_ty::pointer );
1439 string_ty *change_metrics_filename_pattern_get(change::pointer );
1440 
1441 /**
1442  * The change_uuid_set function is used to set a change's UUID,
1443  * if it has not been set already.
1444  */
1445 void change_uuid_set(change::pointer cp);
1446 
1447 /**
1448  * The change_uuid_clear function is used to clear a change's UUID,
1449  * if it has been set in the past.
1450  */
1451 void change_uuid_clear(change::pointer cp);
1452 
1453 /**
1454  * The change_reviewer_list function is used to get the list of
1455  * reviewers since the last develop_end.  There can be more than one
1456  * if the review_policy_command filed of the project configuration is
1457  * being used.
1458  *
1459  * @param cp
1460  *     The change to be consulted.
1461  * @param result
1462  *     where to put the answers.
1463  */
1464 void change_reviewer_list(change::pointer cp, string_list_ty &result);
1465 
1466 /**
1467   * The change_reviewer_already function is used to determine if a user
1468   * has already reviewed a change, since the last develop end.
1469   *
1470   * @param cp
1471   *     The change to be consulted.
1472   * @param login
1473   *     The login name of the user in question.
1474   * @returns
1475   *     bool; true if the user has reviewed already, false if not.
1476   */
1477 bool change_reviewer_already(change::pointer cp, string_ty *login);
1478 
1479 /**
1480   * The change_reviewer_already function is used to determine if a user
1481   * has already reviewed a change, since the last develop end.
1482   *
1483   * @param cp
1484   *     The change to be consulted.
1485   * @param login
1486   *     The login name of the user in question.
1487   * @returns
1488   *     bool; true if the user has reviewed already, false if not.
1489   */
1490 bool change_reviewer_already(change::pointer cp, const nstring &login);
1491 
1492 /**
1493  * The change_when_get function is used to obtain the last (most
1494  * recent) time for the given state transition.
1495  *
1496  * @param cp
1497  *     The change in qiestion.
1498  * @param what
1499  *     The state transition to look for.
1500  * @returns
1501  *     time_t; the time of the event, or 0 if not found.
1502  */
1503 time_t change_when_get(change::pointer cp, cstate_history_what_ty what);
1504 
1505 /**
1506  * The change_diff_required function is used to see of the project (and
1507  * this specific change set) need the diff command to be run.
1508  *
1509  * @param cp
1510  *     The change in question.
1511  * @returns
1512  *     bool; true if diff command needs to be run, false if not.
1513  */
1514 bool change_diff_required(change::pointer cp);
1515 
1516 /**
1517  * The change_build_required function is used to see of the project (and
1518  * this specific change set) need the build command to be run.
1519  *
1520  * @param cp
1521  *     The change in question.
1522  * @param conf_exists
1523  *     true if the project configuration file must exist (causing fatal
1524  *     error if it does not), or false if it doesn't matter.
1525  * @returns
1526  *     bool; true if build command needs to be run, false if not.
1527  */
1528 bool change_build_required(change::pointer cp, bool conf_exists = true);
1529 
1530 // vim: set ts=8 sw=4 et :
1531 #endif // LIBAEGIS_CHANGE_H
1532