1 //
2 // aegis - project change supervisor
3 // Copyright (C) 1992-1999, 2001-2008, 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 PROJECT_H
21 #define PROJECT_H
22 
23 #include <common/ac/time.h>
24 
25 #include <libaegis/pattr.fmtgen.h>
26 #include <libaegis/pstate.fmtgen.h>
27 #include <libaegis/view_path.h>
28 #include <libaegis/change.h>
29 
30 class string_list_ty; // forward
31 class sub_context_ty; // forward
32 class fstate_src_ty; // forward
33 class itab_ty; // forward
34 
35 /**
36   * The project class is used to remember the state of a project.
37   *
38   * Eventually, it will be discouraged to use this class directly.  The
39   * preferred method will be to access it via a project class (see
40   * below) smart pointer.  This will be able to guarantee the reference
41   * counting semantics.
42   *
43   * This class is presently in transition from being a C struct.  One by
44   * one the access functions will be turned into access methids, and the
45   * instance variables will become private.
46   */
47 class project
48 {
49 public:
50     /**
51       * The pointer typedef is provided so that clients of this
52       * interface may use change::pointer everywhere they need to point
53       * at a change instance, and only this typedef needs to be edited
54       * to use a variety of smart pointer instead.
55       */
56     typedef project *pointer;
57 
58     /**
59       * The destructor.
60       *
61       * It is not virtual; thou shalt not derive fron this class.
62       *
63       * @note
64       *     Eventually this method will be private, to ensure the
65       *     reference counting always works.  The correct method is to
66       *     call the project_free function.
67       */
68     ~project();
69 
70     /**
71       * The constructor.
72       *
73       * @param name
74       *     The name of the project.
75       */
76     project(string_ty *name);
77 
78     // NOTE: methods are sorted alphabetically.  To have methods
79     // grouped, make sure they change their suffix rather than their
80     // prefix.  E.g. thingumy_get and thingumy_set rather than
81     // get_thingumy and set_thingumy.
82     //
83     // Note: public or protected or private, it doesn't matter, keep
84     // them sorted.
85 
86     // ----------  A  ------------------------------------------------------
87 
88     /**
89       * The attribute_get method is used to obtain the value of an
90       * attribute of this project.
91       *
92       * The project attributes are kept in the <tt>project_specific</tt>
93       * field of the project config file (<tt>aegis.conf</tt>) which is
94       * a project source file.  Only use this method when you want the
95       * <b>baseline</b> attributes, use change::pconf_attributes_find
96       * within a change set.
97       *
98       * @param name
99       *     The name of the attribute.
100       *     Attribute names are not case sensitive.
101       * @returns
102       *     the string value of the attribute, or the empty string
103       *     if not found.
104       */
105     nstring attribute_get(const nstring &name);
106 
107     /**
108       * The attribute_get_boolean method is used to obtain the value of
109       * an attribute of this project, as a true/false value.
110       *
111       * The project attributes are kept in the <tt>project_specific</tt>
112       * field of the project config file (<tt>aegis.conf</tt>)
113       * which is a project source file.  Only use this method
114       * when you want the <b>baseline</b> attributes, use
115       * change::pconf_attributes_find_boolean within a change set.
116       *
117       * @param name
118       *     The name of the attribute.
119       *     Attribute names are not case sensitive.
120       * @returns
121       *     the boolean value of the attribute, or false if the
122       *     attribute is not found or is not interpretable as a
123       *     boolean.
124       */
125     bool attribute_get_boolean(const nstring &name);
126 
127     // ----------  B  ------------------------------------------------------
128 
129     /**
130       * The baseline_path_get method is used to obtain the absolure path
131       * of the project's (branch's) baseline.
132       *
133       * @param resolve
134       *     Whether or not to resolve all of the symlinks in the path.
135       */
136     string_ty *baseline_path_get(bool resolve = false);
137 
138     /**
139       * The bind_branch method is used to bind a branch of this project
140       * into a new project object.
141       *
142       * @param bp
143       *     The change corresponding to the project of interest.
144       */
145     project *bind_branch(change::pointer bp);
146 
147     /**
148       * The bind_existing method is used to bind a newly created project
149       * object to an existing project.
150       *
151       * @note
152       *     This method does not return if there is an error.  A fatal
153       *     error message will be produced in this case.
154       */
155     void bind_existing();
156 
157     /**
158       * The bind_existing_errok method is used to bind a newly created
159       * project object to an existing project.
160       *
161       * @returns
162       *     bool; true if bound successfully, false if not
163       */
164     bool bind_existing_errok();
165 
166     /**
167       * The bind_keep method is used to bind a new project to an
168       * existing directory, as needed by the "aenpr -keep" option.
169       *
170       * @param path
171       *     The directory containing the project.
172       */
173     void bind_keep(const nstring &path);
174 
175     /**
176       * The bind_new method is used to bind a new project object to a
177       * new name.  This will create all of the necessary data structures
178       * and (eventually) files, once the project directory has been set.
179       */
180     void bind_new();
181 
182     // ----------  C  ------------------------------------------------------
183 
184     /**
185       * The change_completion_timestamp is used to
186       * determine the completion timestamp of a change.
187       *
188       * @param change_number
189       *    the number of the change.
190       *
191       * @returns
192       *    the completion timestamp of the change.
193       *
194       * @note
195       *    this method caches its results for speed.
196       */
197     time_t change_completion_timestamp(long change_number);
198 
199     /**
200       * The change_get method is used to obtain a pointer to the change
201       * object representing this project branch.
202       *
203       * @returns
204       *     pointer to change object;
205       *     DO NOT change_free() or delete it.
206       */
207     change::pointer change_get(void);
208 
209     /**
210       * The change_get_raw method is used to obtain a pointer to the change
211       * object representing this project branch or NULL if no such object
212       * is in the project.
213       *
214       * @returns
215       *     pointer to change object;
216       *     DO NOT change_free() or delete it.
217       */
change_get_raw()218     change::pointer change_get_raw() { return pcp; }
219 
220     /**
221       * The change_path_get method is used to obtain the absolute path
222       * of the meta-data of a specific change set.
223       *
224       * @param change_number
225       *     The number of the change for which the path is desired.
226       * @returns
227       *     a string; use str_free when you are done with.
228       */
229     string_ty *change_path_get(long change_number);
230 
231     void
change_reset()232     change_reset()
233     {
234         change::pointer tmp = pcp;
235         pcp = 0;
236         change_free(tmp);
237     }
238 
239     /**
240       * The changes_path_get method is used to obtain the absolute path
241       * of the directory containing change set meta-data.
242       *
243       * @returns
244       *     a string; do not str_free or delete it, because it is cached.
245       */
246     string_ty *changes_path_get();
247 
248 public: // during transition, then private
249     /**
250       * The convert_to_new_format method is used to convert Aegis 2.3
251       * project meta-data into Aegis 3.0 (and later) project meta-data.
252       */
253     void convert_to_new_format();
254 
255 public:
256     /**
257       * The copy_the_owner method is used to copy the owner from another
258       * project.  It is only ever used by aenrls, which sort-of clones
259       * another project.  Don't use this method.
260       *
261       * Note: this is only a transient requirement for new projects.
262       * Existing projects take their uid and gid from the Unix uid and
263       * gid of the project directory.
264       */
265     void copy_the_owner(project *pp);
266 
267     /**
268       * the copyright_years_slurp method is used to determine the range
269       * of copyright years covered by this project and all its ancrestor
270       * projects back to the trunk.
271       *
272       * @param a
273       *     The array to store the results in
274       * @param amax
275       *     The maximum number of distinct years which can be stored in
276       *     the array (see SIZEOF macro).
277       * @param alen_p
278       *     This is a pointer to the array length used to date.
279       */
280     void copyright_years_slurp(int *a, int amax, int *alen_p);
281 
282     // ----------  D  ------------------------------------------------------
283     // ----------  E  ------------------------------------------------------
284     // ----------  F  ------------------------------------------------------
285 
286     /**
287       * The file_directory_query method is used to determine whether or
288       * not a given file name is actually a directory name, and if it
289       * is, expand it into a list of files below that directory.
290       *
291       * @param filename
292       *     The name of the file to be checked.
293       * @param result_in
294       *     If the filename is a directory, will be filled with a list
295       *     of files existing in that directory.
296       * @param result_out
297       *     If the filename is a directory, will be filled with a list
298       *     of removed files from that directory.
299       * @param as_view_path
300       *     The view path style to be used.
301       */
302     bool file_directory_query(const nstring &filename, nstring_list &result_in,
303         nstring_list &result_out, view_path_ty as_view_path);
304 
305     /**
306       * The file_directory_query method is used to determine whether or
307       * not a given file name is actually a directory name, and if it
308       * is, expand it into a list of files below that directory.
309       *
310       * @param filename
311       *     The name of the file to be checked.
312       * @param result_in
313       *     If not NULL, and if the filename is a directory, will be
314       *     filled with a list of files existing in that directory.
315       * @param result_out
316       *     If not NULL, and if the filename is a directory, will be
317       *     filled with a list of removed files from that directory.
318       * @param as_view_path
319       *     The view path style to be used.
320       */
321     void file_directory_query(string_ty *filename,
322         struct string_list_ty *result_in, struct string_list_ty *result_out,
323         view_path_ty as_view_path);
324 
325     /**
326       * The file_exists method is used to determine whether or not a
327       * file exists in the project baseline, or any of the ancestor
328       * basleines.
329       *
330       * @param filename
331       *     The base-relative name of the file to search for.
332       */
333     bool file_exists(const nstring &filename);
334 
335     /**
336       * The file_find method is used to find the state information of
337       * the named file within the project.  It will search the immediate
338       * branch, and then any ancestor branches until the file is found.
339       *
340       * @param filename
341       *     The base-relative name of the file to search for.
342       * @param as_view_path
343       *     If this is true, apply viewpath rules to the file (i.e. if
344       *     it is removed, return a null pointer) if false return first
345       *     instance found.
346       */
347     fstate_src_ty *file_find(const nstring &filename,
348         view_path_ty as_view_path);
349 
350     /**
351       * The file_find method is used to find the state information of
352       * the named file within the project.  It will search the immediate
353       * branch, and then any ancestor branches until the file is found.
354       *
355       * @param filename
356       *     The base-relative name of the file to search for.
357       * @param as_view_path
358       *     If this is true, apply viewpath rules to the file (i.e. if
359       *     it is removed, return a null pointer) if false return first
360       *     instance found.
361       */
362     fstate_src_ty *file_find(string_ty *filename, view_path_ty as_view_path);
363 
364     /**
365       * The file_find method is used to find the state information of a
366       * file within the project, given the corresponding change file's
367       * meta-data.  It will search the immediate branch, and then any
368       * ancestor branches until the file is found.
369       *
370       * @param c_src
371       *     The change file meta-data for which the corresponding project
372       *     file is sought.
373       * @param as_view_path
374       *     If this is true, apply viewpath rules to the file (i.e. if
375       *     it is removed, return a null pointer) if false return first
376       *     instance found.
377       */
378     fstate_src_ty *file_find(fstate_src_ty *c_src, view_path_ty as_view_path);
379 
380     /**
381       * The file_find method is used to find the state information of a
382       * file within the project, given the corresponding change file's
383       * meta-data.  It will search the immediate branch, and then any
384       * ancestor branches until the file is found.
385       *
386       * @param c_src
387       *     The change file meta-data for which the corresponding project
388       *     file is sought.
389       * @param as_view_path
390       *     If this is true, apply viewpath rules to the file (i.e. if
391       *     it is removed, return a null pointer) if false return first
392       *     instance found.
393       */
394     fstate_src_ty *file_find(cstate_src_ty *c_src, view_path_ty as_view_path);
395 
396     /**
397       * The file_find_by_uuid method is used to find the state
398       * information of a file within the project, given the file's UUID.
399       * It will search the immediate branch, and then any ancestor
400       * branches until the file is found.
401       *
402       * \param uuid
403       *     The UUID of the file to search for.
404       * \param vp
405       *     If this is true, apply viewpath rules to the file (i.e. if
406       *     it is removed, return a null pointer) if false return first
407       *     instance found.
408       */
409     fstate_src_ty *file_find_by_uuid(string_ty *uuid, view_path_ty vp);
410 
411     /**
412       * The file_find_fuzzy method is used to find the state information
413       * for a project file when the project::file_find function fails.
414       * It uses fuzzy string matching, which is significantly slower
415       * than exact searching, but can provide very useful error messages
416       * for users.
417       *
418       * \param filename
419       *     The base-relative name of the file to search for.
420       * \param as_view_path
421       *     If this is true, apply viewpath rules to the file (i.e. if
422       *     it is removed, return a null pointer) if false return first
423       *     instance found.
424       */
425     fstate_src_ty *file_find_fuzzy(string_ty *filename,
426         view_path_ty as_view_path);
427 
428 private:
429     /**
430       * The file_list_get method is used to obtain a list of file names.
431       * The lists are calculated on demand and cached.
432       *
433       * \param as_view_path
434       *     The view path style to use when calculating the list of
435       *     project files.
436       * \returns
437       *     Pointer to a string list, do not delete it, it is cached.
438       */
439     struct string_list_ty *file_list_get(view_path_ty as_view_path);
440 
441 public:
442     /**
443       * The file_list_invalidate method is used to clear the cahced
444       * project file information when it becomes stale.
445       */
446     void file_list_invalidate();
447 
448     /**
449       * The file_new method is used to create a new project file by
450       * name, and add it to the project file manifest.  No validation is
451       * done, the called must guarantee that the file name is unique.
452       *
453       * \param file_name
454       *     The base-relative name of the file to search for.
455       */
456     fstate_src_ty *file_new(string_ty *file_name);
457 
458     /**
459       * The file_new method is used to create a new project file from
460       * the meta data of an existing (usually change set) file, and add
461       * it to the project file manifest.  No validation is done, the
462       * caller must guarantee that the file name and UUID are unique.
463       *
464       * \param meta
465       *     The meta data, including the name and UUID, of the file to
466       *     be created.
467       */
468     fstate_src_ty *file_new(fstate_src_ty *meta);
469 
470     /**
471       * The file_nth method is used to get the 'n'th file from the list
472       * of project files.
473       *
474       * \param n
475       *     The file number to obtain (zero based).
476       * \param as_view_path
477       *     The style of view path to use when calculating the list.
478       * \returns
479       *     pointer to file mete-data, or NULL if beyond end of list
480       */
481     fstate_src_ty *file_nth(size_t n, view_path_ty as_view_path);
482 
483     /**
484       * The find_branch method is used to locate the branch with the
485       * given number in this project.
486       *
487       * @param number
488       *     The branch number to locate.
489       * @returns
490       *     Pointer to valid project object.
491       */
492     project *find_branch(const char *number);
493 
494     // ----------  G  ------------------------------------------------------
495 
496 private:
497     /**
498       * The get_the_owner method is used to determine the Unix pid and
499       * gid for the project.
500       */
501     void get_the_owner();
502 
503 public:
504     /**
505       * The get_user method may be used to obtain a pointer to the user
506       * (and group) ownership date for this project.
507       */
508     user_ty::pointer get_user() const;
509 
510     /**
511       * The gid_get method is used to obtain the Unix group id of the
512       * project owner.
513       */
514     int gid_get();
515 
516     // ----------  H  ------------------------------------------------------
517 
518     /**
519       * The history_path_get method is used to determine the top-level
520       * directory of the tree which is used to hold the project's
521       * history files.
522       *
523       * @returns
524       *     a pointer to a string.  Do NOT free this string when you are
525       *     done with it, because it is cached.
526       */
527     string_ty *history_path_get();
528 
529     /**
530       * The home_path_get method is used to get the "home" directory
531       * of a project; the directory which contains trunk's delta
532       * directories and the baseline, and the "info" meta-data
533       * directory.
534       *
535       * @returns
536       *     a string containing the absolute path.
537       *     DO NOT str_free or delete it.
538       *
539       * @note
540       *     It is a bug to call this method for anything other than a
541       *     trunk project.  Calling if for a branch will result in an
542       *     assert failure.
543       */
544     string_ty *home_path_get();
545 
546     /**
547       * The home_path_set method is used when creating a new project to
548       * remeber the directory the project beaselines and meta-data are
549       * stored within.
550       *
551       * @param dir
552       *     The absolute path of the directory in which to keep the
553       *     project.  To cope with automounters, directories are stored
554       *     as given, or are derived from the home directory in the
555       *     passwd file.  Within Aegis, pathnames have their symbolic
556       *     links resolved, and any comparison of paths is done on this
557       *     "system idea" of the pathname.
558       */
559     void home_path_set(string_ty *dir);
560     void home_path_set(const nstring &dir);
561 
562     // ----------  I  ------------------------------------------------------
563 
564     /**
565       * The info_path_get method is used to obtain the absolute path of
566       * the meta-data file for this project (branch).
567       *
568       * @returns
569       *     a string; do not str_free or delete it, because it is cached.
570       * @note
571       *     it is a bug to call this for anything but a top-level
572       *     (trunk) project.
573       */
574     string_ty *info_path_get();
575 
576     /**
577       * The is_a_trunk method is used to determine whether a project
578       * is a trunk branch (is the deepest ancestor) or a normal nested
579       * branch (has at least one ancestor branch).
580       *
581       * @returns
582       *     bool; true if is a trunk, false if is a branch
583       */
is_a_trunk()584     bool is_a_trunk() const { return (parent == 0); }
585 
586     // ----------  J  ------------------------------------------------------
587     // ----------  K  ------------------------------------------------------
588     // ----------  L  ------------------------------------------------------
589 
590     /**
591       * The list_inner method is used to append the branch names to the
592       * result list.  This is one step of building a complete list of
593       * projects.
594       *
595       * @param result
596       *     Append all project branch names to this list.
597       */
598     void list_inner(string_list_ty &result);
599 
600     /**
601       * The lock_prepare_everything method is used to take a resd-only
602       * lock of everything in the project: pstate, baseline, changes,
603       * and recurse into all active branches.
604       */
605     void lock_prepare_everything();
606 
607 private:
608     /**
609       * The lock_sync method is used to invalidate the project state
610       * data if the lock has been released and taken again.
611       *
612       * @note
613       *     it is a bug to call this for anything but a top-level
614       *     (trunk) project.
615       */
616     void lock_sync();
617 
618     // ----------  M  ------------------------------------------------------
619     // ----------  N  ------------------------------------------------------
620 
621 public:
622     /**
623       * The name_get method is used to get the name of the project.
624       *
625       * @returns
626       *     a string; the name of the project.
627       *     DO NOT str_free it.
628       */
629     string_ty *name_get() const;
630 
631     // ----------  O  ------------------------------------------------------
632     // ----------  P  ------------------------------------------------------
633 
634     /**
635       * The parent_branch_number_get method is used to get the branch
636       * (change) number of this branch in the parent branch.
637       *
638       * @note
639       *     This method is not meaningful for trunk projects (branches).
640       */
parent_branch_number_get()641     long parent_branch_number_get() const { return parent_bn; }
642 
643     /**
644       * The parent_get method is used to obtain the parent brach of this
645       * project.
646       *
647       * @returns
648       *     pointer to project; do not delete or project_free
649       */
parent_get()650     project *parent_get() { return (parent ? parent : this); }
651 
652     /**
653       * The pstate_get method is used to obtain the project state data.
654       *
655       * @returns
656       *     pointer to pstate_ty data; do not delete, it is cached.
657       * @note
658       *     it is a bug to call this for anything but a top-level
659       *     (trunk) project.
660       */
661     pstate_ty *pstate_get();
662 
663     /**
664       * The pstate_lock_prepare method is used to prepare to take a
665       * project pstate lock for this project, prior to lock_take() being
666       * called.
667       */
668     void pstate_lock_prepare();
669 
670     /**
671       * The pstate_path_get method is used to obtain the absolute path
672       * of the pstate (project state) file.
673       *
674       * @returns
675       *     a string; do not str_free or delete it, because it is cached.
676       * @note
677       *     it is a bug to call this for anything but a top-level
678       *     (trunk) project.
679       */
680     string_ty *pstate_path_get();
681 
682     /**
683       * The search_path_get method may be used to obtain the search path
684       * (list of progressively more out-of-date ancestor btranches)
685       * within which to search for files.
686       *
687       * @param result
688       *     Where to append the additional directories.
689       * @param resolve
690       *     Whether or not to expand synbolic links within paths.
691       */
692     void search_path_get(string_list_ty *result, bool resolve);
693 
694     /**
695       * The search_path_get method may be used to obtain the search path
696       * (list of progressively more out-of-date ancestor btranches)
697       * within which to search for files.
698       *
699       * @param result
700       *     Where to append the additional directories.
701       * @param resolve
702       *     Whether or not to expand synbolic links within paths.
703       */
704     void search_path_get(nstring_list &result, bool resolve);
705 
706     /**
707       * The pstate_write method is used to write out the project state
708       * data into the meta-data directory tree.
709       */
710     void pstate_write();
711 
712     // ----------  Q  ------------------------------------------------------
713     // ----------  R  ------------------------------------------------------
714     // ----------  S  ------------------------------------------------------
715     // ----------  T  ------------------------------------------------------
716 
717     /**
718       * The trunk_get method is used to find the trunk project of this
719       * project, then top-level branch of this project.
720       */
721     project *trunk_get();
722 
723     // ----------  U ------------------------------------------------------
724     // ----------  V  ------------------------------------------------------
725     // ----------  W  ------------------------------------------------------
726     // ----------  X  ------------------------------------------------------
727     // ----------  Y  ------------------------------------------------------
728     // ----------  Z  ------------------------------------------------------
729     // ---------------------------------------------------------------------
730 
731     /**
732       * The uid_get method is used to obtain the Unix user id of the
733       * project owner.
734       */
735     int uid_get();
736 
737     /**
738       * The umask_get method is used to obtain the file creation mode
739       * mask for this project.
740       */
741     int umask_get();
742 
743 public: // during transition
744     long            reference_count;
745 
746 private:
747     /**
748       * The name instance variable is used to remember the name of this
749       * project.
750       */
751     string_ty *name;
752 
753     /**
754       * The home_path instance variable is used to remember the "home"
755       * directory of a project; the directory which contains trunk's
756       * delta directories and the baseline, and the "info" meta-data
757       * directory.
758       *
759       * @note
760       *     Never access this instance variable directly, always go via
761       *     home_path_get() in case it hasn't been calculated yet.
762       */
763     string_ty *home_path;
764 
765     /**
766       * The baseline_path_unresolved instance variable is used to
767       * remember the absolute path of this project's (branch's) baseline
768       * directory.  It has not had is symbolic links resolved.  All
769       * access is via the baseline_path_get method, which takes care of
770       * calculating it on demand.
771       */
772     string_ty *baseline_path_unresolved;
773 
774     /**
775       * The baseline_path_unresolved instance variable is used to
776       * remember the absolute path of this project's (branch's) baseline
777       * directory.  It has not had is symbolic links resolved.  All
778       * access is via the baseline_path_get method, which takes care of
779       * calculating it on demand.
780       */
781     string_ty *baseline_path;
782 
783     /**
784       * The change2time_stp instance variable is used to remember for
785       * each change the completion timestamp.  All access are via the
786       * change_completion_timestamp_maybe_cached method, which take
787       * care of calculating it on demand.
788       */
789     itab_ty *change2time_stp;
790 
791     /**
792       * The history_path is used to remember the absolute path of the
793       * distory directory.  The calculation is deferred until needed.
794       * Always use the history_path_get method, never access this
795       * instance variable directly.
796       */
797     string_ty *history_path;
798 
799     /**
800       * The info_path instance variable is used to remember the location
801       * of the meta-data file for this project (branch).  Never access
802       * the info_path variable directly, always go via the info_path_get
803       * method.
804       */
805     string_ty *info_path;
806 
807     /**
808       * The pstate_path instance variable is used to remember the
809       * absolute path of the pstate (project state) file.  It is
810       * calculated as needed.  Never access this instance variable
811       * directly, always go via the pstate_path_get method.
812       */
813     string_ty *pstate_path;
814 
815     /**
816       * The changes_path instance variable is used to remember the
817       * absolute path of the directory containing change set meta-data.
818       * It is calculated as needed.  Never access this instance variable
819       * directly, always go via the changes_path_get method.
820       */
821     string_ty *changes_path;
822 
823     /**
824       * The pstate_data instance variable is used to remember the
825       * project state data.  It is calculated as needed.  Never
826       * access this instance variable directly, always go via the
827       * pstate_get method.
828       */
829     pstate_ty *pstate_data;
830 
831     /**
832       * The is_a_new_file instance variable is used to remember whether
833       * the pstate file is a new file which has to be created.
834       */
835     bool is_a_new_file;
836 
837     /**
838       * The lock_magic instance variable is used to remember the last
839       * time the lock was taken.  If the lock_sync function returns
840       * different, it means we have to invalidate all our project data
841       * and read it in again, because something could have changed.
842       * Only every accessed by the lock_sync ethod.
843       */
844     long lock_magic;
845 
846     /**
847       * The pcp instance variable is used to remember the change object
848       * representing this branch's state.
849       *
850       * @note
851       *     Never access this instance variable directly, event from a
852       *     project method, always go via the change_get() method in
853       *     case it has not been calculated yet.
854       */
855     change::pointer pcp;
856 
857     /**
858       * The uid instance variable is used to remember the Unix user id
859       * for the project owner.  This is set by the get_the_owner method.
860       */
861     int uid;
862 
863     /**
864       * The gid instance variable is used to remember the Unix group id
865       * for the project owner.  This is set by the get_the_owner method.
866       */
867     int gid;
868 
869     /**
870       * The parent instance variable is used to remember the project
871       * which this project is a branch of.  If it is NULL, then this is
872       * a trunk project.
873       */
874     project *parent;
875 
876     /**
877       * The parent_bn instance variable is used to remember the change
878       * (branch) number of this project relative to the parent branch.
879       * If it is TRUNK_BRANCH_NUMER, then this is a trunk project.
880       */
881     long parent_bn;
882 
883     /**
884       * The file_list instance variable is used to remember the list
885       * of files in the project, one list for each style of view path.
886       * Never access this instance variable directly, always go via the
887       * file_list_get method, they are calculated on demand.
888       */
889     struct string_list_ty *file_list[view_path_MAX];
890 
891     /**
892       * The file_by_uuid instance variable is used to remember a symbol
893       * table of files indexed by UUID (or by file name if your project
894       * has any files without a UUID for backwards compatibility).
895       *
896       * This instance variable shall always be accessed via the
897       * find_file_by_uuid method.  The tables are calculated on demand
898       * and cached.
899       */
900     struct symtab_ty *file_by_uuid[view_path_MAX];
901 
902     //
903     // If you add an instance variable to this class, make sure you
904     // dispose of it in the destructor and initialize in in the
905     // constructor.  Both may be found in libaegis/project.cc
906     //
907 
908 private:
909     /**
910       * The up instance variable is used to remember the user (and
911       * group) which owns this project.
912       */
913     user_ty::pointer up;
914 
915     /**
916       * The off_limits instance variable is used to remember when
917       * a project is inaccessable to the executing user.  This
918       * flag is normally false, but it will be set to true by
919       * project::bind_existing for projects which are inaccessable.
920       */
921     bool off_limits;
922 
923     /**
924       * The default constructor.
925       *
926       * Do not use this method.  It is not defined.  Projects will
927       * always have a name, it it shall always be supplied to the
928       * constructor.
929       */
930     project();
931 
932     /**
933       * The copy constructor.  Do not use.
934       *
935       * The prefereed mechanism is to use the reference counting
936       * provided the the project class (see below) smart pointer.
937       */
938     project(const project &);
939 
940     /**
941       * The assignment operator.  Do not use.
942       *
943       * The prefereed mechanism is to use the reference counting
944       * provided the the project class (see below) smart pointer.
945       */
946     project &operator=(const project &);
947 };
948 
949 project *project_alloc(string_ty *name);
950 
951 inline DEPRECATED void
project_bind_existing(project * pp)952 project_bind_existing(project *pp)
953 {
954     pp->bind_existing();
955 }
956 
957 inline DEPRECATED bool
project_bind_existing_errok(project * pp)958 project_bind_existing_errok(project *pp)
959 {
960     return pp->bind_existing_errok();
961 }
962 
963 inline DEPRECATED project *
project_bind_branch(project * ppp,change::pointer bp)964 project_bind_branch(project *ppp, change::pointer bp)
965 {
966     return ppp->bind_branch(bp);
967 }
968 
969 inline DEPRECATED void
project_bind_new(project * pp)970 project_bind_new(project *pp)
971 {
972     pp->bind_new();
973 }
974 
975 void project_list_get(struct string_list_ty *);
976 
977 inline DEPRECATED void
project_list_inner(struct string_list_ty * result,project * pp)978 project_list_inner(struct string_list_ty *result, project *pp)
979 {
980     pp->list_inner(*result);
981 }
982 
983 inline DEPRECATED project *
project_find_branch(project * pp,const char * number)984 project_find_branch(project *pp, const char *number)
985 {
986     return pp->find_branch(number);
987 }
988 
989 void project_free(project *);
990 
991 inline nstring
project_name_get(project * pp)992 project_name_get(project *pp)
993 {
994     return nstring(pp->name_get());
995 }
996 
997 project *project_copy(project *);
998 
999 inline DEPRECATED change::pointer
project_change_get(project * pp)1000 project_change_get(project *pp)
1001 {
1002     return pp->change_get();
1003 }
1004 
1005 inline DEPRECATED string_ty *
project_home_path_get(project * pp)1006 project_home_path_get(project *pp)
1007 {
1008     return pp->home_path_get();
1009 }
1010 
1011 string_ty *project_Home_path_get(project *);
1012 string_ty *project_top_path_get(project *, int);
1013 
1014 /**
1015   * The project_rss_path_get function is used to get the path of the RSS
1016   * directory for the given project.
1017   *
1018   * @param pp
1019   *     The project in question
1020   * @param resolve
1021   *     Whether or not to resolve symlinks in the path.
1022   * @returns
1023   *     a string containing the absolute path
1024   */
1025 nstring project_rss_path_get(project *pp, bool resolve = false);
1026 
1027 inline DEPRECATED void
project_home_path_set(project * pp,string_ty * dir)1028 project_home_path_set(project *pp, string_ty *dir)
1029 {
1030     pp->home_path_set(dir);
1031 }
1032 
1033 inline DEPRECATED string_ty *
1034 project_baseline_path_get(project *pp, bool resolve = false)
1035 {
1036     return pp->baseline_path_get(resolve);
1037 }
1038 
1039 inline DEPRECATED string_ty *
project_history_path_get(project * pp)1040 project_history_path_get(project *pp)
1041 {
1042     return pp->history_path_get();
1043 }
1044 
1045 /**
1046   * The project_history_filename_get function is used to determine the
1047   * absolute path pf the file used to contain the history of the given file.
1048   *
1049   * @returns
1050   *     a pointer to a string.  You are required to str_free this string
1051   *     when you are done with it.
1052   */
1053 string_ty *project_history_filename_get(project *, struct fstate_src_ty *);
1054 
1055 inline DEPRECATED string_ty *
project_info_path_get(project * pp)1056 project_info_path_get(project *pp)
1057 {
1058     return pp->info_path_get();
1059 }
1060 
1061 inline DEPRECATED string_ty *
project_changes_path_get(project * pp)1062 project_changes_path_get(project *pp)
1063 {
1064     return pp->changes_path_get();
1065 }
1066 
1067 DEPRECATED
1068 string_ty *project_change_path_get(project *, long);
1069 
1070 inline DEPRECATED string_ty *
project_pstate_path_get(project * pp)1071 project_pstate_path_get(project *pp)
1072 {
1073     return pp->pstate_path_get();
1074 }
1075 
1076 inline DEPRECATED pstate_ty *
project_pstate_get(project * pp)1077 project_pstate_get(project *pp)
1078 {
1079     return pp->pstate_get();
1080 }
1081 
1082 inline DEPRECATED void
project_pstate_write(project * pp)1083 project_pstate_write(project *pp)
1084 {
1085     pp->pstate_write();
1086 }
1087 
1088 void project_pstate_write_top(project *);
1089 
1090 inline DEPRECATED void
project_pstate_lock_prepare(project * pp)1091 project_pstate_lock_prepare(project *pp)
1092 {
1093     pp->pstate_lock_prepare();
1094 }
1095 
1096 void project_pstate_lock_prepare_top(project *);
1097 void project_baseline_read_lock_prepare(project *);
1098 void project_baseline_write_lock_prepare(project *);
1099 void project_history_lock_prepare(project *);
1100 void project_error(project *, struct sub_context_ty *, const char *);
1101 void project_fatal(project *, struct sub_context_ty *, const char *)
1102     NORETURN;
1103 void project_verbose(project *, struct sub_context_ty *, const char *);
1104 void project_change_append(project *, long, int);
1105 void project_change_delete(project *, long);
1106 int project_change_number_in_use(project *, long);
1107 nstring project_version_short_get(project *);
1108 nstring project_version_get(project *);
1109 
1110 inline DEPRECATED int
project_uid_get(project * pp)1111 project_uid_get(project *pp)
1112 {
1113     return pp->uid_get();
1114 }
1115 
1116 inline DEPRECATED int
project_gid_get(project * pp)1117 project_gid_get(project *pp)
1118 {
1119     return pp->gid_get();
1120 }
1121 
1122 user_ty::pointer project_user(project *);
1123 void project_become(project *);
1124 void project_become_undo(project *pp);
1125 long project_next_test_number_get(project *);
1126 int project_is_readable(project *);
1127 long project_minimum_change_number_get(project *);
1128 void project_minimum_change_number_set(project *, long);
1129 bool project_reuse_change_numbers_get(project *);
1130 void project_reuse_change_numbers_set(project *, bool);
1131 long project_minimum_branch_number_get(project *);
1132 void project_minimum_branch_number_set(project *, long);
1133 bool project_skip_unlucky_get(project *);
1134 void project_skip_unlucky_set(project *, bool);
1135 bool project_compress_database_get(project *);
1136 void project_compress_database_set(project *, bool);
1137 int project_develop_end_action_get(project *);
1138 void project_develop_end_action_set(project *, int);
1139 bool project_protect_development_directory_get(project *);
1140 void project_protect_development_directory_set(project *, bool);
1141 
1142 int break_up_version_string(const char *, long *, int, int *, int);
1143 void extract_version_from_project_name(string_ty **, long *, int, int *);
1144 int project_name_ok(string_ty *);
1145 
1146 pconf_ty *project_pconf_get(project *);
1147 
1148 /**
1149   * The project_new_branch function is used to create new branches.
1150   *
1151   * @param pp
1152   *     The project to create the branch below.
1153   * @param up
1154   *     The authorised user requesting the new branch.
1155   * @param change_number
1156   *     The change number to use for the new branch.
1157   * @param topdir
1158   *     The change (branch) directory, It is in the same place as the
1159   *     rest of the project, unless otherwise specified (i.e. not NULL).
1160   *     This makes it easy to collect the whole project tree, branches,
1161   *     info and all, in a simple tar or cpio command for archiving or
1162   *     moving.
1163   * @param reason
1164   *     The reason the user gave on the command line, or NULL for no
1165   *     reason to be attached to the change's history.
1166   * @returns
1167   *     A pointer to the new project represented by the new branch.
1168   */
1169 project *project_new_branch(project *pp, user_ty::pointer up,
1170     long change_number, string_ty *topdir = 0, string_ty *reason = 0);
1171 
1172 inline DEPRECATED void
project_file_list_invalidate(project * pp)1173 project_file_list_invalidate(project *pp)
1174 {
1175     pp->file_list_invalidate();
1176 }
1177 
1178 string_ty *project_brief_description_get(project *);
1179 
1180 /**
1181   * The project_uuid_find function is used to locate a change given its UUID.
1182   *
1183   * @param pp
1184   *     The project to search.  Will rewind to the trunk project
1185   *     before the search commences.
1186   * @param uuid
1187   *     The change UUID to search for.
1188   * @returns
1189   *     a pointer to the change with th given UUID, or NULL if no change
1190   *     has the given UUID.
1191   */
1192 change::pointer project_uuid_find(project *pp, string_ty *uuid);
1193 
1194 // vim: set ts=8 sw=4 et :
1195 #endif // PROJECT_H
1196